microsoft/spirv_to_dxil: Fix discard to demote + return pass

While SPIR-V's OpKill is block terminating, the converted discard
intrinsic is not block terminating. This can lead to issues where
instruction could be placed after discard.

This patch adds an extra pass that drops all instructions after discard
before we convert discards.

Reviewed-by: Jesse Natalie <jenatali@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17474>
This commit is contained in:
Enrico Galli 2022-07-11 14:15:40 -07:00 committed by Marge Bot
parent ed6c346155
commit 1f0d27e45f
1 changed files with 34 additions and 1 deletions

View File

@ -2033,6 +2033,36 @@ dxil_nir_fix_io_uint_type(nir_shader *s, uint64_t in_mask, uint64_t out_mask)
return progress;
}
struct remove_after_discard_state {
struct nir_block *active_block;
};
static bool
remove_after_discard(struct nir_builder *builder, nir_instr *instr,
void *cb_data)
{
struct remove_after_discard_state *state = cb_data;
if (instr->block == state->active_block) {
nir_instr_remove_v(instr);
return true;
}
if (instr->type != nir_instr_type_intrinsic)
return false;
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
if (intr->intrinsic != nir_intrinsic_discard &&
intr->intrinsic != nir_intrinsic_terminate &&
intr->intrinsic != nir_intrinsic_discard_if &&
intr->intrinsic != nir_intrinsic_terminate_if)
return false;
state->active_block = instr->block;
return false;
}
static bool
lower_kill(struct nir_builder *builder, nir_instr *instr, void *_cb_data)
{
@ -2069,7 +2099,10 @@ dxil_nir_lower_discard_and_terminate(nir_shader *s)
// This pass only works if all functions have been inlined
assert(exec_list_length(&s->functions) == 1);
struct remove_after_discard_state state;
state.active_block = NULL;
nir_shader_instructions_pass(s, remove_after_discard, nir_metadata_none,
&state);
return nir_shader_instructions_pass(s, lower_kill, nir_metadata_none,
NULL);
}