Mesa (staging/20.1): spirv: fix emitting switch cases that directly jump to the merge block

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Sep 28 16:23:42 UTC 2020


Module: Mesa
Branch: staging/20.1
Commit: db4a29d078fcfacb434d9c12027da9ec684d64d4
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=db4a29d078fcfacb434d9c12027da9ec684d64d4

Author: Samuel Pitoiset <samuel.pitoiset at gmail.com>
Date:   Thu Sep  3 22:02:01 2020 +0200

spirv: fix emitting switch cases that directly jump to the merge block

As shown in the valid SPIR-V below, if one switch case statement
directly jumps to the merge block, it has no branches at all and
we have to reset the fall variable. Otherwise, it creates an
unintentional fallthrough.

       OpSelectionMerge %97 None
       OpSwitch %96 %97 1 %99 2 %100
%100 = OpLabel
%102 = OpAccessChain %_ptr_StorageBuffer_v4float %86 %uint_0 %uint_37
%103 = OpLoad %v4float %102
%104 = OpBitcast %v4uint %103
%105 = OpCompositeExtract %uint %104 0
%106 = OpShiftLeftLogical %uint %105 %uint_1
       OpBranch %97
 %99 = OpLabel
       OpBranch %97
 %97 = OpLabel
%107 = OpPhi %uint %uint_4 %75 %uint_5 %99 %106 %100

This fixes serious corruption in Horizon Zero Dawn.

v2: Changed the code to skip the entire if-block instead of resetting
    the fallthrough variable.

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/3460
Cc: mesa-stable
Signed-off-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
Signed-off-by: Bas Nieuwenhuizen <bas at basnieuwenhuizen.nl>
Reviewed-by: Daniel Schürmann <daniel at schuermann.dev>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6590>
(cherry picked from commit 57fba85da408dd4ec98508b5106c156d616b5602)

---

 .pick_status.json            | 2 +-
 src/compiler/spirv/vtn_cfg.c | 7 +++++++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/.pick_status.json b/.pick_status.json
index 4b56dbf333c..f6a950f52e4 100644
--- a/.pick_status.json
+++ b/.pick_status.json
@@ -5566,7 +5566,7 @@
         "description": "spirv: fix emitting switch cases that directly jump to the merge block",
         "nominated": true,
         "nomination_type": 0,
-        "resolution": 0,
+        "resolution": 1,
         "master_sha": null,
         "because_sha": null
     },
diff --git a/src/compiler/spirv/vtn_cfg.c b/src/compiler/spirv/vtn_cfg.c
index 4a07b35be53..3f157db009b 100644
--- a/src/compiler/spirv/vtn_cfg.c
+++ b/src/compiler/spirv/vtn_cfg.c
@@ -1285,6 +1285,13 @@ vtn_emit_cf_list(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);



More information about the mesa-commit mailing list