Merge pull request #1410 from KhronosGroup/fix-1406
GLSL: Support switch more properly in legacy ESSL
This commit is contained in:
commit
b1082c10af
77
reference/opt/shaders/legacy/fragment/switch.legacy.frag
Normal file
77
reference/opt/shaders/legacy/fragment/switch.legacy.frag
Normal 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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
78
reference/shaders/legacy/fragment/switch.legacy.frag
Normal file
78
reference/shaders/legacy/fragment/switch.legacy.frag
Normal 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;
|
||||
}
|
||||
|
@ -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
|
43
shaders/legacy/fragment/switch.legacy.frag
Normal file
43
shaders/legacy/fragment/switch.legacy.frag
Normal 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;
|
||||
}
|
@ -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();
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user