diff options
-rw-r--r-- | reference/opt/shaders/asm/frag/for-loop-phi-only-continue.asm.frag | 17 | ||||
-rw-r--r-- | reference/shaders/asm/frag/for-loop-phi-only-continue.asm.frag | 19 | ||||
-rw-r--r-- | shaders/asm/frag/for-loop-phi-only-continue.asm.frag | 48 | ||||
-rw-r--r-- | spirv_cross.cpp | 8 | ||||
-rw-r--r-- | spirv_glsl.cpp | 16 | ||||
-rw-r--r-- | spirv_glsl.hpp | 1 |
6 files changed, 107 insertions, 2 deletions
diff --git a/reference/opt/shaders/asm/frag/for-loop-phi-only-continue.asm.frag b/reference/opt/shaders/asm/frag/for-loop-phi-only-continue.asm.frag new file mode 100644 index 00000000..7a78d00b --- /dev/null +++ b/reference/opt/shaders/asm/frag/for-loop-phi-only-continue.asm.frag @@ -0,0 +1,17 @@ +#version 450 + +layout(location = 0) out vec4 FragColor; + +void main() +{ + float _19; + _19 = 0.0; + for (int _22 = 0; _22 < 16; ) + { + _19 += 1.0; + _22++; + continue; + } + FragColor = vec4(_19); +} + diff --git a/reference/shaders/asm/frag/for-loop-phi-only-continue.asm.frag b/reference/shaders/asm/frag/for-loop-phi-only-continue.asm.frag new file mode 100644 index 00000000..feb45db4 --- /dev/null +++ b/reference/shaders/asm/frag/for-loop-phi-only-continue.asm.frag @@ -0,0 +1,19 @@ +#version 450 + +layout(location = 0) out vec4 FragColor; + +void main() +{ + float _19; + _19 = 0.0; + float _20; + int _23; + for (int _22 = 0; _22 < 16; _19 = _20, _22 = _23) + { + _20 = _19 + 1.0; + _23 = _22 + 1; + continue; + } + FragColor = vec4(_19); +} + diff --git a/shaders/asm/frag/for-loop-phi-only-continue.asm.frag b/shaders/asm/frag/for-loop-phi-only-continue.asm.frag new file mode 100644 index 00000000..ae84b30b --- /dev/null +++ b/shaders/asm/frag/for-loop-phi-only-continue.asm.frag @@ -0,0 +1,48 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 6 +; Bound: 51 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %FragColor + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 450 + OpName %main "main" + OpName %FragColor "FragColor" + OpDecorate %FragColor Location 0 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %float_0 = OpConstant %float 0 + %int = OpTypeInt 32 1 + %int_0 = OpConstant %int 0 + %int_16 = OpConstant %int 16 + %bool = OpTypeBool + %float_1 = OpConstant %float 1 + %int_1 = OpConstant %int 1 + %float_2 = OpConstant %float 2 + %v4float = OpTypeVector %float 4 +%_ptr_Output_v4float = OpTypePointer Output %v4float + %FragColor = OpVariable %_ptr_Output_v4float Output + %main = OpFunction %void None %3 + %5 = OpLabel + OpBranch %14 + %14 = OpLabel + %50 = OpPhi %float %float_0 %5 %25 %15 + %47 = OpPhi %int %int_0 %5 %28 %15 + %22 = OpSLessThan %bool %47 %int_16 + OpLoopMerge %16 %15 None + OpBranchConditional %22 %body1 %16 + %body1 = OpLabel + %25 = OpFAdd %float %50 %float_1 + %28 = OpIAdd %int %47 %int_1 + OpBranch %15 + %15 = OpLabel + OpBranch %14 + %16 = OpLabel + %46 = OpCompositeConstruct %v4float %50 %50 %50 %50 + OpStore %FragColor %46 + OpReturn + OpFunctionEnd diff --git a/spirv_cross.cpp b/spirv_cross.cpp index dd2a44ca..eaddeca5 100644 --- a/spirv_cross.cpp +++ b/spirv_cross.cpp @@ -2437,7 +2437,13 @@ bool Compiler::execution_is_noop(const SPIRBlock &from, const SPIRBlock &to) con if (!start->ops.empty()) return false; - start = &get<SPIRBlock>(start->next_block); + auto &next = get<SPIRBlock>(start->next_block); + // Flushing phi variables does not count as noop. + for (auto &phi : next.phi_variables) + if (phi.parent == start->self) + return false; + + start = &next; } } diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp index b6987bc3..dc237110 100644 --- a/spirv_glsl.cpp +++ b/spirv_glsl.cpp @@ -9292,6 +9292,16 @@ string CompilerGLSL::emit_continue_block(uint32_t continue_block) return merge(statements); } +void CompilerGLSL::emit_while_loop_initializers(const SPIRBlock &block) +{ + // While loops do not take initializers, so declare all of them outside. + for (auto &loop_var : block.loop_variables) + { + auto &var = get<SPIRVariable>(loop_var); + statement(variable_decl(var), ";"); + } +} + string CompilerGLSL::emit_for_loop_initializers(const SPIRBlock &block) { if (block.loop_variables.empty()) @@ -9409,12 +9419,12 @@ bool CompilerGLSL::attempt_emit_loop_header(SPIRBlock &block, SPIRBlock::Method { // This block may be a dominating block, so make sure we flush undeclared variables before building the for loop header. flush_undeclared_variables(block); - emit_block_hints(block); // Important that we do this in this order because // emitting the continue block can invalidate the condition expression. auto initializer = emit_for_loop_initializers(block); auto condition = to_expression(block.condition); + emit_block_hints(block); if (method != SPIRBlock::MergeToSelectContinueForLoop) { auto continue_block = emit_continue_block(block.continue_block); @@ -9428,6 +9438,7 @@ bool CompilerGLSL::attempt_emit_loop_header(SPIRBlock &block, SPIRBlock::Method case SPIRBlock::WhileLoop: // This block may be a dominating block, so make sure we flush undeclared variables before building the while loop header. flush_undeclared_variables(block); + emit_while_loop_initializers(block); emit_block_hints(block); statement("while (", to_expression(block.condition), ")"); break; @@ -9482,6 +9493,7 @@ bool CompilerGLSL::attempt_emit_loop_header(SPIRBlock &block, SPIRBlock::Method } case SPIRBlock::WhileLoop: + emit_while_loop_initializers(block); emit_block_hints(block); statement("while (", to_expression(child.condition), ")"); break; @@ -9600,6 +9612,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block) else if (continue_type == SPIRBlock::DoWhileLoop) { flush_undeclared_variables(block); + emit_while_loop_initializers(block); // We have some temporaries where the loop header is the dominator. // We risk a case where we have code like: // for (;;) { create-temporary; break; } consume-temporary; @@ -9613,6 +9626,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block) else if (block.merge == SPIRBlock::MergeLoop) { flush_undeclared_variables(block); + emit_while_loop_initializers(block); // We have a generic loop without any distinguishable pattern like for, while or do while. get<SPIRBlock>(block.continue_block).complex_continue = true; diff --git a/spirv_glsl.hpp b/spirv_glsl.hpp index a8fc8edd..fa0475a8 100644 --- a/spirv_glsl.hpp +++ b/spirv_glsl.hpp @@ -549,6 +549,7 @@ protected: void find_static_extensions(); std::string emit_for_loop_initializers(const SPIRBlock &block); + void emit_while_loop_initializers(const SPIRBlock &block); bool for_loop_initializers_are_same_type(const SPIRBlock &block); bool optimize_read_modify_write(const SPIRType &type, const std::string &lhs, const std::string &rhs); void fixup_image_load_store_access(); |