nir: rename to nir_opt_load_skip_helpers and add options struct

Reviewed-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36610>
This commit is contained in:
Georg Lehmann 2025-08-06 12:05:35 +02:00 committed by Marge Bot
parent fbae0893a6
commit 91572a99bb
4 changed files with 34 additions and 24 deletions

View file

@ -274,6 +274,7 @@ else
'nir_opt_intrinsics.c',
'nir_opt_large_constants.c',
'nir_opt_licm.c',
'nir_opt_load_skip_helpers.c',
'nir_opt_load_store_vectorize.c',
'nir_opt_loop.c',
'nir_opt_loop_unroll.c',
@ -296,7 +297,6 @@ else
'nir_opt_shrink_stores.c',
'nir_opt_shrink_vectors.c',
'nir_opt_sink.c',
'nir_opt_tex_skip_helpers.c',
'nir_opt_undef.c',
'nir_opt_uniform_atomics.c',
'nir_opt_uniform_subgroup.c',

View file

@ -2462,7 +2462,7 @@ typedef struct nir_tex_instr {
/** True if helper invocation loads can be skipped
*
* This is set by nir_opt_tex_skip_helpers().
* This is set by nir_opt_load_skip_helpers().
*/
unsigned skip_helpers : 1;
@ -6379,7 +6379,11 @@ bool nir_opt_ray_queries(nir_shader *shader);
bool nir_opt_ray_query_ranges(nir_shader *shader);
bool nir_opt_tex_skip_helpers(nir_shader *shader, bool no_add_divergence);
typedef struct nir_opt_load_skip_helpers_options {
bool no_add_divergence : 1;
} nir_opt_load_skip_helpers_options;
bool nir_opt_load_skip_helpers(nir_shader *shader, nir_opt_load_skip_helpers_options *options);
void nir_sweep(nir_shader *shader);

View file

@ -48,8 +48,8 @@ instr_never_needs_helpers(nir_instr *instr)
struct helper_state {
BITSET_WORD *needs_helpers;
nir_instr_worklist *worklist;
nir_instr_worklist *tex_instrs;
bool no_add_divergence;
nir_instr_worklist *load_instrs;
nir_opt_load_skip_helpers_options *options;
};
static inline bool
@ -72,7 +72,7 @@ set_src_needs_helpers(nir_src *src, void *_data)
}
bool
nir_opt_tex_skip_helpers(nir_shader *shader, bool no_add_divergence)
nir_opt_load_skip_helpers(nir_shader *shader, nir_opt_load_skip_helpers_options *options)
{
/* This is only useful on fragment shaders */
assert(shader->info.stage == MESA_SHADER_FRAGMENT);
@ -84,13 +84,13 @@ nir_opt_tex_skip_helpers(nir_shader *shader, bool no_add_divergence)
.needs_helpers = rzalloc_array(NULL, BITSET_WORD,
BITSET_WORDS(impl->ssa_alloc)),
.worklist = nir_instr_worklist_create(),
.tex_instrs = nir_instr_worklist_create(),
.no_add_divergence = no_add_divergence,
.load_instrs = nir_instr_worklist_create(),
.options = options,
};
/* First, add subgroup ops and anything that might cause side effects */
nir_foreach_block(block, impl) {
/* Control-flow is hard. Given that this is only for texture ops, we
/* Control-flow is hard. Given that this is only for load ops, we
* can afford to be conservative and assume that any control-flow is
* potentially going to affect helpers.
*/
@ -106,7 +106,7 @@ nir_opt_tex_skip_helpers(nir_shader *shader, bool no_add_divergence)
/* Stash texture instructions so we don't have to walk the whole
* shader again just to set the skip_helpers bit.
*/
nir_instr_worklist_push_tail(hs.tex_instrs, instr);
nir_instr_worklist_push_tail(hs.load_instrs, instr);
for (uint32_t i = 0; i < tex->num_srcs; i++) {
switch (tex->src[i].src_type) {
@ -178,35 +178,35 @@ nir_opt_tex_skip_helpers(nir_shader *shader, bool no_add_divergence)
bool progress = false;
/* We only need to run the worklist if we have textures */
if (!nir_instr_worklist_is_empty(hs.tex_instrs)) {
/* We only need to run the worklist if we have loads */
if (!nir_instr_worklist_is_empty(hs.load_instrs)) {
while (!nir_instr_worklist_is_empty(hs.worklist)) {
nir_instr *instr = nir_instr_worklist_pop_head(hs.worklist);
assert(nir_foreach_def(instr, def_needs_helpers, &hs));
nir_foreach_src(instr, set_src_needs_helpers, &hs);
}
while (!nir_instr_worklist_is_empty(hs.tex_instrs)) {
nir_instr *instr = nir_instr_worklist_pop_head(hs.tex_instrs);
while (!nir_instr_worklist_is_empty(hs.load_instrs)) {
nir_instr *instr = nir_instr_worklist_pop_head(hs.load_instrs);
nir_tex_instr *tex = nir_instr_as_tex(instr);
/* If a texture uniform, we don't want to set skip_helpers because
/* If a load is uniform, we don't want to set skip_helpers because
* then it might not be uniform if the helpers don't fetch. Also,
* for uniform texture results, we shouldn't be burning any more
* for uniform load results, we shouldn't be burning any more
* memory by executing the helper pixels unless the hardware is
* really dumb.
*
* NOTE: Any texture instruction that doesn't have skip_helpers set
* NOTE: Any load instruction that doesn't have skip_helpers set
* then relies on correct parameters in those helper invocations.
* If we're depending on those helpers to keep things uniform, then
* leaving skip_helpers=false adds dependencies. However, in order
* for the texture result to be uniform, all parameters must be
* for the load result to be uniform, all parameters must be
* uniform so they either have to come from other uniform things or
* subgroup ops which uniformize values. Therefore, as long as we
* always leave skip_helpers=false on all uniform texture ops, we'll
* have valid helper data in this texture op.
* always leave skip_helpers=false on all uniform load ops, we'll
* have valid helper data in this load op.
*/
if (!tex->def.divergent && hs.no_add_divergence)
if (!tex->def.divergent && hs.options->no_add_divergence)
continue;
if (!def_needs_helpers(&tex->def, &hs) && !tex->skip_helpers) {
@ -216,7 +216,7 @@ nir_opt_tex_skip_helpers(nir_shader *shader, bool no_add_divergence)
}
}
nir_instr_worklist_destroy(hs.tex_instrs);
nir_instr_worklist_destroy(hs.load_instrs);
nir_instr_worklist_destroy(hs.worklist);
ralloc_free(hs.needs_helpers);

View file

@ -1032,8 +1032,14 @@ nak_postprocess_nir(nir_shader *nir,
OPT(nir, nir_convert_to_lcssa, true, true);
nir_divergence_analysis(nir);
if (nir->info.stage == MESA_SHADER_FRAGMENT)
OPT(nir, nir_opt_tex_skip_helpers, true);
if (nir->info.stage == MESA_SHADER_FRAGMENT) {
nir_opt_load_skip_helpers_options skip_helper_options = {
.no_add_divergence = true,
};
OPT(nir, nir_opt_load_skip_helpers, &skip_helper_options);
}
OPT(nir, nak_nir_lower_scan_reduce, nak);
nak_optimize_nir(nir, nak);