mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-06 08:50:09 +01:00
nir: lower load_helper to is_helper if the shader uses demote()
load_helper_invocation is an Input Builtin, for which the value should not change during the execution of a shader. This new pass inserts an is_helper intrinsic before any demote() instruction and re-uses its value. Reviewed-by: Marek Olšák <marek.olsak@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9058>
This commit is contained in:
parent
3c31364f5e
commit
b689a65316
1 changed files with 62 additions and 0 deletions
|
|
@ -69,6 +69,56 @@ nir_lower_demote_to_discard_instr(nir_builder *b, nir_instr *instr, void *data)
|
|||
}
|
||||
}
|
||||
|
||||
static nir_ssa_def *
|
||||
insert_is_helper(nir_builder *b, nir_instr *instr)
|
||||
{
|
||||
/* find best place to insert is_helper */
|
||||
nir_cf_node *node = &instr->block->cf_node;
|
||||
while (node->parent->type != nir_cf_node_function)
|
||||
node = nir_cf_node_prev(node->parent);
|
||||
nir_block *block = nir_cf_node_as_block(node);
|
||||
if (block == instr->block) {
|
||||
b->cursor = nir_before_instr(instr);
|
||||
} else {
|
||||
b->cursor = nir_after_block_before_jump(block);
|
||||
}
|
||||
return nir_is_helper_invocation(b, 1);
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
nir_lower_load_helper_to_is_helper(nir_builder *b, nir_instr *instr, void *data)
|
||||
{
|
||||
if (instr->type != nir_instr_type_intrinsic)
|
||||
return false;
|
||||
|
||||
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
|
||||
nir_ssa_def *is_helper = *(nir_ssa_def**) data;
|
||||
switch (intrin->intrinsic) {
|
||||
case nir_intrinsic_demote:
|
||||
case nir_intrinsic_demote_if:
|
||||
/* insert is_helper at last top level occasion */
|
||||
if (is_helper == NULL) {
|
||||
is_helper = insert_is_helper(b, instr);
|
||||
*(nir_ssa_def**)data = is_helper;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
case nir_intrinsic_load_helper_invocation:
|
||||
/* Don't update data: as long as we didn't encounter any demote(),
|
||||
* we can insert new is_helper() intrinsics. These are placed at
|
||||
* top-level blocks to ensure correct behavior w.r.t. loops */
|
||||
if (is_helper == NULL)
|
||||
is_helper = insert_is_helper(b, instr);
|
||||
nir_ssa_def_rewrite_uses_ssa(&intrin->dest.ssa, is_helper);
|
||||
nir_instr_remove_v(instr);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Optimize discard and demote opcodes.
|
||||
*
|
||||
|
|
@ -119,6 +169,18 @@ nir_lower_discard_or_demote(nir_shader *shader,
|
|||
nir_metadata_all,
|
||||
NULL);
|
||||
shader->info.fs.uses_demote = false;
|
||||
} else if (shader->info.fs.uses_demote &&
|
||||
BITSET_TEST(shader->info.system_values_read,
|
||||
nir_system_value_from_intrinsic(nir_intrinsic_load_helper_invocation))) {
|
||||
/* load_helper needs to preserve the value (whether an invocation is
|
||||
* a helper lane) from the beginning of the shader. */
|
||||
nir_ssa_def *is_helper = NULL;
|
||||
progress = nir_shader_instructions_pass(shader,
|
||||
nir_lower_load_helper_to_is_helper,
|
||||
nir_metadata_all,
|
||||
&is_helper);
|
||||
BITSET_CLEAR(shader->info.system_values_read,
|
||||
nir_system_value_from_intrinsic(nir_intrinsic_load_helper_invocation));
|
||||
}
|
||||
|
||||
/* Validate again that if uses_demote is set, uses_discard is also be set. */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue