Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/KhronosGroup/SPIRV-Cross.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastián Aedo <saedo@codeweavers.com>2021-11-18 22:08:59 +0300
committerSebastián Aedo <saedo@codeweavers.com>2021-11-26 21:54:56 +0300
commit6d8302ef14d603f5e6171ea17048ad04e18c3a80 (patch)
tree750e74f45782da3187b498b2d3e7909b659e65ae
parent37dfb3f45f4fc47c841f81e618c602f6f3de0f17 (diff)
MSL: Add 64 bit switch support
Add 64 bit switch support for MSL version 2.2. * Also fixes a wrong endianness conversion. Signed-off-by: Sebastián Aedo <saedo@codeweavers.com>
-rw-r--r--reference/opt/shaders-msl/asm/frag/switch-different-sizes.asm.frag9
-rw-r--r--reference/opt/shaders-msl/asm/frag/switch-long-case.asm.msl22.frag9
-rw-r--r--reference/opt/shaders-msl/asm/frag/switch-unsigned-long-case.asm.msl22.frag9
-rw-r--r--reference/opt/shaders/asm/frag/switch-preserve-sign-extension.asm.frag9
-rw-r--r--reference/shaders-msl/asm/frag/switch-different-sizes.asm.frag78
-rw-r--r--reference/shaders-msl/asm/frag/switch-long-case.asm.msl22.frag27
-rw-r--r--reference/shaders-msl/asm/frag/switch-unsigned-long-case.asm.msl22.frag27
-rw-r--r--reference/shaders/asm/frag/switch-preserve-sign-extension.asm.frag27
-rw-r--r--shaders-msl/asm/frag/switch-different-sizes.asm.frag106
-rw-r--r--shaders-msl/asm/frag/switch-long-case.asm.msl22.frag48
-rw-r--r--shaders-msl/asm/frag/switch-unsigned-long-case.asm.msl22.frag48
-rw-r--r--shaders/asm/frag/switch-preserve-sign-extension.asm.frag44
-rw-r--r--spirv_glsl.cpp49
-rw-r--r--spirv_glsl.hpp1
-rw-r--r--spirv_msl.cpp1
-rw-r--r--spirv_parser.cpp2
16 files changed, 474 insertions, 20 deletions
diff --git a/reference/opt/shaders-msl/asm/frag/switch-different-sizes.asm.frag b/reference/opt/shaders-msl/asm/frag/switch-different-sizes.asm.frag
new file mode 100644
index 00000000..92ac1d9f
--- /dev/null
+++ b/reference/opt/shaders-msl/asm/frag/switch-different-sizes.asm.frag
@@ -0,0 +1,9 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+fragment void main0()
+{
+}
+
diff --git a/reference/opt/shaders-msl/asm/frag/switch-long-case.asm.msl22.frag b/reference/opt/shaders-msl/asm/frag/switch-long-case.asm.msl22.frag
new file mode 100644
index 00000000..92ac1d9f
--- /dev/null
+++ b/reference/opt/shaders-msl/asm/frag/switch-long-case.asm.msl22.frag
@@ -0,0 +1,9 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+fragment void main0()
+{
+}
+
diff --git a/reference/opt/shaders-msl/asm/frag/switch-unsigned-long-case.asm.msl22.frag b/reference/opt/shaders-msl/asm/frag/switch-unsigned-long-case.asm.msl22.frag
new file mode 100644
index 00000000..92ac1d9f
--- /dev/null
+++ b/reference/opt/shaders-msl/asm/frag/switch-unsigned-long-case.asm.msl22.frag
@@ -0,0 +1,9 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+fragment void main0()
+{
+}
+
diff --git a/reference/opt/shaders/asm/frag/switch-preserve-sign-extension.asm.frag b/reference/opt/shaders/asm/frag/switch-preserve-sign-extension.asm.frag
new file mode 100644
index 00000000..41b98085
--- /dev/null
+++ b/reference/opt/shaders/asm/frag/switch-preserve-sign-extension.asm.frag
@@ -0,0 +1,9 @@
+#version 330
+#ifdef GL_ARB_shading_language_420pack
+#extension GL_ARB_shading_language_420pack : require
+#endif
+
+void main()
+{
+}
+
diff --git a/reference/shaders-msl/asm/frag/switch-different-sizes.asm.frag b/reference/shaders-msl/asm/frag/switch-different-sizes.asm.frag
new file mode 100644
index 00000000..1ee9eebf
--- /dev/null
+++ b/reference/shaders-msl/asm/frag/switch-different-sizes.asm.frag
@@ -0,0 +1,78 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+fragment void main0()
+{
+ int sw0 = 42;
+ int result = 0;
+ switch (sw0)
+ {
+ case -42:
+ {
+ result = 42;
+ }
+ case 420:
+ {
+ result = 420;
+ }
+ case -1234:
+ {
+ result = 420;
+ break;
+ }
+ }
+ char sw1 = char(10);
+ switch (sw1)
+ {
+ case -42:
+ {
+ result = 42;
+ }
+ case 42:
+ {
+ result = 420;
+ }
+ case -123:
+ {
+ result = 512;
+ break;
+ }
+ }
+ short sw2 = short(10);
+ switch (sw2)
+ {
+ case -42:
+ {
+ result = 42;
+ }
+ case 42:
+ {
+ result = 420;
+ }
+ case -1234:
+ {
+ result = 512;
+ break;
+ }
+ }
+ short sw3 = short(10);
+ switch (sw3)
+ {
+ case -42:
+ {
+ result = 42;
+ }
+ case 42:
+ {
+ result = 420;
+ }
+ case -1234:
+ {
+ result = 512;
+ break;
+ }
+ }
+}
+
diff --git a/reference/shaders-msl/asm/frag/switch-long-case.asm.msl22.frag b/reference/shaders-msl/asm/frag/switch-long-case.asm.msl22.frag
new file mode 100644
index 00000000..5ec002e7
--- /dev/null
+++ b/reference/shaders-msl/asm/frag/switch-long-case.asm.msl22.frag
@@ -0,0 +1,27 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+fragment void main0()
+{
+ long sw = 42l;
+ int result = 0;
+ switch (sw)
+ {
+ case -42l:
+ {
+ result = 42;
+ }
+ case 420l:
+ {
+ result = 420;
+ }
+ case -34359738368l:
+ {
+ result = 420;
+ break;
+ }
+ }
+}
+
diff --git a/reference/shaders-msl/asm/frag/switch-unsigned-long-case.asm.msl22.frag b/reference/shaders-msl/asm/frag/switch-unsigned-long-case.asm.msl22.frag
new file mode 100644
index 00000000..2bf44c20
--- /dev/null
+++ b/reference/shaders-msl/asm/frag/switch-unsigned-long-case.asm.msl22.frag
@@ -0,0 +1,27 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+fragment void main0()
+{
+ ulong sw = 42ul;
+ int result = 0;
+ switch (sw)
+ {
+ case 42ul:
+ {
+ result = 42;
+ }
+ case 420ul:
+ {
+ result = 420;
+ }
+ case 343597383680ul:
+ {
+ result = 420;
+ break;
+ }
+ }
+}
+
diff --git a/reference/shaders/asm/frag/switch-preserve-sign-extension.asm.frag b/reference/shaders/asm/frag/switch-preserve-sign-extension.asm.frag
new file mode 100644
index 00000000..08921e1e
--- /dev/null
+++ b/reference/shaders/asm/frag/switch-preserve-sign-extension.asm.frag
@@ -0,0 +1,27 @@
+#version 330
+#ifdef GL_ARB_shading_language_420pack
+#extension GL_ARB_shading_language_420pack : require
+#endif
+
+void main()
+{
+ int sw = 42;
+ int result = 0;
+ switch (sw)
+ {
+ case -42:
+ {
+ result = 42;
+ }
+ case 420:
+ {
+ result = 420;
+ }
+ case -1234:
+ {
+ result = 420;
+ break;
+ }
+ }
+}
+
diff --git a/shaders-msl/asm/frag/switch-different-sizes.asm.frag b/shaders-msl/asm/frag/switch-different-sizes.asm.frag
new file mode 100644
index 00000000..ee6daa3d
--- /dev/null
+++ b/shaders-msl/asm/frag/switch-different-sizes.asm.frag
@@ -0,0 +1,106 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Google Shaderc over Glslang; 10
+; Bound: 42
+; Schema: 0
+ OpCapability Shader
+ OpCapability Int8
+ OpCapability Int16
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main"
+ OpExecutionMode %main OriginUpperLeft
+ OpSource GLSL 330
+ OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
+ OpSourceExtension "GL_GOOGLE_include_directive"
+ OpName %main "main"
+ OpName %sw0 "sw0"
+ OpName %result "result"
+ OpName %sw1 "sw1"
+ OpName %sw2 "sw2"
+ OpName %sw3 "sw3"
+ OpDecorate %sw1 RelaxedPrecision
+ OpDecorate %21 RelaxedPrecision
+ OpDecorate %sw2 RelaxedPrecision
+ OpDecorate %29 RelaxedPrecision
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %int = OpTypeInt 32 1
+ %lowp_int = OpTypeInt 8 1
+ %highp_int = OpTypeInt 16 1
+ %_ptr_Function_int = OpTypePointer Function %int
+ %_ptr_Function_lowp_int = OpTypePointer Function %lowp_int
+ %_ptr_Function_highp_int = OpTypePointer Function %highp_int
+ %int_42 = OpConstant %int 42
+ %int_0 = OpConstant %int 0
+ %int_420 = OpConstant %int 420
+ %int_10 = OpConstant %int 10
+ %int_512 = OpConstant %int 512
+ %lowp_int_10 = OpConstant %lowp_int 10
+ %highp_int_10 = OpConstant %highp_int 10
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %sw0 = OpVariable %_ptr_Function_int Function
+ %result = OpVariable %_ptr_Function_int Function
+ %sw1 = OpVariable %_ptr_Function_lowp_int Function
+ %sw2 = OpVariable %_ptr_Function_highp_int Function
+ %sw3 = OpVariable %_ptr_Function_highp_int Function
+ OpStore %sw0 %int_42
+ OpStore %result %int_0
+ %12 = OpLoad %int %sw0
+ OpSelectionMerge %16 None
+ OpSwitch %12 %16 -42 %13 420 %14 -1234 %15
+ %13 = OpLabel
+ OpStore %result %int_42
+ OpBranch %14
+ %14 = OpLabel
+ OpStore %result %int_420
+ OpBranch %15
+ %15 = OpLabel
+ OpStore %result %int_420
+ OpBranch %16
+ %16 = OpLabel
+ OpStore %sw1 %lowp_int_10
+ %21 = OpLoad %lowp_int %sw1
+ OpSelectionMerge %25 None
+ OpSwitch %21 %25 -42 %22 42 %23 -123 %24
+ %22 = OpLabel
+ OpStore %result %int_42
+ OpBranch %23
+ %23 = OpLabel
+ OpStore %result %int_420
+ OpBranch %24
+ %24 = OpLabel
+ OpStore %result %int_512
+ OpBranch %25
+ %25 = OpLabel
+ OpStore %sw2 %highp_int_10
+ %29 = OpLoad %highp_int %sw2
+ OpSelectionMerge %33 None
+ OpSwitch %29 %33 -42 %30 42 %31 -1234 %32
+ %30 = OpLabel
+ OpStore %result %int_42
+ OpBranch %31
+ %31 = OpLabel
+ OpStore %result %int_420
+ OpBranch %32
+ %32 = OpLabel
+ OpStore %result %int_512
+ OpBranch %33
+ %33 = OpLabel
+ OpStore %sw3 %highp_int_10
+ %36 = OpLoad %highp_int %sw3
+ OpSelectionMerge %40 None
+ OpSwitch %36 %40 -42 %37 42 %38 -1234 %39
+ %37 = OpLabel
+ OpStore %result %int_42
+ OpBranch %38
+ %38 = OpLabel
+ OpStore %result %int_420
+ OpBranch %39
+ %39 = OpLabel
+ OpStore %result %int_512
+ OpBranch %40
+ %40 = OpLabel
+ OpReturn
+ OpFunctionEnd
diff --git a/shaders-msl/asm/frag/switch-long-case.asm.msl22.frag b/shaders-msl/asm/frag/switch-long-case.asm.msl22.frag
new file mode 100644
index 00000000..62f2dc68
--- /dev/null
+++ b/shaders-msl/asm/frag/switch-long-case.asm.msl22.frag
@@ -0,0 +1,48 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos SPIR-V Tools Assembler; 0
+; Bound: 21
+; Schema: 0
+ OpCapability Shader
+ OpCapability Int64
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main"
+ OpExecutionMode %main OriginUpperLeft
+ OpSource GLSL 330
+ OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
+ OpSourceExtension "GL_GOOGLE_include_directive"
+ OpName %main "main"
+ OpName %sw "sw"
+ OpName %result "result"
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %int = OpTypeInt 32 1
+ %long = OpTypeInt 64 1
+%_ptr_Function_int = OpTypePointer Function %int
+%_ptr_Function_long = OpTypePointer Function %long
+ %int_42 = OpConstant %int 42
+ %int_0 = OpConstant %int 0
+ %int_420 = OpConstant %int 420
+ %long_42 = OpConstant %long 42
+ %main = OpFunction %void None %6
+ %15 = OpLabel
+ %sw = OpVariable %_ptr_Function_long Function
+ %result = OpVariable %_ptr_Function_int Function
+ OpStore %sw %long_42
+ OpStore %result %int_0
+ %16 = OpLoad %long %sw
+ OpSelectionMerge %17 None
+ OpSwitch %16 %17 -42 %18 420 %19 -34359738368 %20
+ %18 = OpLabel
+ OpStore %result %int_42
+ OpBranch %19
+ %19 = OpLabel
+ OpStore %result %int_420
+ OpBranch %20
+ %20 = OpLabel
+ OpStore %result %int_420
+ OpBranch %17
+ %17 = OpLabel
+ OpReturn
+ OpFunctionEnd
diff --git a/shaders-msl/asm/frag/switch-unsigned-long-case.asm.msl22.frag b/shaders-msl/asm/frag/switch-unsigned-long-case.asm.msl22.frag
new file mode 100644
index 00000000..cea32b42
--- /dev/null
+++ b/shaders-msl/asm/frag/switch-unsigned-long-case.asm.msl22.frag
@@ -0,0 +1,48 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos SPIR-V Tools Assembler; 0
+; Bound: 21
+; Schema: 0
+ OpCapability Shader
+ OpCapability Int64
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main"
+ OpExecutionMode %main OriginUpperLeft
+ OpSource GLSL 330
+ OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
+ OpSourceExtension "GL_GOOGLE_include_directive"
+ OpName %main "main"
+ OpName %sw "sw"
+ OpName %result "result"
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %int = OpTypeInt 32 1
+ %long = OpTypeInt 64 0
+%_ptr_Function_int = OpTypePointer Function %int
+%_ptr_Function_long = OpTypePointer Function %long
+ %int_42 = OpConstant %int 42
+ %int_0 = OpConstant %int 0
+ %int_420 = OpConstant %int 420
+ %long_42 = OpConstant %long 42
+ %main = OpFunction %void None %6
+ %15 = OpLabel
+ %sw = OpVariable %_ptr_Function_long Function
+ %result = OpVariable %_ptr_Function_int Function
+ OpStore %sw %long_42
+ OpStore %result %int_0
+ %16 = OpLoad %long %sw
+ OpSelectionMerge %17 None
+ OpSwitch %16 %17 42 %18 420 %19 343597383680 %20
+ %18 = OpLabel
+ OpStore %result %int_42
+ OpBranch %19
+ %19 = OpLabel
+ OpStore %result %int_420
+ OpBranch %20
+ %20 = OpLabel
+ OpStore %result %int_420
+ OpBranch %17
+ %17 = OpLabel
+ OpReturn
+ OpFunctionEnd
diff --git a/shaders/asm/frag/switch-preserve-sign-extension.asm.frag b/shaders/asm/frag/switch-preserve-sign-extension.asm.frag
new file mode 100644
index 00000000..97140ee5
--- /dev/null
+++ b/shaders/asm/frag/switch-preserve-sign-extension.asm.frag
@@ -0,0 +1,44 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Google Shaderc over Glslang; 10
+; Bound: 19
+; Schema: 0
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main"
+ OpExecutionMode %main OriginUpperLeft
+ OpSource GLSL 330
+ OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
+ OpSourceExtension "GL_GOOGLE_include_directive"
+ OpName %main "main"
+ OpName %sw "sw"
+ OpName %result "result"
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %int = OpTypeInt 32 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_42 = OpConstant %int 42
+ %int_0 = OpConstant %int 0
+ %int_420 = OpConstant %int 420
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %sw = OpVariable %_ptr_Function_int Function
+ %result = OpVariable %_ptr_Function_int Function
+ OpStore %sw %int_42
+ OpStore %result %int_0
+ %12 = OpLoad %int %sw
+ OpSelectionMerge %16 None
+ OpSwitch %12 %16 -42 %13 420 %14 -1234 %15
+ %13 = OpLabel
+ OpStore %result %int_42
+ OpBranch %14
+ %14 = OpLabel
+ OpStore %result %int_420
+ OpBranch %15
+ %15 = OpLabel
+ OpStore %result %int_420
+ OpBranch %16
+ %16 = OpLabel
+ OpReturn
+ OpFunctionEnd
diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp
index 5c21518f..9ae5d966 100644
--- a/spirv_glsl.cpp
+++ b/spirv_glsl.cpp
@@ -14768,13 +14768,13 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
case SPIRBlock::MultiSelect:
{
auto &type = expression_type(block.condition);
- bool unsigned_case =
- type.basetype == SPIRType::UInt || type.basetype == SPIRType::UShort || type.basetype == SPIRType::UByte;
+ bool unsigned_case = type.basetype == SPIRType::UInt || type.basetype == SPIRType::UShort ||
+ type.basetype == SPIRType::UByte || type.basetype == SPIRType::UInt64;
if (block.merge == SPIRBlock::MergeNone)
SPIRV_CROSS_THROW("Switch statement is not structured");
- if (type.basetype == SPIRType::UInt64 || type.basetype == SPIRType::Int64)
+ if (!backend.support_64bit_switch && (type.basetype == SPIRType::UInt64 || type.basetype == SPIRType::Int64))
{
// SPIR-V spec suggests this is allowed, but we cannot support it in higher level languages.
SPIRV_CROSS_THROW("Cannot use 64-bit switch selectors.");
@@ -14783,6 +14783,10 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
const char *label_suffix = "";
if (type.basetype == SPIRType::UInt && backend.uint32_t_literal_suffix)
label_suffix = "u";
+ else if (type.basetype == SPIRType::Int64 && backend.support_64bit_switch)
+ label_suffix = "l";
+ else if (type.basetype == SPIRType::UInt64 && backend.support_64bit_switch)
+ label_suffix = "ul";
else if (type.basetype == SPIRType::UShort)
label_suffix = backend.uint16_t_literal_suffix;
else if (type.basetype == SPIRType::Short)
@@ -14795,9 +14799,9 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
statement("bool _", block.self, "_ladder_break = false;");
// Find all unique case constructs.
- unordered_map<uint32_t, SmallVector<uint32_t>> case_constructs;
+ unordered_map<uint32_t, SmallVector<uint64_t>> case_constructs;
SmallVector<uint32_t> block_declaration_order;
- SmallVector<uint32_t> literals_to_merge;
+ SmallVector<uint64_t> literals_to_merge;
// If a switch case branches to the default block for some reason, we can just remove that literal from consideration
// and let the default: block handle it.
@@ -14806,21 +14810,17 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
auto &cases = get_case_list(block);
for (auto &c : cases)
{
- // It's safe to cast to uint32_t since we actually do a check
- // previously that we're not using uint64_t as the switch selector.
- auto case_value = static_cast<uint32_t>(c.value);
-
if (c.block != block.next_block && c.block != block.default_block)
{
if (!case_constructs.count(c.block))
block_declaration_order.push_back(c.block);
- case_constructs[c.block].push_back(case_value);
+ case_constructs[c.block].push_back(c.value);
}
else if (c.block == block.next_block && block.default_block != block.next_block)
{
// We might have to flush phi inside specific case labels.
// If we can piggyback on default:, do so instead.
- literals_to_merge.push_back(case_value);
+ literals_to_merge.push_back(c.value);
}
}
@@ -14865,11 +14865,22 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
size_t num_blocks = block_declaration_order.size();
- const auto to_case_label = [](uint32_t literal, bool is_unsigned_case) -> string {
- return is_unsigned_case ? convert_to_string(literal) : convert_to_string(int32_t(literal));
+ const auto to_case_label = [](uint64_t literal, uint32_t width, bool is_unsigned_case) -> string
+ {
+ if (is_unsigned_case)
+ return convert_to_string(literal);
+
+ // For smaller cases, the literals are compiled as 32 bit wide
+ // literals so we don't need to care for all sizes specifically.
+ if (width <= 32)
+ {
+ return convert_to_string(int64_t(int32_t(literal)));
+ }
+
+ return convert_to_string(int64_t(literal));
};
- const auto to_legacy_case_label = [&](uint32_t condition, const SmallVector<uint32_t> &labels,
+ const auto to_legacy_case_label = [&](uint32_t condition, const SmallVector<uint64_t> &labels,
const char *suffix) -> string {
string ret;
size_t count = labels.size();
@@ -14911,7 +14922,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
auto &negative_literals = case_constructs[block_declaration_order[j]];
for (auto &case_label : negative_literals)
conditions.push_back(join(to_enclosed_expression(block.condition),
- " != ", to_case_label(case_label, unsigned_case)));
+ " != ", to_case_label(case_label, type.width, unsigned_case)));
}
statement("if (", merge(conditions, " && "), ")");
@@ -14925,7 +14936,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
conditions.reserve(literals.size());
for (auto &case_label : literals)
conditions.push_back(join(to_enclosed_expression(block.condition),
- " == ", to_case_label(case_label, unsigned_case)));
+ " == ", to_case_label(case_label, type.width, unsigned_case)));
statement("if (", merge(conditions, " || "), ")");
begin_scope();
flush_phi(block.self, target_block);
@@ -14940,7 +14951,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
// If there is only one default block, and no cases, this is a case where SPIRV-opt decided to emulate
// non-structured exits with the help of a switch block.
// This is buggy on FXC, so just emit the logical equivalent of a do { } while(false), which is more idiomatic.
- bool degenerate_switch = block.default_block != block.merge_block && block.cases_32bit.empty();
+ bool degenerate_switch = block.default_block != block.merge_block && cases.empty();
if (degenerate_switch || is_legacy_es())
{
@@ -14989,7 +15000,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
for (auto &case_literal : literals)
{
// The case label value must be sign-extended properly in SPIR-V, so we can assume 32-bit values here.
- statement("case ", to_case_label(case_literal, unsigned_case), label_suffix, ":");
+ statement("case ", to_case_label(case_literal, type.width, unsigned_case), label_suffix, ":");
}
}
}
@@ -15027,7 +15038,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
if ((header_merge_requires_phi && need_fallthrough_block) || !literals_to_merge.empty())
{
for (auto &case_literal : literals_to_merge)
- statement("case ", to_case_label(case_literal, unsigned_case), label_suffix, ":");
+ statement("case ", to_case_label(case_literal, type.width, unsigned_case), label_suffix, ":");
if (block.default_block == block.next_block)
{
diff --git a/spirv_glsl.hpp b/spirv_glsl.hpp
index 52362442..b34ed993 100644
--- a/spirv_glsl.hpp
+++ b/spirv_glsl.hpp
@@ -586,6 +586,7 @@ protected:
bool needs_row_major_load_workaround = false;
bool support_pointer_to_pointer = false;
bool support_precise_qualifier = false;
+ bool support_64bit_switch = false;
} backend;
void emit_struct(SPIRType &type);
diff --git a/spirv_msl.cpp b/spirv_msl.cpp
index fabf2e9c..ffa69bfe 100644
--- a/spirv_msl.cpp
+++ b/spirv_msl.cpp
@@ -1355,6 +1355,7 @@ string CompilerMSL::compile()
backend.nonuniform_qualifier = "";
backend.support_small_type_sampling_result = true;
backend.supports_empty_struct = true;
+ backend.support_64bit_switch = true;
// Allow Metal to use the array<T> template unless we force it off.
backend.can_return_array = !msl_options.force_native_arrays;
diff --git a/spirv_parser.cpp b/spirv_parser.cpp
index da39367d..4faf3ca0 100644
--- a/spirv_parser.cpp
+++ b/spirv_parser.cpp
@@ -1029,7 +1029,7 @@ void Parser::parse(const Instruction &instruction)
{
for (uint32_t i = 2; i + 3 <= length; i += 3)
{
- uint64_t value = (static_cast<uint64_t>(ops[i]) << 32) | ops[i + 1];
+ uint64_t value = (static_cast<uint64_t>(ops[i + 1]) << 32) | ops[i];
current_block->cases_64bit.push_back({ value, ops[i + 2] });
}
}