GLSL: Implement switch on ESSL 1.0.
Cannot use switch on legacy ESSL, fallback to plain branches.
This commit is contained in:
parent
bae76d7915
commit
4d79d634f5
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 j;
|
||||||
int _30;
|
int _30;
|
||||||
int _31;
|
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)
|
switch (vIndex)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
@ -37,6 +29,7 @@ void frag_main()
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
_30 = 2;
|
||||||
j = _30;
|
j = _30;
|
||||||
_31 = 0;
|
_31 = 0;
|
||||||
j = _31;
|
j = _31;
|
||||||
@ -45,6 +38,7 @@ void frag_main()
|
|||||||
case 1:
|
case 1:
|
||||||
case 11:
|
case 11:
|
||||||
{
|
{
|
||||||
|
_31 = 1;
|
||||||
j = _31;
|
j = _31;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
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;
|
||||||
|
}
|
@ -539,6 +539,9 @@ string CompilerGLSL::compile()
|
|||||||
backend.supports_extensions = true;
|
backend.supports_extensions = true;
|
||||||
backend.use_array_constructor = 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.
|
// Scan the SPIR-V to find trivial uses of extensions.
|
||||||
fixup_type_alias();
|
fixup_type_alias();
|
||||||
reorder_type_alias();
|
reorder_type_alias();
|
||||||
@ -13272,6 +13275,8 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
|
|||||||
// Order does not matter.
|
// Order does not matter.
|
||||||
if (!injected_block)
|
if (!injected_block)
|
||||||
block_declaration_order.push_back(block.default_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] = {};
|
case_constructs[block.default_block] = {};
|
||||||
}
|
}
|
||||||
@ -13282,12 +13287,25 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
|
|||||||
return is_unsigned_case ? convert_to_string(literal) : convert_to_string(int32_t(literal));
|
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 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,
|
// 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.
|
// 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
|
// 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.
|
// 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]) &&
|
if (flush_phi_required(block.self, block_declaration_order[i]) &&
|
||||||
flush_phi_required(block_declaration_order[i - 1], block_declaration_order[i]))
|
flush_phi_required(block_declaration_order[i - 1], block_declaration_order[i]))
|
||||||
@ -13341,7 +13359,7 @@ 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.
|
// 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();
|
bool degenerate_switch = block.default_block != block.merge_block && block.cases.empty();
|
||||||
|
|
||||||
if (degenerate_switch)
|
if (degenerate_switch || is_legacy_es())
|
||||||
{
|
{
|
||||||
// ESSL 1.0 is not guaranteed to support do/while.
|
// ESSL 1.0 is not guaranteed to support do/while.
|
||||||
if (is_legacy_es())
|
if (is_legacy_es())
|
||||||
@ -13365,8 +13383,21 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
|
|||||||
{
|
{
|
||||||
// Default case.
|
// Default case.
|
||||||
if (!degenerate_switch)
|
if (!degenerate_switch)
|
||||||
|
{
|
||||||
|
if (is_legacy_es())
|
||||||
|
statement("else");
|
||||||
|
else
|
||||||
statement("default:");
|
statement("default:");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (is_legacy_es())
|
||||||
|
{
|
||||||
|
statement((i ? "else " : ""), "if (",
|
||||||
|
to_legacy_case_label(block.condition, literals, label_suffix),
|
||||||
|
")");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (auto &case_literal : literals)
|
for (auto &case_literal : literals)
|
||||||
@ -13375,6 +13406,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
|
|||||||
statement("case ", to_case_label(case_literal, unsigned_case), label_suffix, ":");
|
statement("case ", to_case_label(case_literal, unsigned_case), label_suffix, ":");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto &case_block = get<SPIRBlock>(target_block);
|
auto &case_block = get<SPIRBlock>(target_block);
|
||||||
if (backend.support_case_fallthrough && i + 1 < num_blocks &&
|
if (backend.support_case_fallthrough && i + 1 < num_blocks &&
|
||||||
@ -13407,7 +13439,12 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
|
|||||||
statement("case ", to_case_label(case_literal, unsigned_case), label_suffix, ":");
|
statement("case ", to_case_label(case_literal, unsigned_case), label_suffix, ":");
|
||||||
|
|
||||||
if (block.default_block == block.next_block)
|
if (block.default_block == block.next_block)
|
||||||
|
{
|
||||||
|
if (is_legacy_es())
|
||||||
|
statement("else");
|
||||||
|
else
|
||||||
statement("default:");
|
statement("default:");
|
||||||
|
}
|
||||||
|
|
||||||
begin_scope();
|
begin_scope();
|
||||||
flush_phi(block.self, block.next_block);
|
flush_phi(block.self, block.next_block);
|
||||||
|
Loading…
Reference in New Issue
Block a user