Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/KhronosGroup/SPIRV-Cross.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--reference/opt/shaders/asm/frag/for-loop-phi-only-continue.asm.frag17
-rw-r--r--reference/shaders/asm/frag/for-loop-phi-only-continue.asm.frag19
-rw-r--r--shaders/asm/frag/for-loop-phi-only-continue.asm.frag48
-rw-r--r--spirv_cross.cpp8
-rw-r--r--spirv_glsl.cpp16
-rw-r--r--spirv_glsl.hpp1
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();