From: Giovanni Mascellani gmascellani@codeweavers.com
The SPIR-V backend generates invalid SPIR-V code when VSIR has dead code (except for NOPs). --- libs/vkd3d-shader/ir.c | 70 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 6d7c89653..3e78e4f92 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -1260,6 +1260,73 @@ static enum vkd3d_result instruction_array_normalise_flat_constants(struct vkd3d return VKD3D_OK; }
+static void remove_dead_code(struct vkd3d_shader_parser *parser) +{ + size_t i, depth = 0; + bool dead = false; + + for (i = 0; i < parser->instructions.count; ++i) + { + struct vkd3d_shader_instruction *ins = &parser->instructions.elements[i]; + + switch (ins->handler_idx) + { + case VKD3DSIH_IF: + case VKD3DSIH_LOOP: + case VKD3DSIH_SWITCH: + if (dead) + { + vkd3d_shader_instruction_make_nop(ins); + ++depth; + } + break; + + case VKD3DSIH_ENDIF: + case VKD3DSIH_ENDLOOP: + case VKD3DSIH_ENDSWITCH: + if (dead) + { + if (depth > 0) + { + vkd3d_shader_instruction_make_nop(ins); + --depth; + } + else + { + dead = false; + } + } + break; + + case VKD3DSIH_BREAK: + case VKD3DSIH_RET: + case VKD3DSIH_CONTINUE: + if (!dead) + { + dead = true; + depth = 0; + } + break; + + case VKD3DSIH_CASE: + case VKD3DSIH_DEFAULT: + if (dead) + { + if (depth == 0) + dead = false; + else + vkd3d_shader_instruction_make_nop(ins); + } + break; + + default: + if (dead) + vkd3d_shader_instruction_make_nop(ins); + break; + } + } +} + enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, const struct vkd3d_shader_compile_info *compile_info) { @@ -1287,6 +1354,9 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, if (result >= 0) result = instruction_array_normalise_flat_constants(parser);
+ if (result >= 0) + remove_dead_code(parser); + if (result >= 0 && TRACE_ON()) vkd3d_shader_trace(instructions, &parser->shader_version);