diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp index a8ab3b42..bb1ec592 100644 --- a/spirv_glsl.cpp +++ b/spirv_glsl.cpp @@ -10573,6 +10573,8 @@ void CompilerGLSL::emit_function(SPIRFunction &func, const Bitset &return_flags) for (auto &v : func.local_variables) { auto &var = get(v); + var.deferred_declaration = false; + if (var.storage == StorageClassWorkgroup) { // Special variable type which cannot have initializer, @@ -10632,6 +10634,13 @@ void CompilerGLSL::emit_function(SPIRFunction &func, const Bitset &return_flags) var.deferred_declaration = false; } + // Enforce declaration order for regression testing purposes. + for (auto &block_id : func.blocks) + { + auto &block = get(block_id); + sort(begin(block.dominated_variables), end(block.dominated_variables)); + } + for (auto &line : current_function->fixup_hooks_in) line(); @@ -11260,8 +11269,6 @@ bool CompilerGLSL::attempt_emit_loop_header(SPIRBlock &block, SPIRBlock::Method void CompilerGLSL::flush_undeclared_variables(SPIRBlock &block) { - // Enforce declaration order for regression testing purposes. - sort(begin(block.dominated_variables), end(block.dominated_variables)); for (auto &v : block.dominated_variables) flush_variable_declaration(v); } @@ -11308,6 +11315,15 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block) for (auto var : block.loop_variables) get(var).loop_variable_enable = true; + // Remember deferred declaration state. We will restore it before returning. + SmallVector rearm_dominated_variables(block.dominated_variables.size()); + for (size_t i = 0; i < block.dominated_variables.size(); i++) + { + uint32_t var_id = block.dominated_variables[i]; + auto &var = get(var_id); + rearm_dominated_variables[i] = var.deferred_declaration; + } + // This is the method often used by spirv-opt to implement loops. // The loop header goes straight into the continue block. // However, don't attempt this on ESSL 1.0, because if a loop variable is used in a continue block, @@ -11686,6 +11702,15 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block) // Forget about control dependent expressions now. block.invalidate_expressions.clear(); + + // After we return, we must be out of scope, so if we somehow have to re-emit this function, + // re-declare variables if necessary. + assert(rearm_dominated_variables.size() == block.dominated_variables.size()); + for (size_t i = 0; i < block.dominated_variables.size(); i++) + { + uint32_t var = block.dominated_variables[i]; + get(var).deferred_declaration = rearm_dominated_variables[i]; + } } void CompilerGLSL::begin_scope()