radeonsi: get SPI_PS_INPUT_ENA from shader variant NIR for ACO

All PS lowering that changes, adds, or removes system values based on
the shader key is done first, which is done in ac_nir_lower_ps_early and
other passes, so now we just need to gather them.

This should improve performance for ACO due to fewer VGPRs needed
for optimized shader variants of PS.

Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32910>
This commit is contained in:
Marek Olšák
2024-12-31 11:10:23 -05:00
committed by Marge Bot
parent edeb52ce4a
commit 1c4c883a3b
+52 -73
View File
@@ -2261,8 +2261,7 @@ static bool run_pre_link_optimization_passes(struct si_nir_shader_ctx *ctx)
* The driver takes into account these things if they suddenly disappear
* from the shader code:
* - Register usage and code size decrease (obvious)
* - Eliminated PS system values are disabled by LLVM
* (FragCoord, FrontFace, barycentrics)
* - Eliminated PS system values are disabled
* - VS/TES/GS param exports are eliminated if they are undef.
* The param space for eliminated outputs is also not allocated.
* - VS/TCS/TES/GS/PS input loads are eliminated (VS relies on DCE in LLVM)
@@ -2742,78 +2741,60 @@ static void si_fixup_spi_ps_input_config(struct si_shader *shader)
}
static void
si_set_spi_ps_input_config(struct si_shader *shader)
si_get_shader_variant_info(struct si_shader *shader, nir_shader *nir)
{
const struct si_shader_selector *sel = shader->selector;
const struct si_shader_info *info = &sel->info;
const union si_shader_key *key = &shader->key;
nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
assert(shader->selector->info.base.use_aco_amd == nir->info.use_aco_amd);
const BITSET_WORD *sysvals = nir->info.system_values_read;
/* TODO: This should be determined from the final NIR instead of the input NIR,
* otherwise LLVM will have a performance advantage here because it determines
* VGPR inputs for each shader variant after LLVM optimizations.
*/
uint8_t frag_coord_mask = info->reads_frag_coord_mask | info->reads_sample_pos_mask;
/* ACO needs spi_ps_input_ena before si_init_shader_args. */
if (nir->info.use_aco_amd) {
/* Find out which frag coord components are used. */
uint8_t frag_coord_mask = 0;
shader->config.spi_ps_input_ena =
S_0286CC_PERSP_CENTER_ENA(info->uses_persp_center) |
S_0286CC_PERSP_CENTROID_ENA(info->uses_persp_centroid) |
S_0286CC_PERSP_SAMPLE_ENA(info->uses_persp_sample) |
S_0286CC_LINEAR_CENTER_ENA(info->uses_linear_center) |
S_0286CC_LINEAR_CENTROID_ENA(info->uses_linear_centroid) |
S_0286CC_LINEAR_SAMPLE_ENA(info->uses_linear_sample) |
S_0286CC_POS_X_FLOAT_ENA(!!(frag_coord_mask & 0x1) &&
!key->ps.part.prolog.get_frag_coord_from_pixel_coord) |
S_0286CC_POS_Y_FLOAT_ENA(!!(frag_coord_mask & 0x2) &&
!key->ps.part.prolog.get_frag_coord_from_pixel_coord) |
S_0286CC_POS_Z_FLOAT_ENA(!!(frag_coord_mask & 0x4)) |
S_0286CC_POS_W_FLOAT_ENA(!!(frag_coord_mask & 0x8)) |
S_0286CC_FRONT_FACE_ENA(info->uses_frontface && !key->ps.opt.force_front_face_input) |
S_0286CC_SAMPLE_COVERAGE_ENA(info->reads_samplemask) |
S_0286CC_ANCILLARY_ENA(info->uses_sampleid || info->uses_layer_id) |
S_0286CC_POS_FIXED_PT_ENA(key->ps.part.prolog.get_frag_coord_from_pixel_coord);
if (BITSET_TEST(sysvals, SYSTEM_VALUE_FRAG_COORD)) {
nir_foreach_block(block, nir_shader_get_entrypoint(nir)) {
nir_foreach_instr(instr, block) {
if (instr->type == nir_instr_type_intrinsic) {
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
if (intr->intrinsic == nir_intrinsic_load_frag_coord ||
intr->intrinsic == nir_intrinsic_load_sample_pos)
frag_coord_mask |= nir_def_components_read(&intr->def);
}
}
}
}
if (key->ps.part.prolog.color_two_side)
shader->config.spi_ps_input_ena |= S_0286CC_FRONT_FACE_ENA(1);
shader->config.spi_ps_input_ena =
S_0286CC_PERSP_SAMPLE_ENA(BITSET_TEST(sysvals, SYSTEM_VALUE_BARYCENTRIC_PERSP_SAMPLE)) |
S_0286CC_PERSP_CENTER_ENA(BITSET_TEST(sysvals, SYSTEM_VALUE_BARYCENTRIC_PERSP_PIXEL)) |
S_0286CC_PERSP_CENTROID_ENA(BITSET_TEST(sysvals, SYSTEM_VALUE_BARYCENTRIC_PERSP_CENTROID)) |
S_0286CC_LINEAR_SAMPLE_ENA(BITSET_TEST(sysvals, SYSTEM_VALUE_BARYCENTRIC_LINEAR_SAMPLE)) |
S_0286CC_LINEAR_CENTER_ENA(BITSET_TEST(sysvals, SYSTEM_VALUE_BARYCENTRIC_LINEAR_PIXEL)) |
S_0286CC_LINEAR_CENTROID_ENA(BITSET_TEST(sysvals, SYSTEM_VALUE_BARYCENTRIC_LINEAR_CENTROID)) |
S_0286CC_POS_X_FLOAT_ENA(!!(frag_coord_mask & 0x1)) |
S_0286CC_POS_Y_FLOAT_ENA(!!(frag_coord_mask & 0x2)) |
S_0286CC_POS_Z_FLOAT_ENA(!!(frag_coord_mask & 0x4)) |
S_0286CC_POS_W_FLOAT_ENA(!!(frag_coord_mask & 0x8)) |
S_0286CC_FRONT_FACE_ENA(BITSET_TEST(sysvals, SYSTEM_VALUE_FRONT_FACE) |
BITSET_TEST(sysvals, SYSTEM_VALUE_FRONT_FACE_FSIGN)) |
S_0286CC_ANCILLARY_ENA(BITSET_TEST(sysvals, SYSTEM_VALUE_SAMPLE_ID) |
BITSET_TEST(sysvals, SYSTEM_VALUE_LAYER_ID)) |
S_0286CC_SAMPLE_COVERAGE_ENA(BITSET_TEST(sysvals, SYSTEM_VALUE_SAMPLE_MASK_IN)) |
S_0286CC_POS_FIXED_PT_ENA(BITSET_TEST(sysvals, SYSTEM_VALUE_PIXEL_COORD));
/* INTERP_MODE_COLOR, same as SMOOTH if flat shading is disabled. */
if (info->uses_interp_color && !key->ps.part.prolog.flatshade_colors) {
shader->config.spi_ps_input_ena |=
S_0286CC_PERSP_SAMPLE_ENA(info->uses_persp_sample_color) |
S_0286CC_PERSP_CENTER_ENA(info->uses_persp_center_color) |
S_0286CC_PERSP_CENTROID_ENA(info->uses_persp_centroid_color);
}
/* nir_lower_poly_line_smooth use nir_load_sample_mask_in */
if (key->ps.mono.poly_line_smoothing)
shader->config.spi_ps_input_ena |= S_0286CC_SAMPLE_COVERAGE_ENA(1);
/* nir_lower_point_smooth use nir_load_point_coord_maybe_flipped which is lowered
* to nir_load_barycentric_pixel and nir_load_interpolated_input.
*/
if (key->ps.mono.point_smoothing)
shader->config.spi_ps_input_ena |= S_0286CC_PERSP_CENTER_ENA(1);
/* See fetch_framebuffer() for used args when fbfetch output. */
if (info->base.fs.uses_fbfetch_output) {
shader->config.spi_ps_input_ena |= S_0286CC_POS_FIXED_PT_ENA(1);
if (key->ps.mono.fbfetch_layered || key->ps.mono.fbfetch_msaa)
shader->config.spi_ps_input_ena |= S_0286CC_ANCILLARY_ENA(1);
}
if (shader->is_monolithic) {
si_set_spi_ps_input_config_for_separate_prolog(shader);
si_fixup_spi_ps_input_config(shader);
shader->config.spi_ps_input_addr = shader->config.spi_ps_input_ena;
} else {
/* Part mode will call si_fixup_spi_ps_input_config() when combining multi
* shader part in si_shader_select_ps_parts().
*
* Reserve register locations for VGPR inputs the PS prolog may need.
*/
shader->config.spi_ps_input_addr =
shader->config.spi_ps_input_ena |
SI_SPI_PS_INPUT_ADDR_FOR_PROLOG;
if (shader->is_monolithic) {
si_fixup_spi_ps_input_config(shader);
shader->config.spi_ps_input_addr = shader->config.spi_ps_input_ena;
} else {
/* Part mode will call si_fixup_spi_ps_input_config() when combining multi
* shader part in si_shader_select_ps_parts().
*
* Reserve register locations for VGPR inputs the PS prolog may need.
*/
shader->config.spi_ps_input_addr = shader->config.spi_ps_input_ena |
SI_SPI_PS_INPUT_ADDR_FOR_PROLOG;
}
}
}
@@ -2862,6 +2843,8 @@ static void get_nir_shaders(struct si_shader *shader, struct si_linked_shaders *
if (shader->is_monolithic)
NIR_PASS_V(linked->consumer.nir, nir_recompute_io_bases, nir_var_shader_in);
si_get_shader_variant_info(shader, linked->consumer.nir);
struct si_shader_info info;
si_nir_scan_shader(shader->selector->screen, linked->consumer.nir, &info,
shader->is_monolithic);
@@ -3025,10 +3008,6 @@ bool si_compile_shader(struct si_screen *sscreen, struct ac_llvm_compiler *compi
determine_shader_variant_info(sscreen, shader);
/* ACO need spi_ps_input in advance to init args and used in compiler. */
if (sel->stage == MESA_SHADER_FRAGMENT && sel->info.base.use_aco_amd)
si_set_spi_ps_input_config(shader);
struct si_linked_shaders linked;
get_nir_shaders(shader, &linked);
nir_shader *nir = linked.consumer.nir;