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:
authorHans-Kristian Arntzen <post@arntzen-software.no>2020-06-29 16:22:39 +0300
committerGitHub <noreply@github.com>2020-06-29 16:22:39 +0300
commitb1082c10afe15eef03e8b12d66008388ce2a468c (patch)
treeec1e4eff6abb5a99878fd0ca52dd69ec4dfbdd4d
parent42096ca4a124f8700052e949a5c6443335d124c4 (diff)
parent4d79d634f5d03e4a0bc50f518c476793f20370c9 (diff)
Merge pull request #1410 from KhronosGroup/fix-14062020-06-29
GLSL: Support switch more properly in legacy ESSL
-rw-r--r--reference/opt/shaders/legacy/fragment/switch.legacy.frag77
-rw-r--r--reference/shaders-hlsl-no-opt/asm/frag/switch-block-case-fallthrough.asm.invalid.frag10
-rw-r--r--reference/shaders-no-opt/legacy/frag/switch-single-case-multiple-exit-cfg.legacy.asm.frag24
-rw-r--r--reference/shaders/legacy/fragment/switch.legacy.frag78
-rw-r--r--shaders-no-opt/legacy/frag/switch-single-case-multiple-exit-cfg.legacy.asm.frag57
-rw-r--r--shaders/legacy/fragment/switch.legacy.frag43
-rw-r--r--spirv_glsl.cpp61
-rwxr-xr-xtest_shaders.py2
8 files changed, 334 insertions, 18 deletions
diff --git a/reference/opt/shaders/legacy/fragment/switch.legacy.frag b/reference/opt/shaders/legacy/fragment/switch.legacy.frag
new file mode 100644
index 00000000..21a4d673
--- /dev/null
+++ b/reference/opt/shaders/legacy/fragment/switch.legacy.frag
@@ -0,0 +1,77 @@
+#version 100
+precision mediump float;
+precision highp int;
+
+varying highp float vIndexF;
+
+void main()
+{
+ int _13 = int(vIndexF);
+ highp vec4 _65;
+ highp vec4 _66;
+ highp vec4 _68;
+ for (int SPIRV_Cross_Dummy = 0; SPIRV_Cross_Dummy < 1; SPIRV_Cross_Dummy++)
+ {
+ if (_13 == 2)
+ {
+ _68 = vec4(0.0, 2.0, 3.0, 4.0);
+ break;
+ }
+ else if ((_13 == 4) || (_13 == 5))
+ {
+ _68 = vec4(1.0, 2.0, 3.0, 4.0);
+ break;
+ }
+ else if ((_13 == 8) || (_13 == 9))
+ {
+ _68 = vec4(40.0, 20.0, 30.0, 40.0);
+ break;
+ }
+ else if (_13 == 10)
+ {
+ _65 = vec4(10.0);
+ highp vec4 _45 = _65 + vec4(1.0);
+ _66 = _45;
+ highp vec4 _48 = _66 + vec4(2.0);
+ _68 = _48;
+ break;
+ }
+ else if (_13 == 11)
+ {
+ _65 = vec4(0.0);
+ highp vec4 _45 = _65 + vec4(1.0);
+ _66 = _45;
+ highp vec4 _48 = _66 + vec4(2.0);
+ _68 = _48;
+ break;
+ }
+ else if (_13 == 12)
+ {
+ _66 = vec4(0.0);
+ highp vec4 _48 = _66 + vec4(2.0);
+ _68 = _48;
+ break;
+ }
+ else
+ {
+ _68 = vec4(10.0, 20.0, 30.0, 40.0);
+ break;
+ }
+ }
+ highp vec4 _70;
+ for (int SPIRV_Cross_Dummy = 0; SPIRV_Cross_Dummy < 1; SPIRV_Cross_Dummy++)
+ {
+ if ((_13 == 10) || (_13 == 20))
+ {
+ _70 = vec4(40.0);
+ break;
+ }
+ else
+ {
+ _70 = vec4(20.0);
+ break;
+ }
+ }
+ gl_FragData[0] = _68 + _70;
+}
+
diff --git a/reference/shaders-hlsl-no-opt/asm/frag/switch-block-case-fallthrough.asm.invalid.frag b/reference/shaders-hlsl-no-opt/asm/frag/switch-block-case-fallthrough.asm.invalid.frag
index ba66ccf6..19af59d3 100644
--- a/reference/shaders-hlsl-no-opt/asm/frag/switch-block-case-fallthrough.asm.invalid.frag
+++ b/reference/shaders-hlsl-no-opt/asm/frag/switch-block-case-fallthrough.asm.invalid.frag
@@ -17,14 +17,6 @@ void frag_main()
int j;
int _30;
int _31;
- if (vIndex != 0 && vIndex != 1 && vIndex != 11 && vIndex != 2 && vIndex != 3 && vIndex != 4 && vIndex != 5)
- {
- _30 = 2;
- }
- if (vIndex == 1 || vIndex == 11)
- {
- _31 = 1;
- }
switch (vIndex)
{
case 0:
@@ -37,6 +29,7 @@ void frag_main()
}
default:
{
+ _30 = 2;
j = _30;
_31 = 0;
j = _31;
@@ -45,6 +38,7 @@ void frag_main()
case 1:
case 11:
{
+ _31 = 1;
j = _31;
break;
}
diff --git a/reference/shaders-no-opt/legacy/frag/switch-single-case-multiple-exit-cfg.legacy.asm.frag b/reference/shaders-no-opt/legacy/frag/switch-single-case-multiple-exit-cfg.legacy.asm.frag
new file mode 100644
index 00000000..d36e7827
--- /dev/null
+++ b/reference/shaders-no-opt/legacy/frag/switch-single-case-multiple-exit-cfg.legacy.asm.frag
@@ -0,0 +1,24 @@
+#version 100
+precision mediump float;
+precision highp int;
+
+vec2 _19;
+
+void main()
+{
+ highp vec2 _30;
+ for (int SPIRV_Cross_Dummy = 0; SPIRV_Cross_Dummy < 1; SPIRV_Cross_Dummy++)
+ {
+ if (gl_FragCoord.x != gl_FragCoord.x)
+ {
+ _30 = _19;
+ break;
+ }
+ highp vec2 _29 = _19;
+ _29.y = _19.y;
+ _30 = _29;
+ break;
+ }
+ gl_FragData[0] = vec4(_30, 1.0, 1.0);
+}
+
diff --git a/reference/shaders/legacy/fragment/switch.legacy.frag b/reference/shaders/legacy/fragment/switch.legacy.frag
new file mode 100644
index 00000000..9960ce7e
--- /dev/null
+++ b/reference/shaders/legacy/fragment/switch.legacy.frag
@@ -0,0 +1,78 @@
+#version 100
+precision mediump float;
+precision highp int;
+
+varying highp float vIndexF;
+
+void main()
+{
+ int vIndex = int(vIndexF);
+ highp vec4 v = vec4(0.0);
+ for (int SPIRV_Cross_Dummy = 0; SPIRV_Cross_Dummy < 1; SPIRV_Cross_Dummy++)
+ {
+ if (vIndex == 2)
+ {
+ v = vec4(0.0, 2.0, 3.0, 4.0);
+ break;
+ }
+ else if ((vIndex == 4) || (vIndex == 5))
+ {
+ v = vec4(1.0, 2.0, 3.0, 4.0);
+ break;
+ }
+ else if ((vIndex == 8) || (vIndex == 9))
+ {
+ v = vec4(40.0, 20.0, 30.0, 40.0);
+ break;
+ }
+ else if (vIndex == 10)
+ {
+ v = vec4(10.0);
+ highp vec4 _43 = v;
+ highp vec4 _44 = vec4(1.0);
+ highp vec4 _45 = _43 + _44;
+ v = _45;
+ highp vec4 _46 = v;
+ highp vec4 _47 = vec4(2.0);
+ highp vec4 _48 = _46 + _47;
+ v = _48;
+ break;
+ }
+ else if (vIndex == 11)
+ {
+ highp vec4 _43 = v;
+ highp vec4 _44 = vec4(1.0);
+ highp vec4 _45 = _43 + _44;
+ v = _45;
+ highp vec4 _46 = v;
+ highp vec4 _47 = vec4(2.0);
+ highp vec4 _48 = _46 + _47;
+ v = _48;
+ break;
+ }
+ else if (vIndex == 12)
+ {
+ highp vec4 _46 = v;
+ highp vec4 _47 = vec4(2.0);
+ highp vec4 _48 = _46 + _47;
+ v = _48;
+ break;
+ }
+ else
+ {
+ v = vec4(10.0, 20.0, 30.0, 40.0);
+ break;
+ }
+ }
+ highp vec4 w = vec4(20.0);
+ for (int SPIRV_Cross_Dummy = 0; SPIRV_Cross_Dummy < 1; SPIRV_Cross_Dummy++)
+ {
+ if ((vIndex == 10) || (vIndex == 20))
+ {
+ w = vec4(40.0);
+ break;
+ }
+ }
+ gl_FragData[0] = v + w;
+}
+
diff --git a/shaders-no-opt/legacy/frag/switch-single-case-multiple-exit-cfg.legacy.asm.frag b/shaders-no-opt/legacy/frag/switch-single-case-multiple-exit-cfg.legacy.asm.frag
new file mode 100644
index 00000000..d2bd15a9
--- /dev/null
+++ b/shaders-no-opt/legacy/frag/switch-single-case-multiple-exit-cfg.legacy.asm.frag
@@ -0,0 +1,57 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 54
+; Schema: 0
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main" %gl_FragCoord %_GLF_color
+ OpExecutionMode %main OriginUpperLeft
+ OpSource ESSL 310
+ OpName %main "main"
+ OpName %gl_FragCoord "gl_FragCoord"
+ OpName %_GLF_color "_GLF_color"
+ OpDecorate %gl_FragCoord BuiltIn FragCoord
+ OpDecorate %_GLF_color Location 0
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %int = OpTypeInt 32 1
+ %int_0 = OpConstant %int 0
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
+ %uint = OpTypeInt 32 0
+ %uint_0 = OpConstant %uint 0
+%_ptr_Input_float = OpTypePointer Input %float
+ %bool = OpTypeBool
+ %v2float = OpTypeVector %float 2
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %_GLF_color = OpVariable %_ptr_Output_v4float Output
+ %float_1 = OpConstant %float 1
+ %52 = OpUndef %v2float
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ OpSelectionMerge %9 None
+ OpSwitch %int_0 %8
+ %8 = OpLabel
+ %17 = OpAccessChain %_ptr_Input_float %gl_FragCoord %uint_0
+ %18 = OpLoad %float %17
+ %22 = OpFOrdNotEqual %bool %18 %18
+ OpSelectionMerge %24 None
+ OpBranchConditional %22 %23 %24
+ %23 = OpLabel
+ OpBranch %9
+ %24 = OpLabel
+ %33 = OpCompositeExtract %float %52 1
+ %51 = OpCompositeInsert %v2float %33 %52 1
+ OpBranch %9
+ %9 = OpLabel
+ %53 = OpPhi %v2float %52 %23 %51 %24
+ %42 = OpCompositeExtract %float %53 0
+ %43 = OpCompositeExtract %float %53 1
+ %48 = OpCompositeConstruct %v4float %42 %43 %float_1 %float_1
+ OpStore %_GLF_color %48
+ OpReturn
+ OpFunctionEnd
diff --git a/shaders/legacy/fragment/switch.legacy.frag b/shaders/legacy/fragment/switch.legacy.frag
new file mode 100644
index 00000000..d5117981
--- /dev/null
+++ b/shaders/legacy/fragment/switch.legacy.frag
@@ -0,0 +1,43 @@
+#version 450
+
+layout(location = 0) out vec4 FragColor;
+layout(location = 0) in float vIndexF;
+
+void main()
+{
+ int vIndex = int(vIndexF);
+ vec4 v = vec4(0.0);
+ switch (vIndex)
+ {
+ case 2:
+ v = vec4(0, 2, 3, 4);
+ break;
+ case 4:
+ case 5:
+ v = vec4(1, 2, 3, 4);
+ break;
+ case 8:
+ case 9:
+ v = vec4(40, 20, 30, 40);
+ break;
+ case 10:
+ v = vec4(10.0);
+ case 11:
+ v += 1.0;
+ case 12:
+ v += 2.0;
+ break;
+ default:
+ v = vec4(10, 20, 30, 40);
+ break;
+ }
+
+ vec4 w = vec4(20.0);
+ switch (vIndex)
+ {
+ case 10:
+ case 20:
+ w = vec4(40.0);
+ }
+ FragColor = v + w;
+}
diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp
index 8d8241e6..5f2a48f0 100644
--- a/spirv_glsl.cpp
+++ b/spirv_glsl.cpp
@@ -540,6 +540,9 @@ string CompilerGLSL::compile()
backend.supports_extensions = true;
backend.use_array_constructor = true;
+ if (is_legacy_es())
+ backend.support_case_fallthrough = false;
+
// Scan the SPIR-V to find trivial uses of extensions.
fixup_type_alias();
reorder_type_alias();
@@ -13295,6 +13298,8 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
// Order does not matter.
if (!injected_block)
block_declaration_order.push_back(block.default_block);
+ else if (is_legacy_es())
+ SPIRV_CROSS_THROW("Default case label fallthrough to other case label is not supported in ESSL 1.0.");
case_constructs[block.default_block] = {};
}
@@ -13305,12 +13310,25 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
return is_unsigned_case ? convert_to_string(literal) : convert_to_string(int32_t(literal));
};
+ const auto to_legacy_case_label = [&](uint32_t condition, const SmallVector<uint32_t> &labels, const char *suffix) -> string {
+ string ret;
+ size_t count = labels.size();
+ for (size_t i = 0; i < count; i++)
+ {
+ if (i)
+ ret += " || ";
+ ret += join(count > 1 ? "(" : "", to_enclosed_expression(condition), " == ", labels[i], suffix,
+ count > 1 ? ")" : "");
+ }
+ return ret;
+ };
+
// We need to deal with a complex scenario for OpPhi. If we have case-fallthrough and Phi in the picture,
// we need to flush phi nodes outside the switch block in a branch,
// and skip any Phi handling inside the case label to make fall-through work as expected.
// This kind of code-gen is super awkward and it's a last resort. Normally we would want to handle this
// inside the case label if at all possible.
- for (size_t i = 1; i < num_blocks; i++)
+ for (size_t i = 1; backend.support_case_fallthrough && i < num_blocks; i++)
{
if (flush_phi_required(block.self, block_declaration_order[i]) &&
flush_phi_required(block_declaration_order[i - 1], block_declaration_order[i]))
@@ -13364,8 +13382,14 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &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.empty();
- if (degenerate_switch)
- statement("do");
+ if (degenerate_switch || is_legacy_es())
+ {
+ // ESSL 1.0 is not guaranteed to support do/while.
+ if (is_legacy_es())
+ statement("for (int SPIRV_Cross_Dummy = 0; SPIRV_Cross_Dummy < 1; SPIRV_Cross_Dummy++)");
+ else
+ statement("do");
+ }
else
{
emit_block_hints(block);
@@ -13382,14 +13406,28 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
{
// Default case.
if (!degenerate_switch)
- statement("default:");
+ {
+ if (is_legacy_es())
+ statement("else");
+ else
+ statement("default:");
+ }
}
else
{
- for (auto &case_literal : literals)
+ if (is_legacy_es())
{
- // 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((i ? "else " : ""), "if (",
+ to_legacy_case_label(block.condition, literals, label_suffix),
+ ")");
+ }
+ else
+ {
+ 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, ":");
+ }
}
}
@@ -13424,7 +13462,12 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
statement("case ", to_case_label(case_literal, unsigned_case), label_suffix, ":");
if (block.default_block == block.next_block)
- statement("default:");
+ {
+ if (is_legacy_es())
+ statement("else");
+ else
+ statement("default:");
+ }
begin_scope();
flush_phi(block.self, block.next_block);
@@ -13433,7 +13476,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
}
}
- if (degenerate_switch)
+ if (degenerate_switch && !is_legacy_es())
end_scope_decl("while(false)");
else
end_scope();
diff --git a/test_shaders.py b/test_shaders.py
index c0130bf4..b4558734 100755
--- a/test_shaders.py
+++ b/test_shaders.py
@@ -492,7 +492,7 @@ def cross_compile(shader, vulkan, spirv, invalid_spirv, eliminate, is_legacy, fl
remove_file(glsl_path)
glsl_path = None
- if vulkan or spirv:
+ if (vulkan or spirv) and (not is_legacy):
subprocess.check_call([spirv_cross_path, '--entry', 'main', '--vulkan-semantics', '--output', vulkan_glsl_path, spirv_path] + extra_args)
validate_shader(vulkan_glsl_path, True, paths)
# SPIR-V shaders might just want to validate Vulkan GLSL output, we don't always care about the output.