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.
This commit is contained in:
parent
98547e8817
commit
81e391a727
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue