amd/common: Add support for modifiers.

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6176>
This commit is contained in:
Bas Nieuwenhuizen 2019-10-08 10:21:30 +02:00 committed by Marge Bot
parent 2cc2b45688
commit 0833dd7d12
4 changed files with 438 additions and 57 deletions

View file

@ -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");
}
}

View file

@ -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

View file

@ -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 &&

View file

@ -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;