Mesa (master): amd/common: Add support for modifiers.
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Fri Nov 13 03:44:46 UTC 2020
Module: Mesa
Branch: master
Commit: 0833dd7d124bfd94161bff15e5b4293987920fce
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=0833dd7d124bfd94161bff15e5b4293987920fce
Author: Bas Nieuwenhuizen <bas at basnieuwenhuizen.nl>
Date: Tue Oct 8 10:21:30 2019 +0200
amd/common: Add support for modifiers.
Reviewed-by: Marek Olšák <marek.olsak at amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6176>
---
src/amd/common/ac_surface.c | 452 ++++++++++++++++++++++++++----
src/amd/common/ac_surface.h | 33 +++
src/amd/vulkan/radv_image.c | 6 +-
src/gallium/drivers/radeonsi/si_texture.c | 2 +
4 files changed, 437 insertions(+), 56 deletions(-)
diff --git a/src/amd/common/ac_surface.c b/src/amd/common/ac_surface.c
index 9eddd3cb7c2..6218fbea3f3 100644
--- a/src/amd/common/ac_surface.c
+++ b/src/amd/common/ac_surface.c
@@ -32,11 +32,13 @@
#include "addrlib/src/amdgpu_asic_addr.h"
#include "amd_family.h"
#include "drm-uapi/amdgpu_drm.h"
+#include "drm-uapi/drm_fourcc.h"
#include "sid.h"
#include "util/hash_table.h"
#include "util/macros.h"
#include "util/simple_mtx.h"
#include "util/u_atomic.h"
+#include "util/format/u_format.h"
#include "util/u_math.h"
#include "util/u_memory.h"
@@ -326,6 +328,259 @@ static uint32_t *ac_compute_dcc_retile_map(struct ac_addrlib *addrlib,
return dcc_retile_map;
}
+bool ac_modifier_has_dcc(uint64_t modifier)
+{
+ return IS_AMD_FMT_MOD(modifier) && AMD_FMT_MOD_GET(DCC, modifier);
+}
+
+bool ac_modifier_has_dcc_retile(uint64_t modifier)
+{
+ return IS_AMD_FMT_MOD(modifier) && AMD_FMT_MOD_GET(DCC_RETILE, modifier);
+}
+
+static
+AddrSwizzleMode ac_modifier_gfx9_swizzle_mode(uint64_t modifier)
+{
+ if (modifier == DRM_FORMAT_MOD_LINEAR)
+ return ADDR_SW_LINEAR;
+
+ return AMD_FMT_MOD_GET(TILE, modifier);
+}
+static void
+ac_modifier_fill_dcc_params(uint64_t modifier, struct radeon_surf *surf,
+ ADDR2_COMPUTE_SURFACE_INFO_INPUT *surf_info)
+{
+ assert(ac_modifier_has_dcc(modifier));
+
+ surf_info->flags.metaRbUnaligned = 0;
+ if (AMD_FMT_MOD_GET(DCC_RETILE, modifier)) {
+ surf_info->flags.metaPipeUnaligned = 0;
+ } else {
+ surf_info->flags.metaPipeUnaligned = !AMD_FMT_MOD_GET(DCC_PIPE_ALIGN, modifier);
+ }
+
+ surf->u.gfx9.dcc.independent_64B_blocks = AMD_FMT_MOD_GET(DCC_INDEPENDENT_64B, modifier);
+ surf->u.gfx9.dcc.independent_128B_blocks = AMD_FMT_MOD_GET(DCC_INDEPENDENT_128B, modifier);
+ surf->u.gfx9.dcc.max_compressed_block_size = AMD_FMT_MOD_GET(DCC_MAX_COMPRESSED_BLOCK, modifier);
+}
+
+bool ac_is_modifier_supported(const struct radeon_info *info,
+ const struct ac_modifier_options *options,
+ enum pipe_format format,
+ uint64_t modifier)
+{
+
+ if (util_format_is_compressed(format) ||
+ util_format_is_depth_or_stencil(format) ||
+ util_format_get_blocksize(format) > 8)
+ return false;
+
+ if (info->chip_class < GFX9)
+ return false;
+
+ if(modifier == DRM_FORMAT_MOD_LINEAR)
+ return true;
+
+ if (util_format_get_num_planes(format) > 1)
+ return false;
+
+ uint32_t allowed_swizzles = 0xFFFFFFFF;
+ switch(info->chip_class) {
+ case GFX9:
+ allowed_swizzles = ac_modifier_has_dcc(modifier) ? 0x06000000 : 0x06660660;
+ break;
+ case GFX10:
+ case GFX10_3:
+ allowed_swizzles = ac_modifier_has_dcc(modifier) ? 0x08000000 : 0x0E660660;
+ break;
+ default:
+ return false;
+ }
+
+ if (!((1u << ac_modifier_gfx9_swizzle_mode(modifier)) & allowed_swizzles))
+ return false;
+
+ if (ac_modifier_has_dcc(modifier)) {
+ if (!info->has_graphics)
+ return false;
+
+ if (!options->dcc)
+ return false;
+
+ if (ac_modifier_has_dcc_retile(modifier) && !options->dcc_retile)
+ return false;
+ }
+
+ return true;
+}
+
+bool ac_get_supported_modifiers(const struct radeon_info *info,
+ const struct ac_modifier_options *options,
+ enum pipe_format format,
+ unsigned *mod_count,
+ uint64_t *mods)
+{
+ unsigned current_mod = 0;
+
+#define ADD_MOD(name) \
+ if (ac_is_modifier_supported(info, options, format, (name))) { \
+ if (mods && current_mod < *mod_count) \
+ mods[current_mod] = (name); \
+ ++current_mod; \
+ }
+
+ /* The modifiers have to be added in descending order of estimated
+ * performance. The drivers will prefer modifiers that come earlier
+ * in the list. */
+ switch (info->chip_class) {
+ case GFX9: {
+ unsigned pipe_xor_bits = MIN2(G_0098F8_NUM_PIPES(info->gb_addr_config) +
+ G_0098F8_NUM_SHADER_ENGINES_GFX9(info->gb_addr_config), 8);
+ unsigned bank_xor_bits = MIN2(G_0098F8_NUM_BANKS(info->gb_addr_config), 8 - pipe_xor_bits);
+ unsigned pipes = G_0098F8_NUM_PIPES(info->gb_addr_config);
+ unsigned rb = G_0098F8_NUM_RB_PER_SE(info->gb_addr_config) +
+ G_0098F8_NUM_SHADER_ENGINES_GFX9(info->gb_addr_config);
+
+ uint64_t common_dcc = AMD_FMT_MOD_SET(DCC, 1) |
+ AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
+ AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
+ AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, info->has_dcc_constant_encode) |
+ AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+ AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
+ AMD_FMT_MOD_SET(RB, rb);
+
+ ADD_MOD(AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
+ AMD_FMT_MOD_SET(DCC_PIPE_ALIGN, 1) |
+ common_dcc |
+ AMD_FMT_MOD_SET(PIPE, pipes))
+
+ ADD_MOD(AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
+ AMD_FMT_MOD_SET(DCC_PIPE_ALIGN, 1) |
+ common_dcc |
+ AMD_FMT_MOD_SET(PIPE, pipes))
+
+ if (util_format_get_blocksize(format) == 4) {
+ if (info->num_render_backends == 1) {
+ ADD_MOD(AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
+ common_dcc);
+ }
+
+
+ ADD_MOD(AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
+ AMD_FMT_MOD_SET(DCC_RETILE, 1) |
+ common_dcc |
+ AMD_FMT_MOD_SET(PIPE, pipes))
+ }
+
+
+ ADD_MOD(AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
+ AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+ AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits));
+
+ ADD_MOD(AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
+ AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+ AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits));
+
+ ADD_MOD(AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
+
+ ADD_MOD(AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
+
+ ADD_MOD(DRM_FORMAT_MOD_LINEAR)
+ break;
+ }
+ case GFX10:
+ case GFX10_3: {
+ bool rbplus = info->chip_class >= GFX10_3;
+ unsigned pipe_xor_bits = G_0098F8_NUM_PIPES(info->gb_addr_config);
+ unsigned pkrs = rbplus ? G_0098F8_NUM_PKRS(info->gb_addr_config) : 0;
+
+ unsigned version = rbplus ? AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS : AMD_FMT_MOD_TILE_VER_GFX10;
+ uint64_t common_dcc = AMD_FMT_MOD_SET(TILE_VERSION, version) |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
+ AMD_FMT_MOD_SET(DCC, 1) |
+ AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
+ AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+ AMD_FMT_MOD_SET(PACKERS, pkrs);
+
+ ADD_MOD(AMD_FMT_MOD | common_dcc |
+ AMD_FMT_MOD_SET(DCC_PIPE_ALIGN, 1) |
+ AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
+ AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_128B))
+
+ if (info->family == CHIP_NAVI12 || info->family == CHIP_NAVI14 || info->chip_class >= GFX10_3) {
+ bool independent_128b = info->chip_class >= GFX10_3;
+
+ if (info->num_render_backends == 1) {
+ ADD_MOD(AMD_FMT_MOD | common_dcc |
+ AMD_FMT_MOD_SET(DCC_PIPE_ALIGN, 1) |
+ AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
+ AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, independent_128b) |
+ AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B))
+ }
+
+ ADD_MOD(AMD_FMT_MOD | common_dcc |
+ AMD_FMT_MOD_SET(DCC_RETILE, 1) |
+ AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
+ AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, independent_128b) |
+ AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B))
+ }
+
+ ADD_MOD(AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE_VERSION, version) |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
+ AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+ AMD_FMT_MOD_SET(PACKERS, pkrs))
+
+ ADD_MOD(AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
+ AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits))
+
+ if (util_format_get_blocksize(format) != 4) {
+ ADD_MOD(AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
+ }
+
+ ADD_MOD(AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
+
+ ADD_MOD(DRM_FORMAT_MOD_LINEAR)
+ break;
+ }
+ default:
+ break;
+ }
+
+#undef ADD_MOD
+
+ if (!mods) {
+ *mod_count = current_mod;
+ return true;
+ }
+
+ bool complete = current_mod <= *mod_count;
+ *mod_count = MIN2(*mod_count, current_mod);
+ return complete;
+}
+
static void *ADDR_API allocSysMem(const ADDR_ALLOCSYSMEM_INPUT *pInput)
{
return malloc(pInput->sizeInBytes);
@@ -695,6 +950,13 @@ static bool get_display_flag(const struct ac_surf_config *config, const struct r
unsigned num_channels = config->info.num_channels;
unsigned bpe = surf->bpe;
+ /* With modifiers the kernel is in charge of whether it is displayable.
+ * We need to ensure at least 32 pixels pitch alignment, but this is
+ * always the case when the blocksize >= 4K.
+ */
+ if (surf->modifier != DRM_FORMAT_MOD_INVALID)
+ return false;
+
if (!config->is_3d && !config->is_cube && !(surf->flags & RADEON_SURF_Z_OR_SBUFFER) &&
surf->flags & RADEON_SURF_SCANOUT && config->info.samples <= 1 && surf->blk_w <= 2 &&
surf->blk_h == 1) {
@@ -1497,7 +1759,9 @@ static int gfx9_compute_miptree(struct ac_addrlib *addrlib, const struct radeon_
is_dcc_supported_by_CB(info, in->swizzleMode) &&
(!in->flags.display ||
is_dcc_supported_by_DCN(info, config, surf, !in->flags.metaRbUnaligned,
- !in->flags.metaPipeUnaligned))) {
+ !in->flags.metaPipeUnaligned)) &&
+ (surf->modifier == DRM_FORMAT_MOD_INVALID ||
+ ac_modifier_has_dcc(surf->modifier))) {
ADDR2_COMPUTE_DCCINFO_INPUT din = {0};
ADDR2_COMPUTE_DCCINFO_OUTPUT dout = {0};
ADDR2_META_MIP_INFO meta_mip_info[RADEON_SURF_MAX_LEVELS] = {0};
@@ -1579,7 +1843,8 @@ static int gfx9_compute_miptree(struct ac_addrlib *addrlib, const struct radeon_
surf->u.gfx9.dcc_pitch_max = dout.pitch - 1;
/* Compute displayable DCC. */
- if (in->flags.display && surf->num_dcc_levels && info->use_display_dcc_with_retile_blit) {
+ if (((in->flags.display && info->use_display_dcc_with_retile_blit) ||
+ ac_modifier_has_dcc_retile(surf->modifier)) && surf->num_dcc_levels) {
/* Compute displayable DCC info. */
din.dccKeyFlags.pipeAligned = 0;
din.dccKeyFlags.rbAligned = 0;
@@ -1866,72 +2131,86 @@ static int gfx9_compute_surface(struct ac_addrlib *addrlib, const struct radeon_
AddrSurfInfoIn.flags.metaPipeUnaligned = 0;
AddrSurfInfoIn.flags.metaRbUnaligned = 0;
- /* Optimal values for the L2 cache. */
- if (info->chip_class == GFX9) {
- surf->u.gfx9.dcc.independent_64B_blocks = 1;
- surf->u.gfx9.dcc.independent_128B_blocks = 0;
- surf->u.gfx9.dcc.max_compressed_block_size = V_028C78_MAX_BLOCK_SIZE_64B;
- } else if (info->chip_class >= GFX10) {
- surf->u.gfx9.dcc.independent_64B_blocks = 0;
- surf->u.gfx9.dcc.independent_128B_blocks = 1;
- surf->u.gfx9.dcc.max_compressed_block_size = V_028C78_MAX_BLOCK_SIZE_128B;
- }
-
- if (AddrSurfInfoIn.flags.display) {
- /* The display hardware can only read DCC with RB_ALIGNED=0 and
- * PIPE_ALIGNED=0. PIPE_ALIGNED really means L2CACHE_ALIGNED.
- *
- * The CB block requires RB_ALIGNED=1 except 1 RB chips.
- * PIPE_ALIGNED is optional, but PIPE_ALIGNED=0 requires L2 flushes
- * after rendering, so PIPE_ALIGNED=1 is recommended.
- */
- if (info->use_display_dcc_unaligned) {
- AddrSurfInfoIn.flags.metaPipeUnaligned = 1;
- AddrSurfInfoIn.flags.metaRbUnaligned = 1;
+ if (ac_modifier_has_dcc(surf->modifier)) {
+ ac_modifier_fill_dcc_params(surf->modifier, surf, &AddrSurfInfoIn);
+ } else {
+ /* Optimal values for the L2 cache. */
+ if (info->chip_class == GFX9) {
+ surf->u.gfx9.dcc.independent_64B_blocks = 1;
+ surf->u.gfx9.dcc.independent_128B_blocks = 0;
+ surf->u.gfx9.dcc.max_compressed_block_size = V_028C78_MAX_BLOCK_SIZE_64B;
+ } else if (info->chip_class >= GFX10) {
+ surf->u.gfx9.dcc.independent_64B_blocks = 0;
+ surf->u.gfx9.dcc.independent_128B_blocks = 1;
+ surf->u.gfx9.dcc.max_compressed_block_size = V_028C78_MAX_BLOCK_SIZE_128B;
}
- /* Adjust DCC settings to meet DCN requirements. */
- if (info->use_display_dcc_unaligned || info->use_display_dcc_with_retile_blit) {
- /* Only Navi12/14 support independent 64B blocks in L2,
- * but without DCC image stores.
+ if (AddrSurfInfoIn.flags.display) {
+ /* The display hardware can only read DCC with RB_ALIGNED=0 and
+ * PIPE_ALIGNED=0. PIPE_ALIGNED really means L2CACHE_ALIGNED.
+ *
+ * The CB block requires RB_ALIGNED=1 except 1 RB chips.
+ * PIPE_ALIGNED is optional, but PIPE_ALIGNED=0 requires L2 flushes
+ * after rendering, so PIPE_ALIGNED=1 is recommended.
*/
- if (info->family == CHIP_NAVI12 || info->family == CHIP_NAVI14) {
- surf->u.gfx9.dcc.independent_64B_blocks = 1;
- surf->u.gfx9.dcc.independent_128B_blocks = 0;
- surf->u.gfx9.dcc.max_compressed_block_size = V_028C78_MAX_BLOCK_SIZE_64B;
+ if (info->use_display_dcc_unaligned) {
+ AddrSurfInfoIn.flags.metaPipeUnaligned = 1;
+ AddrSurfInfoIn.flags.metaRbUnaligned = 1;
}
- if (info->chip_class >= GFX10_3) {
- surf->u.gfx9.dcc.independent_64B_blocks = 1;
- surf->u.gfx9.dcc.independent_128B_blocks = 1;
- surf->u.gfx9.dcc.max_compressed_block_size = V_028C78_MAX_BLOCK_SIZE_64B;
+ /* Adjust DCC settings to meet DCN requirements. */
+ if (info->use_display_dcc_unaligned || info->use_display_dcc_with_retile_blit) {
+ /* Only Navi12/14 support independent 64B blocks in L2,
+ * but without DCC image stores.
+ */
+ if (info->family == CHIP_NAVI12 || info->family == CHIP_NAVI14) {
+ surf->u.gfx9.dcc.independent_64B_blocks = 1;
+ surf->u.gfx9.dcc.independent_128B_blocks = 0;
+ surf->u.gfx9.dcc.max_compressed_block_size = V_028C78_MAX_BLOCK_SIZE_64B;
+ }
+
+ if (info->chip_class >= GFX10_3) {
+ surf->u.gfx9.dcc.independent_64B_blocks = 1;
+ surf->u.gfx9.dcc.independent_128B_blocks = 1;
+ surf->u.gfx9.dcc.max_compressed_block_size = V_028C78_MAX_BLOCK_SIZE_64B;
+ }
}
}
}
- switch (mode) {
- case RADEON_SURF_MODE_LINEAR_ALIGNED:
- assert(config->info.samples <= 1);
- assert(!(surf->flags & RADEON_SURF_Z_OR_SBUFFER));
- AddrSurfInfoIn.swizzleMode = ADDR_SW_LINEAR;
- break;
+ if (surf->modifier == DRM_FORMAT_MOD_INVALID) {
+ switch (mode) {
+ case RADEON_SURF_MODE_LINEAR_ALIGNED:
+ assert(config->info.samples <= 1);
+ assert(!(surf->flags & RADEON_SURF_Z_OR_SBUFFER));
+ AddrSurfInfoIn.swizzleMode = ADDR_SW_LINEAR;
+ break;
- case RADEON_SURF_MODE_1D:
- case RADEON_SURF_MODE_2D:
- if (surf->flags & RADEON_SURF_IMPORTED ||
- (info->chip_class >= GFX10 && surf->flags & RADEON_SURF_FORCE_SWIZZLE_MODE)) {
- AddrSurfInfoIn.swizzleMode = surf->u.gfx9.surf.swizzle_mode;
+ case RADEON_SURF_MODE_1D:
+ case RADEON_SURF_MODE_2D:
+ if (surf->flags & RADEON_SURF_IMPORTED ||
+ (info->chip_class >= GFX10 && surf->flags & RADEON_SURF_FORCE_SWIZZLE_MODE)) {
+ AddrSurfInfoIn.swizzleMode = surf->u.gfx9.surf.swizzle_mode;
+ break;
+ }
+
+ r = gfx9_get_preferred_swizzle_mode(addrlib->handle, surf, &AddrSurfInfoIn, false,
+ &AddrSurfInfoIn.swizzleMode);
+ if (r)
+ return r;
break;
+
+ default:
+ assert(0);
}
+ } else {
+ /* We have a valid and required modifier here. */
- r = gfx9_get_preferred_swizzle_mode(addrlib->handle, surf, &AddrSurfInfoIn, false,
- &AddrSurfInfoIn.swizzleMode);
- if (r)
- return r;
- break;
+ assert(!compressed);
+ assert(!ac_modifier_has_dcc(surf->modifier) ||
+ !(surf->flags & RADEON_SURF_DISABLE_DCC));
- default:
- assert(0);
+ AddrSurfInfoIn.swizzleMode = ac_modifier_gfx9_swizzle_mode(surf->modifier);
}
surf->u.gfx9.resource_type = AddrSurfInfoIn.resourceType;
@@ -2013,7 +2292,9 @@ static int gfx9_compute_surface(struct ac_addrlib *addrlib, const struct radeon_
AddrSurfInfoIn.flags.color && !surf->is_linear &&
surf->surf_alignment >= 64 * 1024 && /* 64KB tiling */
!(surf->flags & (RADEON_SURF_DISABLE_DCC | RADEON_SURF_FORCE_SWIZZLE_MODE |
- RADEON_SURF_FORCE_MICRO_TILE_MODE))) {
+ RADEON_SURF_FORCE_MICRO_TILE_MODE)) &&
+ (surf->modifier == DRM_FORMAT_MOD_INVALID ||
+ ac_modifier_has_dcc(surf->modifier))) {
/* Validate that DCC is enabled if DCN can do it. */
if ((info->use_display_dcc_unaligned || info->use_display_dcc_with_retile_blit) &&
AddrSurfInfoIn.flags.display && surf->bpe == 4) {
@@ -2316,6 +2597,9 @@ bool ac_surface_set_umd_metadata(const struct radeon_info *info, struct radeon_s
uint32_t *desc = &metadata[2];
uint64_t offset;
+ if (surf->modifier != DRM_FORMAT_MOD_INVALID)
+ return true;
+
if (info->chip_class >= GFX9)
offset = surf->u.gfx9.surf_offset;
else
@@ -2492,3 +2776,61 @@ void ac_surface_override_offset_stride(const struct radeon_info *info, struct ra
if (surf->display_dcc_offset)
surf->display_dcc_offset += offset;
}
+
+unsigned ac_surface_get_nplanes(const struct radeon_surf *surf)
+{
+ if (surf->modifier == DRM_FORMAT_MOD_INVALID)
+ return 1;
+ else if (surf->display_dcc_offset)
+ return 3;
+ else if (surf->dcc_offset)
+ return 2;
+ else
+ return 1;
+}
+
+uint64_t ac_surface_get_plane_offset(enum chip_class chip_class,
+ const struct radeon_surf *surf,
+ unsigned plane, unsigned layer)
+{
+ switch (plane) {
+ case 0:
+ if (chip_class >= GFX9) {
+ return surf->u.gfx9.surf_offset +
+ layer * surf->u.gfx9.surf_slice_size;
+ } else {
+ return surf->u.legacy.level[0].offset +
+ layer * (uint64_t)surf->u.legacy.level[0].slice_size_dw * 4;
+ }
+ case 1:
+ assert(!layer);
+ return surf->display_dcc_offset ?
+ surf->display_dcc_offset : surf->dcc_offset;
+ case 2:
+ assert(!layer);
+ return surf->dcc_offset;
+ default:
+ unreachable("Invalid plane index");
+ }
+}
+
+uint64_t ac_surface_get_plane_stride(enum chip_class chip_class,
+ const struct radeon_surf *surf,
+ unsigned plane)
+{
+ switch (plane) {
+ case 0:
+ if (chip_class >= GFX9) {
+ return surf->u.gfx9.surf_pitch * surf->bpe;
+ } else {
+ return surf->u.legacy.level[0].nblk_x * surf->bpe;
+ }
+ case 1:
+ return 1 + (surf->display_dcc_offset ?
+ surf->u.gfx9.display_dcc_pitch_max : surf->u.gfx9.dcc_pitch_max);
+ case 2:
+ return surf->u.gfx9.dcc_pitch_max + 1;
+ default:
+ unreachable("Invalid plane index");
+ }
+}
diff --git a/src/amd/common/ac_surface.h b/src/amd/common/ac_surface.h
index 630f626500f..ef959eae2c3 100644
--- a/src/amd/common/ac_surface.h
+++ b/src/amd/common/ac_surface.h
@@ -27,6 +27,7 @@
#define AC_SURFACE_H
#include "amd_family.h"
+#include "util/format/u_format.h"
#include <stdbool.h>
#include <stdint.h>
@@ -207,6 +208,12 @@ struct radeon_surf {
unsigned micro_tile_mode : 3;
uint32_t flags;
+ /*
+ * DRM format modifier. Set to DRM_FORMAT_MOD_INVALID to have addrlib
+ * select tiling parameters instead.
+ */
+ uint64_t modifier;
+
/* These are return values. Some of them can be set by the caller, but
* they will be treated as hints (e.g. bankw, bankh) and might be
* changed by the calculator.
@@ -313,6 +320,32 @@ void ac_surface_get_umd_metadata(const struct radeon_info *info, struct radeon_s
void ac_surface_override_offset_stride(const struct radeon_info *info, struct radeon_surf *surf,
unsigned num_mipmap_levels, uint64_t offset, unsigned pitch);
+
+struct ac_modifier_options {
+ bool dcc; /* Whether to allow DCC. */
+ bool dcc_retile; /* Whether to allow use of a DCC retile map. */
+};
+
+bool ac_is_modifier_supported(const struct radeon_info *info,
+ const struct ac_modifier_options *options,
+ enum pipe_format format,
+ uint64_t modifier);
+bool ac_get_supported_modifiers(const struct radeon_info *info,
+ const struct ac_modifier_options *options,
+ enum pipe_format format,
+ unsigned *mod_count,
+ uint64_t *mods);
+bool ac_modifier_has_dcc(uint64_t modifier);
+bool ac_modifier_has_dcc_retile(uint64_t modifier);
+
+unsigned ac_surface_get_nplanes(const struct radeon_surf *surf);
+uint64_t ac_surface_get_plane_offset(enum chip_class chip_class,
+ const struct radeon_surf *surf,
+ unsigned plane, unsigned layer);
+uint64_t ac_surface_get_plane_stride(enum chip_class chip_class,
+ const struct radeon_surf *surf,
+ unsigned plane);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/amd/vulkan/radv_image.c b/src/amd/vulkan/radv_image.c
index 429c3d68467..ab70e1b5b5d 100644
--- a/src/amd/vulkan/radv_image.c
+++ b/src/amd/vulkan/radv_image.c
@@ -25,6 +25,8 @@
* IN THE SOFTWARE.
*/
+#include <libdrm/drm_fourcc.h>
+
#include "radv_debug.h"
#include "radv_private.h"
#include "vk_format.h"
@@ -452,7 +454,6 @@ radv_get_surface_flags(struct radv_device *device,
is_depth = vk_format_has_depth(desc);
is_stencil = vk_format_has_stencil(desc);
-
flags = RADEON_SURF_SET(array_mode, MODE);
switch (pCreateInfo->imageType){
@@ -1317,9 +1318,11 @@ radv_image_reset_layout(struct radv_image *image)
VkFormat format = vk_format_get_plane_format(image->vk_format, i);
uint32_t flags = image->planes[i].surface.flags;
+ uint64_t modifier = image->planes[i].surface.modifier;
memset(image->planes + i, 0, sizeof(image->planes[i]));
image->planes[i].surface.flags = flags;
+ image->planes[i].surface.modifier = modifier;
image->planes[i].surface.blk_w = vk_format_get_blockwidth(format);
image->planes[i].surface.blk_h = vk_format_get_blockheight(format);
image->planes[i].surface.bpe = vk_format_get_blocksize(vk_format_depth_only(format));
@@ -1474,6 +1477,7 @@ radv_image_create(VkDevice _device,
for (unsigned plane = 0; plane < image->plane_count; ++plane) {
image->planes[plane].surface.flags =
radv_get_surface_flags(device, image, plane, pCreateInfo, format);
+ image->planes[plane].surface.modifier = DRM_FORMAT_MOD_INVALID;
}
bool delay_layout = external_info &&
diff --git a/src/gallium/drivers/radeonsi/si_texture.c b/src/gallium/drivers/radeonsi/si_texture.c
index 3fea3b2eebd..794ba1ae0f6 100644
--- a/src/gallium/drivers/radeonsi/si_texture.c
+++ b/src/gallium/drivers/radeonsi/si_texture.c
@@ -316,6 +316,8 @@ static int si_init_surface(struct si_screen *sscreen, struct radeon_surf *surfac
surface->u.gfx9.surf.swizzle_mode = ADDR_SW_64KB_R_X;
}
+ surface->modifier = DRM_FORMAT_MOD_INVALID;
+
r = sscreen->ws->surface_init(sscreen->ws, ptex, flags, bpe, array_mode, surface);
if (r) {
return r;
More information about the mesa-commit
mailing list