Fix performance issues with graph edge iteration in ShaderGraph #2023
+97
−3
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
In complex materials graph and shader graph edge iteration can be extremely slow, because some edges may be visited unnecessarily multiple times. This is especially noticable in two functions: ShaderGraph::addUpstreamDependencies and ShaderGraph::optimize() .
GraphIterator and ShaderGraphEdgeIterator classes iterate over DAGs without marking nodes as visited, which may lead to exponential traversal time for some DAGs: https://stackoverflow.com/a/69326676
This patch adds two functions which efficiently generate a unique list of (shader) graph edges and uses those lists instead of graph iterators.
For one especially complex material on which I tested this fix, shader code generation time decreased from 156.13 sec to 0.08 sec (almost 2000x speedup). Number of visited edges in ShaderGraph::optimize() decreased from 42M to ~600.
I'm not sure if the best approach is to add those two functions next to current graph iterators or maybe those iterators should be replaced altogether. Another solution which I see would be to fix the graph iterators, but IMO they add a lot of overhead and it's faster to simply use a function which returns a list of all edges in a given graph in std::vector.