Deal with switch case labels which share a block.
This commit is contained in:
parent
e59cc24495
commit
9d31154917
@ -0,0 +1,33 @@
|
|||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
precision highp int;
|
||||||
|
|
||||||
|
layout(location = 0) flat in mediump int vIndex;
|
||||||
|
layout(location = 0) out float FragColor;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
highp float _19;
|
||||||
|
switch (vIndex)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
_19 = 1.0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
_19 = 3.0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 8:
|
||||||
|
{
|
||||||
|
_19 = 8.0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FragColor = _19;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
|||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
precision highp int;
|
||||||
|
|
||||||
|
layout(location = 0) flat in mediump int vIndex;
|
||||||
|
layout(location = 0) out float FragColor;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
highp float _19;
|
||||||
|
switch (vIndex)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
_19 = 1.0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
_19 = 3.0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 8:
|
||||||
|
{
|
||||||
|
_19 = 8.0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FragColor = _19;
|
||||||
|
}
|
||||||
|
|
45
shaders/asm/frag/switch-label-shared-block.asm.frag
Normal file
45
shaders/asm/frag/switch-label-shared-block.asm.frag
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
; SPIR-V
|
||||||
|
; Version: 1.0
|
||||||
|
; Generator: Khronos Glslang Reference Front End; 6
|
||||||
|
; Bound: 28
|
||||||
|
; Schema: 0
|
||||||
|
OpCapability Shader
|
||||||
|
%1 = OpExtInstImport "GLSL.std.450"
|
||||||
|
OpMemoryModel Logical GLSL450
|
||||||
|
OpEntryPoint Fragment %main "main" %vIndex %FragColor
|
||||||
|
OpExecutionMode %main OriginUpperLeft
|
||||||
|
OpSource ESSL 310
|
||||||
|
OpName %main "main"
|
||||||
|
OpName %vIndex "vIndex"
|
||||||
|
OpName %FragColor "FragColor"
|
||||||
|
OpDecorate %vIndex RelaxedPrecision
|
||||||
|
OpDecorate %vIndex Flat
|
||||||
|
OpDecorate %vIndex Location 0
|
||||||
|
OpDecorate %13 RelaxedPrecision
|
||||||
|
OpDecorate %FragColor RelaxedPrecision
|
||||||
|
OpDecorate %FragColor Location 0
|
||||||
|
%void = OpTypeVoid
|
||||||
|
%3 = OpTypeFunction %void
|
||||||
|
%float = OpTypeFloat 32
|
||||||
|
%float_8 = OpConstant %float 8
|
||||||
|
%int = OpTypeInt 32 1
|
||||||
|
%_ptr_Input_int = OpTypePointer Input %int
|
||||||
|
%vIndex = OpVariable %_ptr_Input_int Input
|
||||||
|
%float_1 = OpConstant %float 1
|
||||||
|
%float_3 = OpConstant %float 3
|
||||||
|
%_ptr_Output_float = OpTypePointer Output %float
|
||||||
|
%FragColor = OpVariable %_ptr_Output_float Output
|
||||||
|
%main = OpFunction %void None %3
|
||||||
|
%5 = OpLabel
|
||||||
|
%13 = OpLoad %int %vIndex
|
||||||
|
OpSelectionMerge %17 None
|
||||||
|
OpSwitch %13 %15 0 %14 2 %14 1 %15 8 %17
|
||||||
|
%15 = OpLabel
|
||||||
|
OpBranch %17
|
||||||
|
%14 = OpLabel
|
||||||
|
OpBranch %17
|
||||||
|
%17 = OpLabel
|
||||||
|
%27 = OpPhi %float %float_3 %15 %float_1 %14 %float_8 %5
|
||||||
|
OpStore %FragColor %27
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
@ -9657,32 +9657,61 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
|
|||||||
statement("switch (", to_expression(block.condition), ")");
|
statement("switch (", to_expression(block.condition), ")");
|
||||||
begin_scope();
|
begin_scope();
|
||||||
|
|
||||||
|
// Multiple case labels can branch to same block, so find all unique blocks.
|
||||||
|
bool emitted_default = false;
|
||||||
|
unordered_set<uint32_t> emitted_blocks;
|
||||||
|
|
||||||
for (auto &c : block.cases)
|
for (auto &c : block.cases)
|
||||||
{
|
{
|
||||||
auto case_value =
|
if (emitted_blocks.count(c.block) != 0)
|
||||||
uint32_t_case ? convert_to_string(uint32_t(c.value)) : convert_to_string(int32_t(c.value));
|
continue;
|
||||||
statement("case ", case_value, ":");
|
|
||||||
|
// Emit all case labels which branch to our target.
|
||||||
|
// FIXME: O(n^2), revisit if we hit shaders with 100++ case labels ...
|
||||||
|
for (auto &other_case : block.cases)
|
||||||
|
{
|
||||||
|
if (other_case.block == c.block)
|
||||||
|
{
|
||||||
|
auto case_value = uint32_t_case ? convert_to_string(uint32_t(other_case.value)) :
|
||||||
|
convert_to_string(int32_t(other_case.value));
|
||||||
|
statement("case ", case_value, ":");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maybe we share with default block?
|
||||||
|
if (block.default_block == c.block)
|
||||||
|
{
|
||||||
|
statement("default:");
|
||||||
|
emitted_default = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Complete the target.
|
||||||
|
emitted_blocks.insert(c.block);
|
||||||
|
|
||||||
begin_scope();
|
begin_scope();
|
||||||
branch(block.self, c.block);
|
branch(block.self, c.block);
|
||||||
end_scope();
|
end_scope();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (block.default_block != block.next_block)
|
if (!emitted_default)
|
||||||
{
|
{
|
||||||
statement("default:");
|
if (block.default_block != block.next_block)
|
||||||
begin_scope();
|
{
|
||||||
if (is_break(block.default_block))
|
statement("default:");
|
||||||
SPIRV_CROSS_THROW("Cannot break; out of a switch statement and out of a loop at the same time ...");
|
begin_scope();
|
||||||
branch(block.self, block.default_block);
|
if (is_break(block.default_block))
|
||||||
end_scope();
|
SPIRV_CROSS_THROW("Cannot break; out of a switch statement and out of a loop at the same time ...");
|
||||||
}
|
branch(block.self, block.default_block);
|
||||||
else if (flush_phi_required(block.self, block.next_block))
|
end_scope();
|
||||||
{
|
}
|
||||||
statement("default:");
|
else if (flush_phi_required(block.self, block.next_block))
|
||||||
begin_scope();
|
{
|
||||||
flush_phi(block.self, block.next_block);
|
statement("default:");
|
||||||
statement("break;");
|
begin_scope();
|
||||||
end_scope();
|
flush_phi(block.self, block.next_block);
|
||||||
|
statement("break;");
|
||||||
|
end_scope();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
end_scope();
|
end_scope();
|
||||||
|
Loading…
Reference in New Issue
Block a user