Merge pull request #1410 from KhronosGroup/fix-1406

GLSL: Support switch more properly in legacy ESSL
This commit is contained in:
Hans-Kristian Arntzen 2020-06-29 15:22:39 +02:00 committed by GitHub
commit b1082c10af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 334 additions and 18 deletions

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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();

View File

@ -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.