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:
authorHans-Kristian Arntzen <post@arntzen-software.no>2022-01-17 16:12:01 +0300
committerHans-Kristian Arntzen <post@arntzen-software.no>2022-01-17 16:12:01 +0300
commit1d13a3e36a56e446020057beedb82cdce6d23c58 (patch)
tree06285488c1ab8b50ecaeacb15c2bc8351ec2112a /spirv_glsl.cpp
parenta1bb29ccbb285618028a24efb3fe4f6718cee0b5 (diff)
Rework how loop iteration counts are validated.
Introduces an idea of a recompilation making forward progress. There are some extreme edge cases where we need more than 3 loops, but only allow this in specific circumstances where we can reason about forward progress being made.
Diffstat (limited to 'spirv_glsl.cpp')
-rw-r--r--spirv_glsl.cpp31
1 files changed, 22 insertions, 9 deletions
diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp
index a96c9671..aae23803 100644
--- a/spirv_glsl.cpp
+++ b/spirv_glsl.cpp
@@ -296,8 +296,19 @@ const char *CompilerGLSL::vector_swizzle(int vecsize, int index)
return swizzle[vecsize - 1][index];
}
-void CompilerGLSL::reset()
-{
+void CompilerGLSL::reset(uint32_t iteration_count)
+{
+ // Sanity check the iteration count to be robust against a certain class of bugs where
+ // we keep forcing recompilations without making clear forward progress.
+ // In buggy situations we will loop forever, or loop for an unbounded number of iterations.
+ // Certain types of recompilations are considered to make forward progress,
+ // but in almost all situations, we'll never see more than 3 iterations.
+ // It is highly context-sensitive when we need to force recompilation,
+ // and it is not practical with the current architecture
+ // to resolve everything up front.
+ if (iteration_count >= 3 && !is_force_recompile_forward_progress)
+ SPIRV_CROSS_THROW("Over 3 compilation loops detected and no forward progress was made. Must be a bug!");
+
// We do some speculative optimizations which should pretty much always work out,
// but just in case the SPIR-V is rather weird, recompile until it's happy.
// This typically only means one extra pass.
@@ -664,10 +675,7 @@ string CompilerGLSL::compile()
uint32_t pass_count = 0;
do
{
- if (pass_count >= 3)
- SPIRV_CROSS_THROW("Over 3 compilation loops detected. Must be a bug!");
-
- reset();
+ reset(pass_count);
buffer.reset();
@@ -4291,8 +4299,13 @@ void CompilerGLSL::handle_invalid_expression(uint32_t id)
{
// We tried to read an invalidated expression.
// This means we need another pass at compilation, but next time, force temporary variables so that they cannot be invalidated.
- forced_temporaries.insert(id);
- force_recompile();
+ auto res = forced_temporaries.insert(id);
+
+ // Forcing new temporaries guarantees forward progress.
+ if (res.second)
+ force_recompile_guarantee_forward_progress();
+ else
+ force_recompile();
}
// Converts the format of the current expression from packed to unpacked,
@@ -14752,7 +14765,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
// as writes to said loop variables might have been masked out, we need a recompile.
if (!emitted_loop_header_variables && !block.loop_variables.empty())
{
- force_recompile();
+ force_recompile_guarantee_forward_progress();
for (auto var : block.loop_variables)
get<SPIRVariable>(var).loop_variable = false;
block.loop_variables.clear();