From 3b276e4ba66511c4d7b4e7d53093f794c1e13d1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Thu, 10 Apr 2025 16:29:05 -0400 Subject: [PATCH] radeonsi: move gathering VMEM information into si_get_shader_variant_info This is a step towards gathering shader info from shader variants instead of input NIR. uses_fbfetch_output can be ignored because it's already lowered to image loads. Reviewed-by: Pierre-Eric Pelloux-Prayer Part-of: --- src/gallium/drivers/radeonsi/si_shader.c | 100 ++++++++++++++---- src/gallium/drivers/radeonsi/si_shader.h | 13 +-- src/gallium/drivers/radeonsi/si_shader_info.c | 85 --------------- 3 files changed, 86 insertions(+), 112 deletions(-) diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c index e96d503a787..0121fbb30d1 100644 --- a/src/gallium/drivers/radeonsi/si_shader.c +++ b/src/gallium/drivers/radeonsi/si_shader.c @@ -2393,7 +2393,7 @@ static void run_late_optimization_and_lowering_passes(struct si_nir_shader_ctx * NIR_PASS(progress, nir, ac_nir_lower_image_opcodes); /* LLVM does not work well with this, so is handled in llvm backend waterfall. */ - if (nir->info.use_aco_amd && sel->info.has_non_uniform_tex_access) { + if (nir->info.use_aco_amd && ctx->shader->info.has_non_uniform_tex_access) { nir_lower_non_uniform_access_options options = { .types = nir_lower_non_uniform_texture_access, }; @@ -2571,7 +2571,7 @@ static void run_late_optimization_and_lowering_passes(struct si_nir_shader_ctx * /* LLVM keep non-uniform sampler as index, so can't do this in NIR. * Must be done after si_nir_lower_resource(). */ - if (nir->info.use_aco_amd && sel->info.has_shadow_comparison && + if (nir->info.use_aco_amd && ctx->shader->info.has_shadow_comparison && sel->screen->info.gfx_level >= GFX8 && sel->screen->info.gfx_level <= GFX9) { NIR_PASS(progress, nir, si_nir_clamp_shadow_comparison_value); } @@ -2744,6 +2744,8 @@ si_get_shader_variant_info(struct si_shader *shader, nir_shader *nir) /* Find out which frag coord components are used. */ uint8_t frag_coord_mask = 0; + nir_divergence_analysis(nir); + if (nir->info.stage == MESA_SHADER_FRAGMENT) { /* Since flat+convergent and non-flat components can occur in the same vec4, start with * all PS inputs as flat and change them to smooth when we find a component that's @@ -2756,7 +2758,7 @@ si_get_shader_variant_info(struct si_shader *shader, nir_shader *nir) nir_foreach_block(block, nir_shader_get_entrypoint(nir)) { nir_foreach_instr(instr, block) { switch (instr->type) { - case nir_instr_type_intrinsic: + case nir_instr_type_intrinsic: { nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); switch (intr->intrinsic) { @@ -2765,8 +2767,13 @@ si_get_shader_variant_info(struct si_shader *shader, nir_shader *nir) frag_coord_mask |= nir_def_components_read(&intr->def); break; case nir_intrinsic_load_input: + case nir_intrinsic_load_input_vertex: + case nir_intrinsic_load_per_vertex_input: case nir_intrinsic_load_interpolated_input: { - if (nir->info.stage == MESA_SHADER_FRAGMENT) { + if (nir->info.stage == MESA_SHADER_VERTEX || + nir->info.stage == MESA_SHADER_TESS_EVAL) { + shader->info.uses_vmem_load_other = true; + } else if (nir->info.stage == MESA_SHADER_FRAGMENT) { nir_io_semantics sem = nir_intrinsic_io_semantics(intr); unsigned index = nir_intrinsic_base(intr); assert(sem.num_slots == 1); @@ -2792,9 +2799,79 @@ si_get_shader_variant_info(struct si_shader *shader, nir_shader *nir) assert(!shader->is_monolithic); shader->info.ps_colors_read |= nir_def_components_read(&intr->def) << 4; break; + case nir_intrinsic_load_ubo: + if (intr->src[1].ssa->divergent) + shader->info.uses_vmem_load_other = true; + break; + case nir_intrinsic_load_constant: + if (intr->src[0].ssa->divergent) + shader->info.uses_vmem_load_other = true; + break; + /* Global */ + case nir_intrinsic_load_global: + case nir_intrinsic_global_atomic: + case nir_intrinsic_global_atomic_swap: + /* SSBOs (this list is from si_nir_lower_resource.c) */ + case nir_intrinsic_load_ssbo: + case nir_intrinsic_ssbo_atomic: + case nir_intrinsic_ssbo_atomic_swap: + /* Images (this list is from si_nir_lower_resource.c) */ + case nir_intrinsic_image_deref_load: + case nir_intrinsic_image_deref_sparse_load: + case nir_intrinsic_image_deref_fragment_mask_load_amd: + case nir_intrinsic_image_deref_atomic: + case nir_intrinsic_image_deref_atomic_swap: + case nir_intrinsic_bindless_image_load: + case nir_intrinsic_bindless_image_sparse_load: + case nir_intrinsic_bindless_image_fragment_mask_load_amd: + case nir_intrinsic_bindless_image_atomic: + case nir_intrinsic_bindless_image_atomic_swap: + /* Scratch */ + case nir_intrinsic_load_scratch: + /* AMD-specific. */ + case nir_intrinsic_load_buffer_amd: + /* Atomics without return are not treated as loads. */ + if (nir_def_components_read(&intr->def) && + (!nir_intrinsic_has_atomic_op(intr) || + nir_intrinsic_atomic_op(intr) != nir_atomic_op_ordered_add_gfx12_amd)) + shader->info.uses_vmem_load_other = true; + break; default: break; } + break; + } + + case nir_instr_type_tex: { + nir_tex_instr *tex = nir_instr_as_tex(instr); + + shader->info.has_non_uniform_tex_access |= tex->texture_non_uniform || tex->sampler_non_uniform; + shader->info.has_shadow_comparison |= tex->is_shadow; + + /* Gather the types of used VMEM instructions that return something. */ + switch (tex->op) { + case nir_texop_tex: + case nir_texop_txb: + case nir_texop_txl: + case nir_texop_txd: + case nir_texop_lod: + case nir_texop_tg4: + shader->info.uses_vmem_sampler_or_bvh = true; + break; + case nir_texop_txs: + case nir_texop_query_levels: + case nir_texop_texture_samples: + case nir_texop_descriptor_amd: + case nir_texop_sampler_descriptor_amd: + /* These just return the descriptor or information from it. */ + break; + default: + shader->info.uses_vmem_load_other = true; + break; + } + break; + } + default: break; } @@ -2904,21 +2981,6 @@ static void get_nir_shaders(struct si_shader *shader, struct si_linked_shaders * run_late_optimization_and_lowering_passes(&linked->shader[i]); } } - - /* TODO: gather this where other shader_info is gathered */ - for (unsigned i = 0; i < SI_NUM_LINKED_SHADERS; i++) { - if (linked->shader[i].nir) { - struct si_shader_info info; - - /* Save and restore use_aco_amd because si_nir_scan_shader changes it. */ - bool use_aco_amd = linked->shader[i].nir->info.use_aco_amd; - si_nir_scan_shader(shader->selector->screen, linked->shader[i].nir, &info, true); - linked->shader[i].nir->info.use_aco_amd = use_aco_amd; - - shader->info.uses_vmem_load_other |= info.uses_vmem_load_other; - shader->info.uses_vmem_sampler_or_bvh |= info.uses_vmem_sampler_or_bvh; - } - } } /* Generate code for the hardware VS shader stage to go with a geometry shader */ diff --git a/src/gallium/drivers/radeonsi/si_shader.h b/src/gallium/drivers/radeonsi/si_shader.h index ee690bff68e..d46cba8d2be 100644 --- a/src/gallium/drivers/radeonsi/si_shader.h +++ b/src/gallium/drivers/radeonsi/si_shader.h @@ -561,11 +561,6 @@ struct si_shader_info { bool uses_bindless_samplers; bool uses_bindless_images; bool has_divergent_loop; - bool has_non_uniform_tex_access; - bool has_shadow_comparison; - - bool uses_vmem_sampler_or_bvh; - bool uses_vmem_load_other; /* all other VMEM loads and atomics with return */ /** Whether all codepaths write tess factors in all invocations. */ bool tessfactors_are_def_in_all_invocs; @@ -877,9 +872,11 @@ struct si_shader_binary_info { uint8_t ps_colors_read; uint8_t num_input_sgprs; uint8_t num_input_vgprs; - bool uses_vmem_load_other; /* all other VMEM loads and atomics with return */ - bool uses_vmem_sampler_or_bvh; - bool uses_instanceid; + bool uses_vmem_load_other : 1; /* all other VMEM loads and atomics with return */ + bool uses_vmem_sampler_or_bvh : 1; + bool has_non_uniform_tex_access : 1; + bool has_shadow_comparison : 1; + bool uses_instanceid : 1; uint8_t nr_pos_exports; uint8_t nr_param_exports; unsigned private_mem_vgprs; diff --git a/src/gallium/drivers/radeonsi/si_shader_info.c b/src/gallium/drivers/radeonsi/si_shader_info.c index 7af4367476f..c63c9165489 100644 --- a/src/gallium/drivers/radeonsi/si_shader_info.c +++ b/src/gallium/drivers/radeonsi/si_shader_info.c @@ -269,93 +269,10 @@ static void scan_instruction(const struct nir_shader *nir, struct si_shader_info nir_tex_instr *tex = nir_instr_as_tex(instr); info->uses_bindless_samplers |= get_texture_src(tex, nir_tex_src_texture_handle) != NULL; - - /* Gather the types of used VMEM instructions that return something. */ - switch (tex->op) { - case nir_texop_tex: - case nir_texop_txb: - case nir_texop_txl: - case nir_texop_txd: - case nir_texop_lod: - case nir_texop_tg4: - info->uses_vmem_sampler_or_bvh = true; - break; - case nir_texop_txs: - case nir_texop_query_levels: - case nir_texop_texture_samples: - case nir_texop_descriptor_amd: - case nir_texop_sampler_descriptor_amd: - /* These just return the descriptor or information from it. */ - break; - default: - info->uses_vmem_load_other = true; - break; - } - - info->has_non_uniform_tex_access |= - tex->texture_non_uniform || tex->sampler_non_uniform; - - info->has_shadow_comparison |= tex->is_shadow; } else if (instr->type == nir_instr_type_intrinsic) { nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); const char *intr_name = nir_intrinsic_infos[intr->intrinsic].name; - /* Gather the types of used VMEM instructions that return something. */ - if (nir_intrinsic_infos[intr->intrinsic].has_dest) { - switch (intr->intrinsic) { - case nir_intrinsic_load_ubo: - if (intr->src[1].ssa->divergent) - info->uses_vmem_load_other = true; - break; - - case nir_intrinsic_load_input: - case nir_intrinsic_load_input_vertex: - case nir_intrinsic_load_per_vertex_input: - if (nir->info.stage == MESA_SHADER_VERTEX || - nir->info.stage == MESA_SHADER_TESS_EVAL) - info->uses_vmem_load_other = true; - break; - - case nir_intrinsic_load_constant: - if (intr->src[0].ssa->divergent) - info->uses_vmem_load_other = true; - break; - - /* Global */ - case nir_intrinsic_load_global: - case nir_intrinsic_global_atomic: - case nir_intrinsic_global_atomic_swap: - /* SSBOs (this list is from si_nir_lower_resource.c) */ - case nir_intrinsic_load_ssbo: - case nir_intrinsic_ssbo_atomic: - case nir_intrinsic_ssbo_atomic_swap: - /* Images (this list is from si_nir_lower_resource.c) */ - case nir_intrinsic_image_deref_load: - case nir_intrinsic_image_deref_sparse_load: - case nir_intrinsic_image_deref_fragment_mask_load_amd: - case nir_intrinsic_image_deref_atomic: - case nir_intrinsic_image_deref_atomic_swap: - case nir_intrinsic_bindless_image_load: - case nir_intrinsic_bindless_image_sparse_load: - case nir_intrinsic_bindless_image_fragment_mask_load_amd: - case nir_intrinsic_bindless_image_atomic: - case nir_intrinsic_bindless_image_atomic_swap: - /* Scratch */ - case nir_intrinsic_load_scratch: - /* AMD-specific. */ - case nir_intrinsic_load_buffer_amd: - /* Atomics without return are not treated as loads. */ - if (nir_def_components_read(&intr->def) && - (!nir_intrinsic_has_atomic_op(intr) || - nir_intrinsic_atomic_op(intr) != nir_atomic_op_ordered_add_gfx12_amd)) - info->uses_vmem_load_other = true; - break; - - default: - break; - } - } - info->uses_bindless_images |= strstr(intr_name, "bindless_image") == intr_name; if (nir_intrinsic_has_atomic_op(intr)) { @@ -626,8 +543,6 @@ void si_nir_scan_shader(struct si_screen *sscreen, struct nir_shader *nir, BITSET_TEST(nir->info.system_values_read, SYSTEM_VALUE_SAMPLE_MASK_IN) || BITSET_TEST(nir->info.system_values_read, SYSTEM_VALUE_HELPER_INVOCATION)); - info->uses_vmem_load_other |= nir->info.fs.uses_fbfetch_output; - /* Add both front and back color inputs. */ unsigned num_inputs_with_colors = info->num_inputs; for (unsigned back = 0; back < 2; back++) {