diff options
author | Alexander Gavrilov <angavrilov@gmail.com> | 2016-06-19 16:51:10 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2016-06-19 21:17:27 +0300 |
commit | 81e391a72747fe4d8ab1978a0929719844df35a1 (patch) | |
tree | 1e9dad8cdd1e71bf0b74500d4fe5952027e36589 /intern | |
parent | 98547e8817b35470fdf3bc19ded9b6695db5a8ad (diff) |
Fix issues with node deduplication in Cycles shader graph.
It is not possible to use a set split by name as valid input to
check_node_input_traversed - it needs a complete set of all nodes visited so
far. On the other hand, the merge comparison loop should only check nodes that
were not just visited, but found unique. This means that there should really be
two separate data structures.
Without the fix, check_node_input_traversed actually never returns true, so
only nodes without any inputs are processed.
Diffstat (limited to 'intern')
-rw-r--r-- | intern/cycles/render/graph.cpp | 27 |
1 files changed, 17 insertions, 10 deletions
diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index a1b992a2c31..fd48bf2631e 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -558,8 +558,8 @@ void ShaderGraph::deduplicate_nodes() * already deduplicated. */ - ShaderNodeSet scheduled; - map<ustring, ShaderNodeSet> done; + ShaderNodeSet scheduled, done; + map<ustring, ShaderNodeSet> candidates; queue<ShaderNode*> traverse_queue; /* Schedule nodes which doesn't have any dependencies. */ @@ -573,7 +573,7 @@ void ShaderGraph::deduplicate_nodes() while(!traverse_queue.empty()) { ShaderNode *node = traverse_queue.front(); traverse_queue.pop(); - done[node->name].insert(node); + done.insert(node); /* Schedule the nodes which were depending on the current node. */ foreach(ShaderOutput *output, node->outputs) { foreach(ShaderInput *input, output->links) { @@ -584,21 +584,28 @@ void ShaderGraph::deduplicate_nodes() continue; } /* Schedule node if its inputs are fully done. */ - if(check_node_inputs_traversed(input->parent, done[input->parent->name])) { + if(check_node_inputs_traversed(input->parent, done)) { traverse_queue.push(input->parent); scheduled.insert(input->parent); } } } /* Try to merge this node with another one. */ - foreach(ShaderNode *other_node, done[node->name]) { + ShaderNode *merge_with = NULL; + foreach(ShaderNode *other_node, candidates[node->type->name]) { if (node != other_node && node->equals(*other_node)) { - /* TODO(sergey): Consider making it an utility function. */ - for(int i = 0; i < node->outputs.size(); ++i) { - relink(node, node->outputs[i], other_node->outputs[i]); - } + merge_with = other_node; + break; } - break; + } + /* If found an equivalent, merge; otherwise keep node for later merges */ + if (merge_with != NULL) { + for(int i = 0; i < node->outputs.size(); ++i) { + relink(node, node->outputs[i], merge_with->outputs[i]); + } + } + else { + candidates[node->type->name].insert(node); } } } |