Skip to content

Commit

Permalink
Fix pathological complexity explosion for certain shaders.
Browse files Browse the repository at this point in the history
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 :(
  • Loading branch information
HansKristian-Work committed Jan 14, 2021
1 parent 820179b commit 4c866e4
Showing 1 changed file with 12 additions and 4 deletions.
16 changes: 12 additions & 4 deletions spirv_cross.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2829,7 +2829,8 @@ const SPIRConstant &Compiler::get_constant(ConstantID id) const
return get<SPIRConstant>(id);
}

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

// If any of our successors have a path to the end, there exists a path from block.
for (auto &succ : cfg.get_succeeding_edges(block))
if (exists_unaccessed_path_to_return(cfg, succ, blocks))
return true;
{
if (visit_cache.count(succ) == 0)
{
if (exists_unaccessed_path_to_return(cfg, succ, blocks, visit_cache))
return true;
visit_cache.insert(succ);
}
}

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

0 comments on commit 4c866e4

Please sign in to comment.