Fix T84006: Cycles AOV not written with some mix shader node set ups

This commit is contained in:
Brecht Van Lommel 2020-12-22 00:50:22 +01:00
parent 2601501fce
commit dad5aded0c
Notes: blender-bot 2023-02-13 20:06:59 +01:00
Referenced by issue #84006, AOV pass not working correctly when Light Path node is used in shader
2 changed files with 51 additions and 35 deletions

View File

@ -548,22 +548,23 @@ void SVMCompiler::generated_shared_closure_nodes(ShaderNode *root_node,
}
}
void SVMCompiler::generate_aov_node(ShaderNode *node, CompilerState *state)
void SVMCompiler::find_aov_nodes_and_dependencies(ShaderNodeSet &aov_nodes,
ShaderGraph *graph,
CompilerState *state)
{
/* execute dependencies for node */
foreach (ShaderInput *in, node->inputs) {
if (in->link != NULL) {
ShaderNodeSet dependencies;
find_dependencies(dependencies, state->nodes_done, in);
generate_svm_nodes(dependencies, state);
foreach (ShaderNode *node, graph->nodes) {
if (node->special_type == SHADER_SPECIAL_TYPE_OUTPUT_AOV) {
OutputAOVNode *aov_node = static_cast<OutputAOVNode *>(node);
if (aov_node->slot >= 0) {
aov_nodes.insert(aov_node);
foreach (ShaderInput *in, node->inputs) {
if (in->link != NULL) {
find_dependencies(aov_nodes, state->nodes_done, in);
}
}
}
}
}
/* compile node itself */
generate_node(node, state->nodes_done);
state->nodes_done.insert(node);
state->nodes_done_flag[node->id] = true;
}
void SVMCompiler::generate_multi_closure(ShaderNode *root_node,
@ -631,6 +632,25 @@ void SVMCompiler::generate_multi_closure(ShaderNode *root_node,
}
}
/* For dependencies AOV nodes, prevent them from being categorized
* as exclusive deps of one or the other closure, since the need to
* execute them for AOV writing is not dependent on the closure
* weights. */
if (state->aov_nodes.size()) {
set_intersection(state->aov_nodes.begin(),
state->aov_nodes.end(),
cl1deps.begin(),
cl1deps.end(),
std::inserter(shareddeps, shareddeps.begin()),
node_id_comp);
set_intersection(state->aov_nodes.begin(),
state->aov_nodes.end(),
cl2deps.begin(),
cl2deps.end(),
std::inserter(shareddeps, shareddeps.begin()),
node_id_comp);
}
if (!shareddeps.empty()) {
if (cl1in->link) {
generated_shared_closure_nodes(root_node, cl1in->link->parent, state, shareddeps);
@ -782,6 +802,9 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
}
if (generate) {
if (type == SHADER_TYPE_SURFACE) {
find_aov_nodes_and_dependencies(state.aov_nodes, graph, &state);
}
generate_multi_closure(clin->link->parent, clin->link->parent, &state);
}
}
@ -789,28 +812,15 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
/* compile output node */
output->compile(*this);
if (type == SHADER_TYPE_SURFACE) {
vector<OutputAOVNode *> aov_outputs;
foreach (ShaderNode *node, graph->nodes) {
if (node->special_type == SHADER_SPECIAL_TYPE_OUTPUT_AOV) {
OutputAOVNode *aov_node = static_cast<OutputAOVNode *>(node);
if (aov_node->slot >= 0) {
aov_outputs.push_back(aov_node);
}
}
}
if (aov_outputs.size() > 0) {
/* AOV passes are only written if the object is directly visible, so
* there is no point in evaluating all the nodes generated only for the
* AOV outputs if that's not the case. Therefore, we insert
* NODE_AOV_START into the shader before the AOV-only nodes are
* generated which tells the kernel that it can stop evaluation
* early if AOVs will not be written. */
add_node(NODE_AOV_START, 0, 0, 0);
foreach (OutputAOVNode *node, aov_outputs) {
generate_aov_node(node, &state);
}
}
if (!state.aov_nodes.empty()) {
/* AOV passes are only written if the object is directly visible, so
* there is no point in evaluating all the nodes generated only for the
* AOV outputs if that's not the case. Therefore, we insert
* NODE_AOV_START into the shader before the AOV-only nodes are
* generated which tells the kernel that it can stop evaluation
* early if AOVs will not be written. */
add_node(NODE_AOV_START, 0, 0, 0);
generate_svm_nodes(state.aov_nodes, &state);
}
}

View File

@ -176,6 +176,9 @@ class SVMCompiler {
/* Set of closures which were already compiled. */
ShaderNodeSet closure_done;
/* Set of nodes used for writing AOVs. */
ShaderNodeSet aov_nodes;
/* ** SVM nodes generation state ** */
/* Flag whether the node with corresponding ID was already compiled or
@ -197,6 +200,9 @@ class SVMCompiler {
const ShaderNodeSet &done,
ShaderInput *input,
ShaderNode *skip_node = NULL);
void find_aov_nodes_and_dependencies(ShaderNodeSet &aov_nodes,
ShaderGraph *graph,
CompilerState *state);
void generate_node(ShaderNode *node, ShaderNodeSet &done);
void generate_aov_node(ShaderNode *node, CompilerState *state);
void generate_closure_node(ShaderNode *node, CompilerState *state);