From 1f0d27e45f6f19f81e5ec6f3f8a82911d9ee38a9 Mon Sep 17 00:00:00 2001 From: Enrico Galli Date: Mon, 11 Jul 2022 14:15:40 -0700 Subject: [PATCH] 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 Part-of: --- src/microsoft/compiler/dxil_nir.c | 35 ++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/microsoft/compiler/dxil_nir.c b/src/microsoft/compiler/dxil_nir.c index 5e365e531b2..ff6a165dca2 100644 --- a/src/microsoft/compiler/dxil_nir.c +++ b/src/microsoft/compiler/dxil_nir.c @@ -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); }