[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [52533] trunk/blender/intern/cycles/render : Fix #33152: cycles SVM crash with certain shader nodes setups where closures would

Brecht Van Lommel brechtvanlommel at pandora.be
Sat Nov 24 15:50:22 CET 2012


Revision: 52533
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=52533
Author:   blendix
Date:     2012-11-24 14:50:21 +0000 (Sat, 24 Nov 2012)
Log Message:
-----------
Fix #33152: cycles SVM crash with certain shader nodes setups where closures would
appear multiple times after flattening the mix/add shader part of the graph into a
tree structure.

Modified Paths:
--------------
    trunk/blender/intern/cycles/render/svm.cpp
    trunk/blender/intern/cycles/render/svm.h

Modified: trunk/blender/intern/cycles/render/svm.cpp
===================================================================
--- trunk/blender/intern/cycles/render/svm.cpp	2012-11-24 14:19:21 UTC (rev 52532)
+++ trunk/blender/intern/cycles/render/svm.cpp	2012-11-24 14:50:21 UTC (rev 52533)
@@ -487,8 +487,40 @@
 	}
 }
 
-void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done, uint in_offset)
+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)
+{
 	/* 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
@@ -524,21 +556,37 @@
 			out2_offset = in_offset;
 		}
 
-		if(cl1in->link) {
-			generate_multi_closure(cl1in->link->parent, done, out1_offset);
+		if(cl1in->link)
+			generate_multi_closure(cl1in->link->parent, done, closure_data, out1_offset);
 
-			if(fin)
-				stack_clear_offset(SHADER_SOCKET_FLOAT, out1_offset);
+		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);
+	}
+	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);
 
-		if(cl2in->link) {
-			generate_multi_closure(cl2in->link->parent, done, out2_offset);
+			stack_clear_offset(SHADER_SOCKET_FLOAT, in_offset);
+		}
 
-			if(fin)
-				stack_clear_offset(SHADER_SOCKET_FLOAT, out2_offset);
-		}
-	}
-	else {
+		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) {
@@ -548,7 +596,7 @@
 			}
 		}
 
-		mix_weight_offset = in_offset;
+		mix_weight_offset = data.stack_offset;
 
 		/* compile closure itself */
 		node->compile(*this);
@@ -563,6 +611,9 @@
 			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);
 	}
 }
 
@@ -634,8 +685,12 @@
 			if(generate) {
 				set<ShaderNode*> done;
 
-				if(use_multi_closure)
-					generate_multi_closure(clin->link->parent, done, SVM_STACK_INVALID);
+				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);
+				}
 				else
 					generate_closure(clin->link->parent, done);
 			}

Modified: trunk/blender/intern/cycles/render/svm.h
===================================================================
--- trunk/blender/intern/cycles/render/svm.h	2012-11-24 14:19:21 UTC (rev 52532)
+++ trunk/blender/intern/cycles/render/svm.h	2012-11-24 14:50:21 UTC (rev 52533)
@@ -81,6 +81,7 @@
 	bool background;
 
 protected:
+	/* stack */
 	struct Stack {
 		Stack() { memset(users, 0, sizeof(users)); }
 		Stack(const Stack& other) { memcpy(users, other.users, sizeof(users)); }
@@ -123,11 +124,22 @@
 
 	bool node_skip_input(ShaderNode *node, ShaderInput *input);
 
+	/* single closure */
 	void find_dependencies(set<ShaderNode*>& dependencies, const set<ShaderNode*>& done, ShaderInput *input);
 	void generate_svm_nodes(const set<ShaderNode*>& nodes, set<ShaderNode*>& done);
 	void generate_closure(ShaderNode *node, set<ShaderNode*>& done);
-	void generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done, uint in_offset);
 
+	/* multi closure */
+	struct MultiClosureData {
+		int stack_offset;
+		int users;
+	};
+
+	void generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done,
+		map<ShaderNode*,MultiClosureData>& closure_data, uint in_offset);
+	void count_closure_users(ShaderNode *node, map<ShaderNode*, MultiClosureData>& closure_data);
+
+	/* compile */
 	void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type);
 
 	vector<int4> svm_nodes;




More information about the Bf-blender-cvs mailing list