spirv: fix emitting switch cases that directly jump to the merge block
[mesa.git] / src / compiler / spirv / vtn_cfg.c
index 9dc2a842da65ed859c52fe3c00b74444b8cb1aaf..a1573565b81eb6c13275c0fd76efdfe023370c50 100644 (file)
@@ -24,6 +24,7 @@
 #include "vtn_private.h"
 #include "spirv_info.h"
 #include "nir/nir_vla.h"
+#include "util/debug.h"
 
 static struct vtn_block *
 vtn_block(struct vtn_builder *b, uint32_t value_id)
@@ -1164,6 +1165,13 @@ vtn_emit_cf_list_structured(struct vtn_builder *b, struct list_head *cf_list,
          vtn_foreach_cf_node(case_node, &vtn_switch->cases) {
             struct vtn_case *cse = vtn_cf_node_as_case(case_node);
 
+            /* If this case jumps directly to the break block, we don't have
+             * to handle the case as the body is empty and doesn't fall
+             * through.
+             */
+            if (cse->block == vtn_switch->break_block)
+               continue;
+
             /* Figure out the condition */
             nir_ssa_def *cond =
                vtn_switch_case_condition(b, vtn_switch, sel, cse);
@@ -1329,6 +1337,12 @@ void
 vtn_function_emit(struct vtn_builder *b, struct vtn_function *func,
                   vtn_instruction_handler instruction_handler)
 {
+   static int force_unstructured = -1;
+   if (force_unstructured < 0) {
+      force_unstructured =
+         env_var_as_boolean("MESA_SPIRV_FORCE_UNSTRUCTURED", false);
+   }
+
    nir_builder_init(&b->nb, func->impl);
    b->func = func;
    b->nb.cursor = nir_after_cf_list(&func->impl->body);
@@ -1336,7 +1350,7 @@ vtn_function_emit(struct vtn_builder *b, struct vtn_function *func,
    b->has_loop_continue = false;
    b->phi_table = _mesa_pointer_hash_table_create(b);
 
-   if (b->shader->info.stage == MESA_SHADER_KERNEL) {
+   if (b->shader->info.stage == MESA_SHADER_KERNEL || force_unstructured) {
       b->func->impl->structured = false;
       vtn_emit_cf_func_unstructured(b, func, instruction_handler);
    } else {