ac/surface: select 3D tile mode without overallocating too much for gfx6-8

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/12466
Fixes: c87ce78d - ac/surface: enable thick tiling for 3D textures for better perf on gfx6-8

Reviewed-by: Timur Kristóf <timur.kristof@gmail.com>
Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/34432>
This commit is contained in:
Marek Olšák
2025-04-08 14:59:05 -04:00
committed by Marge Bot
parent 195e7b4f75
commit 78cacfd9ce

View File

@@ -1244,6 +1244,11 @@ static uint64_t ac_estimate_size(const struct ac_surf_config *config,
return size;
}
#define SI__GB_TILE_MODE__BANK_WIDTH(x) (((x) >> 14) & 0x3)
#define SI__GB_TILE_MODE__BANK_HEIGHT(x) (((x) >> 16) & 0x3)
#define SI__GB_TILE_MODE__MACRO_TILE_ASPECT(x) (((x) >> 18) & 0x3)
#define SI__GB_TILE_MODE__NUM_BANKS(x) (((x) >> 20) & 0x3)
/**
* Fill in the tiling information in \p surf based on the given surface config.
*
@@ -1306,11 +1311,100 @@ static int gfx6_compute_surface(ADDR_HANDLE addrlib, const struct radeon_info *i
}
} else {
if (config->is_3d) {
/* GFX6 doesn't have 3D_TILED_XTHICK. */
if (info->gfx_level >= GFX7)
AddrSurfInfoIn.tileMode = ADDR_TM_3D_TILED_XTHICK;
else
AddrSurfInfoIn.tileMode = ADDR_TM_2D_TILED_XTHICK;
/* Select the best tile mode that doesn't overallocate memory too much.
* The tile modes below are sorted from best to worst performance.
*/
struct {
unsigned tile_mode;
unsigned gfx6_tile_mode_index;
unsigned gfx7_tile_mode_index;
unsigned microtile_width;
unsigned microtile_height;
unsigned microtile_depth;
bool supported; /* this comes from the tile mode arrays in the kernel */
/* Derived fields. */
unsigned bank_width;
unsigned bank_height;
unsigned num_banks;
unsigned macro_tile_aspect;
unsigned align_width;
unsigned align_height;
unsigned align_depth;
} modes[] = {
{ADDR_TM_3D_TILED_XTHICK, 0, 26, 8, 8, 8, info->gfx_level >= GFX7},
{ADDR_TM_2D_TILED_XTHICK, 19, 25, 8, 8, 8, true},
{ADDR_TM_3D_TILED_THICK, 0, 21, 8, 8, 4, info->gfx_level >= GFX7},
{ADDR_TM_2D_TILED_THICK, 20, 20, 8, 8, 4, true},
{ADDR_TM_3D_TILED_THIN1, 0, 15, 8, 8, 1, info->gfx_level >= GFX7},
{ADDR_TM_2D_TILED_THIN1, 14, 14, 8, 8, 1, true},
{ADDR_TM_1D_TILED_THICK, 18, 19, 8, 8, 4, true},
{ADDR_TM_1D_TILED_THIN1, 13, 13, 8, 8, 1, true},
/* Don't use LINEAR_ALIGNED. It doesn't work with BC formats. */
};
for (unsigned i = 0; i < ARRAY_SIZE(modes); i++) {
if (!modes[i].supported)
continue;
if (modes[i].tile_mode <= ADDR_TM_1D_TILED_THICK) {
modes[i].align_width = modes[i].microtile_width;
modes[i].align_height = modes[i].microtile_height;
modes[i].align_depth = modes[i].microtile_depth;
continue;
}
if (info->gfx_level >= GFX7) {
ADDR_GET_MACROMODEINDEX_INPUT in = {sizeof(in)};
ADDR_GET_MACROMODEINDEX_OUTPUT out = {sizeof(out)};
in.tileIndex = modes[i].gfx7_tile_mode_index;
in.bpp = surf->bpe * 8;
in.numFrags = 1;
if (AddrGetMacroModeIndex(addrlib, &in, &out) != ADDR_OK) {
fprintf(stderr, "amdgpu: AddrGetMacroModeIndex failed.\n");
return -1;
}
uint32_t macro_mode_reg = info->cik_macrotile_mode_array[out.macroModeIndex];
modes[i].bank_width = 1 << G_009990_BANK_WIDTH(macro_mode_reg);
modes[i].bank_height = 1 << G_009990_BANK_HEIGHT(macro_mode_reg);
modes[i].num_banks = 2 << G_009990_NUM_BANKS(macro_mode_reg);
modes[i].macro_tile_aspect = 1 << G_009990_MACRO_TILE_ASPECT(macro_mode_reg);
} else {
/* GFX6. */
uint32_t tile_mode_reg = info->si_tile_mode_array[modes[i].gfx6_tile_mode_index];
modes[i].bank_width = 1 << SI__GB_TILE_MODE__BANK_WIDTH(tile_mode_reg);
modes[i].bank_height = 1 << SI__GB_TILE_MODE__BANK_HEIGHT(tile_mode_reg);
modes[i].num_banks = 2 << SI__GB_TILE_MODE__NUM_BANKS(tile_mode_reg);
modes[i].macro_tile_aspect = 1 << SI__GB_TILE_MODE__MACRO_TILE_ASPECT(tile_mode_reg);
}
modes[i].align_width = modes[i].microtile_width * modes[i].bank_width *
info->num_tile_pipes * modes[i].macro_tile_aspect;
modes[i].align_height = modes[i].microtile_height * modes[i].bank_height *
modes[i].num_banks / modes[i].macro_tile_aspect;
modes[i].align_depth = modes[i].microtile_depth;
}
uint64_t ideal_size = ac_estimate_size(config, surf->blk_w, surf->blk_h, surf->bpe * 8,
config->info.width, config->info.height, 1, 1, 1);
AddrSurfInfoIn.tileMode = ADDR_TM_1D_TILED_THIN1; /* used if everything else fails */
for (unsigned i = 0; i < ARRAY_SIZE(modes); i++) {
if (!modes[i].supported)
continue;
uint64_t size = ac_estimate_size(config, surf->blk_w, surf->blk_h, surf->bpe * 8,
config->info.width, config->info.height,
modes[i].align_width, modes[i].align_height,
modes[i].align_depth);
if (size <= ideal_size * 3) {
AddrSurfInfoIn.tileMode = modes[i].tile_mode;
break;
}
}
} else {
AddrSurfInfoIn.tileMode = ADDR_TM_2D_TILED_THIN1;
}