diff --git a/.pick_status.json b/.pick_status.json index bd3a71dcaf0..75ec0e7d704 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -174,7 +174,7 @@ "description": "ac/surface: select 3D tile mode without overallocating too much for gfx6-8", "nominated": true, "nomination_type": 2, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": "c87ce78d1013a52a78a05470ca33fd8597d3f289", "notes": null diff --git a/src/amd/common/ac_surface.c b/src/amd/common/ac_surface.c index 9ecf927edbe..bfd830d4739 100644 --- a/src/amd/common/ac_surface.c +++ b/src/amd/common/ac_surface.c @@ -1245,6 +1245,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. * @@ -1307,11 +1312,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; }