Skip to content

Commit 4c866e4

Browse files
Fix pathological complexity explosion for certain shaders.
Certain shaders where functions have a *ton* of merging control flow will end up with exponential time complexity to figure out parameter preservation semantics. The trivial fix to make it O(1) again is to terminate recursive traversal early if we've seen the path before. Simple oversight :(
1 parent 820179b commit 4c866e4

1 file changed

Lines changed: 12 additions & 4 deletions

File tree

spirv_cross.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2829,7 +2829,8 @@ const SPIRConstant &Compiler::get_constant(ConstantID id) const
28292829
return get<SPIRConstant>(id);
28302830
}
28312831

2832-
static bool exists_unaccessed_path_to_return(const CFG &cfg, uint32_t block, const unordered_set<uint32_t> &blocks)
2832+
static bool exists_unaccessed_path_to_return(const CFG &cfg, uint32_t block, const unordered_set<uint32_t> &blocks,
2833+
unordered_set<uint32_t> &visit_cache)
28332834
{
28342835
// This block accesses the variable.
28352836
if (blocks.find(block) != end(blocks))
@@ -2841,8 +2842,14 @@ static bool exists_unaccessed_path_to_return(const CFG &cfg, uint32_t block, con
28412842

28422843
// If any of our successors have a path to the end, there exists a path from block.
28432844
for (auto &succ : cfg.get_succeeding_edges(block))
2844-
if (exists_unaccessed_path_to_return(cfg, succ, blocks))
2845-
return true;
2845+
{
2846+
if (visit_cache.count(succ) == 0)
2847+
{
2848+
if (exists_unaccessed_path_to_return(cfg, succ, blocks, visit_cache))
2849+
return true;
2850+
visit_cache.insert(succ);
2851+
}
2852+
}
28462853

28472854
return false;
28482855
}
@@ -2899,7 +2906,8 @@ void Compiler::analyze_parameter_preservation(
28992906
// void foo(int &var) { if (cond) var = 10; }
29002907
// Using read/write counts, we will think it's just an out variable, but it really needs to be inout,
29012908
// because if we don't write anything whatever we put into the function must return back to the caller.
2902-
if (exists_unaccessed_path_to_return(cfg, entry.entry_block, itr->second))
2909+
unordered_set<uint32_t> visit_cache;
2910+
if (exists_unaccessed_path_to_return(cfg, entry.entry_block, itr->second, visit_cache))
29032911
arg.read_count++;
29042912
}
29052913
}

0 commit comments

Comments
 (0)