[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