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:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2012-11-27 01:59:41 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2012-11-27 01:59:41 +0400
commitceed3ef640bb40e1232feeb409220fe19011bc43 (patch)
tree48ad960f483ad185718b14bbc605b6182732f56c /intern/cycles/render/svm.cpp
parenteab58bf994323a53311543d7d706b0be87ffe197 (diff)
Fix #32907: failure rendering a complex node setup, hitting fixed max number
of closures limit. Optimized the code now so it can handle more. Change SVM mix/add closure handling, now we transform the node graph so that the mix weights are fed into the closure nodes directly.
Diffstat (limited to 'intern/cycles/render/svm.cpp')
-rw-r--r--intern/cycles/render/svm.cpp124
1 files changed, 24 insertions, 100 deletions
diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp
index 73904eac41d..50b3bb59ed4 100644
--- a/intern/cycles/render/svm.cpp
+++ b/intern/cycles/render/svm.cpp
@@ -487,106 +487,30 @@ void SVMCompiler::generate_closure(ShaderNode *node, set<ShaderNode*>& done)
}
}
-void SVMCompiler::count_closure_users(ShaderNode *node, map<ShaderNode*, MultiClosureData>& closure_data)
-{
- /* here we count the number of times each closure node is used, so that
- * the last time we encounter it we can run the actually code with the
- * weights from all other places added together */
-
- if(node->name == ustring("mix_closure") || node->name == ustring("add_closure")) {
- ShaderInput *cl1in = node->input("Closure1");
- ShaderInput *cl2in = node->input("Closure2");
-
- if(cl1in->link)
- count_closure_users(cl1in->link->parent, closure_data);
- if(cl2in->link)
- count_closure_users(cl2in->link->parent, closure_data);
- }
- else {
- MultiClosureData data;
-
- if(closure_data.find(node) == closure_data.end()) {
- data.stack_offset = SVM_STACK_INVALID;
- data.users = 1;
- }
- else {
- data = closure_data[node];
- data.users++;
- }
-
- closure_data[node] = data;
- }
-}
-
-void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done,
- map<ShaderNode*, MultiClosureData>& closure_data, uint in_offset)
+void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done)
{
/* todo: the weaks point here is that unlike the single closure sampling
* we will evaluate all nodes even if they are used as input for closures
* that are unused. it's not clear what would be the best way to skip such
* nodes at runtime, especially if they are tangled up */
+
+ /* only generate once */
+ if(done.find(node) != done.end())
+ return;
+
+ done.insert(node);
if(node->name == ustring("mix_closure") || node->name == ustring("add_closure")) {
- ShaderInput *fin = node->input("Fac");
+ /* weighting is already taken care of in ShaderGraph::transform_multi_closure */
ShaderInput *cl1in = node->input("Closure1");
ShaderInput *cl2in = node->input("Closure2");
- uint out1_offset = SVM_STACK_INVALID;
- uint out2_offset = SVM_STACK_INVALID;
-
- if(fin) {
- /* mix closure */
- set<ShaderNode*> dependencies;
- find_dependencies(dependencies, done, fin);
- generate_svm_nodes(dependencies, done);
-
- stack_assign(fin);
-
- if(cl1in->link)
- out1_offset = stack_find_offset(SHADER_SOCKET_FLOAT);
- if(cl2in->link)
- out2_offset = stack_find_offset(SHADER_SOCKET_FLOAT);
-
- add_node(NODE_MIX_CLOSURE,
- encode_uchar4(fin->stack_offset, in_offset, out1_offset, out2_offset));
- }
- else {
- /* add closure */
- out1_offset = in_offset;
- out2_offset = in_offset;
- }
-
if(cl1in->link)
- generate_multi_closure(cl1in->link->parent, done, closure_data, out1_offset);
-
+ generate_multi_closure(cl1in->link->parent, done);
if(cl2in->link)
- generate_multi_closure(cl2in->link->parent, done, closure_data, out2_offset);
-
- if(in_offset != SVM_STACK_INVALID)
- stack_clear_offset(SHADER_SOCKET_FLOAT, in_offset);
+ generate_multi_closure(cl2in->link->parent, done);
}
else {
- MultiClosureData data = closure_data[node];
-
- if(data.stack_offset == SVM_STACK_INVALID) {
- /* first time using closure, use stack position for weight */
- data.stack_offset = in_offset;
- }
- else {
- /* not first time using, add weights together */
- add_node(NODE_MATH, NODE_MATH_ADD, data.stack_offset, in_offset);
- add_node(NODE_MATH, data.stack_offset);
-
- stack_clear_offset(SHADER_SOCKET_FLOAT, in_offset);
- }
-
- data.users--;
- closure_data[node] = data;
-
- /* still users coming? skip generating closure code */
- if(data.users > 0)
- return;
-
/* execute dependencies for closure */
foreach(ShaderInput *in, node->inputs) {
if(!node_skip_input(node, in) && in->link) {
@@ -596,7 +520,16 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& don
}
}
- mix_weight_offset = data.stack_offset;
+ /* closure mix weight */
+ const char *weight_name = (current_type == SHADER_TYPE_VOLUME)? "VolumeMixWeight": "SurfaceMixWeight";
+ ShaderInput *weight_in = node->input(weight_name);
+
+ if(weight_in && (weight_in->link || weight_in->value.x != 1.0f)) {
+ stack_assign(weight_in);
+ mix_weight_offset = weight_in->stack_offset;
+ }
+ else
+ mix_weight_offset = SVM_STACK_INVALID;
/* compile closure itself */
node->compile(*this);
@@ -609,11 +542,6 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& don
current_shader->has_surface_emission = true;
if(node->name == ustring("transparent"))
current_shader->has_surface_transparent = true;
-
- /* end node is added outside of this */
-
- if(data.stack_offset != SVM_STACK_INVALID)
- stack_clear_offset(SHADER_SOCKET_FLOAT, data.stack_offset);
}
}
@@ -685,12 +613,8 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
if(generate) {
set<ShaderNode*> done;
- if(use_multi_closure) {
- map<ShaderNode*, MultiClosureData> closure_data;
-
- count_closure_users(clin->link->parent, closure_data);
- generate_multi_closure(clin->link->parent, done, closure_data, SVM_STACK_INVALID);
- }
+ if(use_multi_closure)
+ generate_multi_closure(clin->link->parent, done);
else
generate_closure(clin->link->parent, done);
}
@@ -713,9 +637,9 @@ void SVMCompiler::compile(Shader *shader, vector<int4>& global_svm_nodes, int in
shader->graph_bump = shader->graph->copy();
/* finalize */
- shader->graph->finalize(false, false);
+ shader->graph->finalize(false, false, use_multi_closure);
if(shader->graph_bump)
- shader->graph_bump->finalize(true, false);
+ shader->graph_bump->finalize(true, false, use_multi_closure);
current_shader = shader;