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), ")");
|
||||
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)
|
||||
{
|
||||
auto case_value =
|
||||
uint32_t_case ? convert_to_string(uint32_t(c.value)) : convert_to_string(int32_t(c.value));
|
||||
statement("case ", case_value, ":");
|
||||
if (emitted_blocks.count(c.block) != 0)
|
||||
continue;
|
||||
|
||||
// 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();
|
||||
branch(block.self, c.block);
|
||||
end_scope();
|
||||
}
|
||||
|
||||
if (block.default_block != block.next_block)
|
||||
if (!emitted_default)
|
||||
{
|
||||
statement("default:");
|
||||
begin_scope();
|
||||
if (is_break(block.default_block))
|
||||
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);
|
||||
end_scope();
|
||||
}
|
||||
else if (flush_phi_required(block.self, block.next_block))
|
||||
{
|
||||
statement("default:");
|
||||
begin_scope();
|
||||
flush_phi(block.self, block.next_block);
|
||||
statement("break;");
|
||||
end_scope();
|
||||
if (block.default_block != block.next_block)
|
||||
{
|
||||
statement("default:");
|
||||
begin_scope();
|
||||
if (is_break(block.default_block))
|
||||
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);
|
||||
end_scope();
|
||||
}
|
||||
else if (flush_phi_required(block.self, block.next_block))
|
||||
{
|
||||
statement("default:");
|
||||
begin_scope();
|
||||
flush_phi(block.self, block.next_block);
|
||||
statement("break;");
|
||||
end_scope();
|
||||
}
|
||||
}
|
||||
|
||||
end_scope();
|
||||
|
Loading…
Reference in New Issue
Block a user