Deal with switch case labels which share a block.

This commit is contained in:
Hans-Kristian Arntzen 2018-06-20 10:49:03 +02:00
parent e59cc24495
commit 9d31154917
4 changed files with 158 additions and 18 deletions

View File

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

View File

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

View 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

View File

@ -9657,16 +9657,44 @@ 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));
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 (!emitted_default)
{
if (block.default_block != block.next_block)
{
statement("default:");
@ -9684,6 +9712,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
statement("break;");
end_scope();
}
}
end_scope();
break;