[Bf-blender-cvs] [6fb22dd] object_nodes: Reference counting for mesh_ptr variables on the stack.

Lukas Tönne noreply at git.blender.org
Tue Nov 24 09:44:46 CET 2015


Commit: 6fb22ddfed3c61ff380d97d7537f887fb6ad9a91
Author: Lukas Tönne
Date:   Sat Nov 21 11:56:01 2015 +0100
Branches: object_nodes
https://developer.blender.org/rB6fb22ddfed3c61ff380d97d7537f887fb6ad9a91

Reference counting for mesh_ptr variables on the stack.

Any extensive data stored as a pointer on the stack should be ref-counted,
so that it stays alive only as long as used by some node.

The way this works is by enclosing instructions that access the stack
entry with 'init'/'release' opcodes. These are added automatically based
on output socket types (nodes don't have to be created explicitly for them).

===================================================================

M	source/blender/blenkernel/intern/DerivedMesh.c
M	source/blender/blenvm/bvm/bvm_eval.cc
M	source/blender/blenvm/bvm/bvm_function.cc
M	source/blender/blenvm/bvm/bvm_opcode.h
M	source/blender/blenvm/compile/bvm_codegen.cc
M	source/blender/blenvm/compile/bvm_nodegraph.h
M	source/blender/blenvm/intern/bvm_api.cc
M	source/blender/blenvm/util/bvm_util_typedesc.h

===================================================================

diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 7c0a6c6..7b82c75 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -1725,7 +1725,7 @@ static DerivedMesh *mesh_calc_modifier_nodes(Scene *scene, Object *ob, bNodeTree
 	 * This flag gets set in places to force freeing of meshes, can't expect this to work
 	 */
 	result = CDDM_copy(dm);
-	DM_release(dm);
+	dm->release(dm);
 	
 	return result;
 }
diff --git a/source/blender/blenvm/bvm/bvm_eval.cc b/source/blender/blenvm/bvm/bvm_eval.cc
index 9d1aba0..411ff1f 100644
--- a/source/blender/blenvm/bvm/bvm_eval.cc
+++ b/source/blender/blenvm/bvm/bvm_eval.cc
@@ -142,6 +142,20 @@ static void eval_op_get_elem_float4(float *stack, int index, StackIndex offset_f
 	stack_store_float(stack, offset_to, f[index]);
 }
 
+static void eval_op_init_mesh_ptr(float *stack, StackIndex offset, int use_count)
+{
+	mesh_ptr p(NULL);
+	p.set_use_count(use_count);
+	stack_store_mesh(stack, offset, p);
+}
+
+static void eval_op_release_mesh_ptr(float *stack, StackIndex offset)
+{
+	mesh_ptr p = stack_load_mesh(stack, offset);
+	p.decrement_use_count();
+	stack_store_mesh(stack, offset, p);
+}
+
 static void eval_op_point_position(const EvalData *data, float *stack, StackIndex offset)
 {
 	stack_store_float3(stack, offset, data->effector.position);
@@ -426,8 +440,10 @@ static void eval_op_effector_closest_point(float *stack, StackIndex offset_objec
 
 static void eval_op_mesh_load(const EvalData *data, float *stack, StackIndex offset)
 {
+	mesh_ptr p = stack_load_mesh(stack, offset);
 	DerivedMesh *dm = CDDM_from_mesh(data->modifier.base_mesh);
-	stack_store_mesh(stack, offset, mesh_ptr(dm));
+	p.set(dm);
+	stack_store_mesh(stack, offset, p);
 }
 
 void EvalContext::eval_instructions(const EvalGlobals *globals, const EvalData *data, const Function *fn, float *stack) const
@@ -524,6 +540,17 @@ void EvalContext::eval_instructions(const EvalGlobals *globals, const EvalData *
 				eval_op_get_elem_float4(stack, index, offset_from, offset_to);
 				break;
 			}
+			case OP_INIT_MESH_PTR: {
+				StackIndex offset = fn->read_stack_index(&instr);
+				int use_count = fn->read_int(&instr);
+				eval_op_init_mesh_ptr(stack, offset, use_count);
+				break;
+			}
+			case OP_RELEASE_MESH_PTR: {
+				StackIndex offset = fn->read_stack_index(&instr);
+				eval_op_release_mesh_ptr(stack, offset);
+				break;
+			}
 			case OP_POINT_POSITION: {
 				StackIndex offset = fn->read_stack_index(&instr);
 				eval_op_point_position(data, stack, offset);
diff --git a/source/blender/blenvm/bvm/bvm_function.cc b/source/blender/blenvm/bvm/bvm_function.cc
index fa18407..44a86c6 100644
--- a/source/blender/blenvm/bvm/bvm_function.cc
+++ b/source/blender/blenvm/bvm/bvm_function.cc
@@ -29,8 +29,6 @@
  *  \ingroup bvm
  */
 
-#include "MEM_guardedalloc.h"
-
 #include "bvm_function.h"
 
 namespace bvm {
diff --git a/source/blender/blenvm/bvm/bvm_opcode.h b/source/blender/blenvm/bvm/bvm_opcode.h
index 3680ac1..925d75e 100644
--- a/source/blender/blenvm/bvm/bvm_opcode.h
+++ b/source/blender/blenvm/bvm/bvm_opcode.h
@@ -50,6 +50,9 @@ enum OpCode {
 	OP_SET_FLOAT4,
 	OP_GET_ELEM_FLOAT4,
 	
+	OP_INIT_MESH_PTR,
+	OP_RELEASE_MESH_PTR,
+	
 	OP_POINT_POSITION,
 	OP_POINT_VELOCITY,
 	
diff --git a/source/blender/blenvm/compile/bvm_codegen.cc b/source/blender/blenvm/compile/bvm_codegen.cc
index 3145231..decf283 100644
--- a/source/blender/blenvm/compile/bvm_codegen.cc
+++ b/source/blender/blenvm/compile/bvm_codegen.cc
@@ -296,17 +296,92 @@ static void sort_nodes(const NodeGraph &graph, NodeList &result)
 	}
 }
 
+typedef std::map<ConstSocketPair, int> SocketUserMap;
+
+static void count_output_users(const NodeGraph &graph, SocketUserMap &users)
+{
+	users.clear();
+	for (NodeGraph::NodeInstanceMap::const_iterator it = graph.nodes.begin(); it != graph.nodes.end(); ++it) {
+		const NodeInstance &node = it->second;
+		for (int i = 0; i < node.outputs.size(); ++i) {
+			ConstSocketPair key(&node, node.type->outputs[i].name);
+			users[key] = 0;
+		}
+	}
+	
+	for (NodeGraph::NodeInstanceMap::const_iterator it = graph.nodes.begin(); it != graph.nodes.end(); ++it) {
+		const NodeInstance &node = it->second;
+		
+		/* note: pass nodes are normally removed, but can exist for debugging purposes */
+		if (node.type->is_pass)
+			continue;
+		
+		for (int i = 0; i < node.inputs.size(); ++i) {
+			if (node.has_input_link(i)) {
+				ConstSocketPair key(node.find_input_link_node(i),
+				                    node.find_input_link_socket(i)->name);
+				users[key] += 1;
+			}
+		}
+	}
+	for (NodeGraph::OutputList::const_iterator it = graph.outputs.begin(); it != graph.outputs.end(); ++it) {
+		const NodeGraphOutput &output = *it;
+		
+		if (output.link_node && output.link_socket) {
+			ConstSocketPair key(output.link_node, output.link_socket->name);
+			users[key] += 1;
+		}
+	}
+}
+
+static OpCode ptr_init_opcode(const TypeDesc &typedesc)
+{
+	switch (typedesc.base_type) {
+		case BVM_FLOAT:
+		case BVM_FLOAT3:
+		case BVM_FLOAT4:
+		case BVM_INT:
+		case BVM_MATRIX44:
+		case BVM_POINTER:
+			return OP_NOOP;
+		
+		case BVM_MESH:
+			return OP_INIT_MESH_PTR;
+	}
+	return OP_NOOP;
+}
+
+static OpCode ptr_release_opcode(const TypeDesc &typedesc)
+{
+	switch (typedesc.base_type) {
+		case BVM_FLOAT:
+		case BVM_FLOAT3:
+		case BVM_FLOAT4:
+		case BVM_INT:
+		case BVM_MATRIX44:
+		case BVM_POINTER:
+			return OP_NOOP;
+		
+		case BVM_MESH:
+			return OP_RELEASE_MESH_PTR;
+	}
+	return OP_NOOP;
+}
+
 Function *BVMCompiler::codegen_function(const NodeGraph &graph)
 {
-	typedef std::pair<const NodeInstance *, const NodeSocket *> SocketPair;
-	typedef std::map<SocketPair, StackIndex> SocketIndexMap;
+	typedef std::map<ConstSocketPair, StackIndex> SocketIndexMap;
 	
 	fn = new Function();
 	
 	NodeList sorted_nodes;
 	sort_nodes(graph, sorted_nodes);
 	
-	SocketIndexMap socket_index;
+	SocketUserMap output_users;
+	count_output_users(graph, output_users);
+	
+	SocketIndexMap input_index;
+	SocketIndexMap output_index;
 	
 	for (NodeList::const_iterator it = sorted_nodes.begin(); it != sorted_nodes.end(); ++it) {
 		const NodeInstance &node = **it;
@@ -315,9 +390,10 @@ Function *BVMCompiler::codegen_function(const NodeGraph &graph)
 		if (op == OP_NOOP)
 			continue;
 		
+		/* prepare input stack entries */
 		for (int i = 0; i < node.type->inputs.size(); ++i) {
 			const NodeSocket &input = node.type->inputs[i];
-			SocketPair key(&node, &input);
+			ConstSocketPair key(&node, input.name);
 			
 			if (node.is_input_constant(i)) {
 				/* value is stored directly in the instructions list,
@@ -325,41 +401,75 @@ Function *BVMCompiler::codegen_function(const NodeGraph &graph)
 				 */
 			}
 			else if (node.has_input_link(i)) {
-				const NodeInstance *link_node = node.find_input_link_node(i);
-				const NodeSocket *link_socket = node.find_input_link_socket(i);
-				SocketPair link_key(link_node, link_socket);
-				socket_index[key] = socket_index[link_key];
+				ConstSocketPair link_key(node.find_input_link_node(i),
+				                         node.find_input_link_socket(i)->name);
+				input_index[key] = output_index[link_key];
 			}
 			else if (node.has_input_value(i)) {
 				Value *value = node.find_input_value(i);
-				socket_index[key] = codegen_value(value);
+				input_index[key] = codegen_value(value);
 			}
 			else {
-				socket_index[key] = codegen_value(input.default_value);
+				input_index[key] = codegen_value(input.default_value);
 			}
 		}
 		
-		push_opcode(op);
+		/* initialize output data stack entries */
+		for (int i = 0; i < node.type->outputs.size(); ++i) {
+			const NodeSocket &output = node.type->outputs[i];
+			ConstSocketPair key(&node, output.name);
+			
+			output_index[key] = assign_stack_index(output.typedesc);
+			
+			/* if necessary, add a user count initializer */
+			OpCode init_op = ptr_init_opcode(output.typedesc);
+			if (init_op != OP_NOOP) {
+				int users = output_users[key];
+				if (users > 0) {
+					push_opcode(init_op);
+					push_stack_index(output_index[key]);
+					push_int(users);
+				}
+			}
+		}
 		
+		/* write main opcode */
+		push_opcode(op);
+		/* write input stack offsets and constants */
 		for (int i = 0; i < node.type->inputs.size(); ++i) {
 			const NodeSocket &input = node.type->inputs[i];
-			SocketPair key(&node, &input);
+			ConstSocketPair key(&node, input.name);
 			
 			if (node.is_input_constant(i)) {
 				Value *value = node.find_input_value(i);
 				codegen_constant(value);
 			}
 			else {
-				push_stack_index(socket_index[key]);
+				push_stack_index(input_index[key]);
 			}
 		}
+		/* write output stack offsets */
 		for (int i = 0; i < node.type->outputs.size(); ++i) {
 			const NodeSocket &output = node.type->outputs[i];
-			SocketPair key(&node, &output);
+			ConstSocketPair key(&node, output.name);
 			
-			socket_index[key] = assign_stack_index(output.typedesc);
+			push_stack_index(output_index[key]);
+		}
+		
+		/* release input data stack entries */
+		for (int i = 0; i < node.type->inputs.size(); ++i) {
+			const NodeSocket &input = node.type->inputs[i];
 			
-			push_stack_index(socket_index[key]);
+			if (node.has_input_link(i)) {
+				ConstSocketPair link_key(node.find_input_link_node(i),
+				                         node.find_input_link_socket(i)->name);
+				OpCode release_op = ptr_release_opcode(input.typedesc);
+				
+				if (release_op != OP_NOOP) {
+					push_opcode(release_op);
+					push_stack_index(output_index[link_key]);
+				}
+			}
 		}
 	}
 	
@@ -371,9 +481,9 @@ Function *BVMCompiler::codegen_function(const NodeGraph &graph)
 		ReturnValue &rval = fn->add_return_value(TypeDesc(output.type), output.name);
 		
 		if (output.link_node && output.link_socket) {
-			SocketPair link_key(output.link_node, output.link_socket);
+			ConstSocketPair link_key(output.link_node, output.link_socket->name);
 			
-			rval.stack_offset = socket_index[link_key];
+			rval.stack_offset = output_index[link_key];
 		}
 		else {
 			rval.stack_offset = codegen_value(output.default_value);
diff --git a/source/blender/blenvm/compile/bvm_nodegraph.h b/source/blender/blenvm/compile/bvm_node

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list