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; - - 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; + 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; + 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 #include @@ -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 + #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;