Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2014-07-11 16:19:14 +0400
committerSergey Sharybin <sergey.vfx@gmail.com>2014-07-11 16:21:52 +0400
commit594ff72bfe597b42bfc11e062649176fec00be0c (patch)
tree5d1b8632c5999da0cffbf0db36d7ca2b9bf2e42d /intern/cycles/render
parent4633e655dc59b68d622e3319102d5050245a22eb (diff)
Fix T41023: Specific material cause bad render result, different on CPU/GPU
Issue was caused by too much aggressive optimization, which skipped execution of some nodes leading to an uninitialized memory read in SVM stack.
Diffstat (limited to 'intern/cycles/render')
-rw-r--r--intern/cycles/render/svm.cpp67
-rw-r--r--intern/cycles/render/svm.h12
2 files changed, 59 insertions, 20 deletions
diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp
index 576c176759c..13c63d9420c 100644
--- a/intern/cycles/render/svm.cpp
+++ b/intern/cycles/render/svm.cpp
@@ -363,14 +363,17 @@ bool SVMCompiler::node_skip_input(ShaderNode *node, ShaderInput *input)
return false;
}
-void SVMCompiler::find_dependencies(set<ShaderNode*>& dependencies, const set<ShaderNode*>& done, ShaderInput *input)
+void SVMCompiler::find_dependencies(set<ShaderNode*>& dependencies,
+ const set<ShaderNode*>& done,
+ ShaderInput *input,
+ ShaderNode *skip_node)
{
ShaderNode *node = (input->link)? input->link->parent: NULL;
- if(node && done.find(node) == done.end()) {
+ if(node && done.find(node) == done.end() && node != skip_node) {
foreach(ShaderInput *in, node->inputs)
if(!node_skip_input(node, in))
- find_dependencies(dependencies, done, in);
+ find_dependencies(dependencies, done, in, skip_node);
dependencies.insert(node);
}
@@ -459,20 +462,28 @@ void SVMCompiler::generate_closure_node(ShaderNode *node, set<ShaderNode*>& done
}
}
-void SVMCompiler::generated_shared_closure_nodes(ShaderNode *node, set<ShaderNode*>& done, set<ShaderNode*>& closure_done, const set<ShaderNode*>& shared)
+void SVMCompiler::generated_shared_closure_nodes(ShaderNode *root_node,
+ ShaderNode *node,
+ set<ShaderNode*>& done,
+ set<ShaderNode*>& closure_done,
+ const set<ShaderNode*>& shared)
{
if(shared.find(node) != shared.end()) {
- generate_multi_closure(node, done, closure_done);
+ generate_multi_closure(root_node, node, done, closure_done);
}
else {
foreach(ShaderInput *in, node->inputs) {
if(in->type == SHADER_SOCKET_CLOSURE && in->link)
- generated_shared_closure_nodes(in->link->parent, done, closure_done, shared);
+ generated_shared_closure_nodes(root_node, in->link->parent,
+ done, closure_done, shared);
}
}
}
-void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done, set<ShaderNode*>& closure_done)
+void SVMCompiler::generate_multi_closure(ShaderNode *root_node,
+ ShaderNode *node,
+ set<ShaderNode*>& done,
+ set<ShaderNode*>& closure_done)
{
/* only generate once */
if(closure_done.find(node) != closure_done.end())
@@ -509,12 +520,33 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& don
set_intersection(cl1deps.begin(), cl1deps.end(),
cl2deps.begin(), cl2deps.end(),
std::inserter(shareddeps, shareddeps.begin()));
-
+
+ /* it's possible some nodes are not shared between this mix node
+ * inputs, but still needed to be always executed, this mainly
+ * happens when a node of current subbranch is used by a parent
+ * node or so */
+ if(root_node != node) {
+ foreach(ShaderInput *in, root_node->inputs) {
+ set<ShaderNode*> rootdeps;
+ find_dependencies(rootdeps, done, in, node);
+ set_intersection(rootdeps.begin(), rootdeps.end(),
+ cl1deps.begin(), cl1deps.end(),
+ std::inserter(shareddeps, shareddeps.begin()));
+ set_intersection(rootdeps.begin(), rootdeps.end(),
+ cl2deps.begin(), cl2deps.end(),
+ std::inserter(shareddeps, shareddeps.begin()));
+ }
+ }
+
if(!shareddeps.empty()) {
- if(cl1in->link)
- generated_shared_closure_nodes(cl1in->link->parent, done, closure_done, shareddeps);
- if(cl2in->link)
- generated_shared_closure_nodes(cl2in->link->parent, done, closure_done, shareddeps);
+ if(cl1in->link) {
+ generated_shared_closure_nodes(root_node, cl1in->link->parent,
+ done, closure_done, shareddeps);
+ }
+ if(cl2in->link) {
+ generated_shared_closure_nodes(root_node, cl2in->link->parent,
+ done, closure_done, shareddeps);
+ }
generate_svm_nodes(shareddeps, done);
}
@@ -525,7 +557,7 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& don
svm_nodes.push_back(make_int4(NODE_JUMP_IF_ONE, 0, facin->stack_offset, 0));
int node_jump_skip_index = svm_nodes.size() - 1;
- generate_multi_closure(cl1in->link->parent, done, closure_done);
+ generate_multi_closure(root_node, cl1in->link->parent, done, closure_done);
/* fill in jump instruction location to be after closure */
svm_nodes[node_jump_skip_index].y = svm_nodes.size() - node_jump_skip_index - 1;
@@ -537,7 +569,7 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& don
svm_nodes.push_back(make_int4(NODE_JUMP_IF_ZERO, 0, facin->stack_offset, 0));
int node_jump_skip_index = svm_nodes.size() - 1;
- generate_multi_closure(cl2in->link->parent, done, closure_done);
+ generate_multi_closure(root_node, cl2in->link->parent, done, closure_done);
/* fill in jump instruction location to be after closure */
svm_nodes[node_jump_skip_index].y = svm_nodes.size() - node_jump_skip_index - 1;
@@ -551,9 +583,9 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& don
* to skip closures here because was already optimized due to
* fixed weight or add closure that always needs both */
if(cl1in->link)
- generate_multi_closure(cl1in->link->parent, done, closure_done);
+ generate_multi_closure(root_node, cl1in->link->parent, done, closure_done);
if(cl2in->link)
- generate_multi_closure(cl2in->link->parent, done, closure_done);
+ generate_multi_closure(root_node, cl2in->link->parent, done, closure_done);
}
}
else {
@@ -638,7 +670,8 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
if(generate) {
set<ShaderNode*> done, closure_done;
- generate_multi_closure(clin->link->parent, done, closure_done);
+ generate_multi_closure(clin->link->parent, clin->link->parent,
+ done, closure_done);
}
}
diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h
index 45aa4d26926..c1dd96e4d80 100644
--- a/intern/cycles/render/svm.h
+++ b/intern/cycles/render/svm.h
@@ -123,15 +123,21 @@ protected:
/* single closure */
void find_dependencies(set<ShaderNode*>& dependencies,
- const set<ShaderNode*>& done, ShaderInput *input);
+ const set<ShaderNode*>& done,
+ ShaderInput *input,
+ ShaderNode *skip_node = NULL);
void generate_node(ShaderNode *node, set<ShaderNode*>& done);
void generate_closure_node(ShaderNode *node, set<ShaderNode*>& done);
- void generated_shared_closure_nodes(ShaderNode *node, set<ShaderNode*>& done,
+ void generated_shared_closure_nodes(ShaderNode *root_node, ShaderNode *node,
+ set<ShaderNode*>& done,
set<ShaderNode*>& closure_done, const set<ShaderNode*>& shared);
void generate_svm_nodes(const set<ShaderNode*>& nodes, set<ShaderNode*>& done);
/* multi closure */
- void generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done, set<ShaderNode*>& closure_done);
+ void generate_multi_closure(ShaderNode *root_node,
+ ShaderNode *node,
+ set<ShaderNode*>& done,
+ set<ShaderNode*>& closure_done);
/* compile */
void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type);