[Bf-blender-cvs] [067dfb3] object_nodes: Adapted the node blockify procedure to the new concept of expressions and variables.

Lukas Tönne noreply at git.blender.org
Fri Jan 29 12:18:59 CET 2016


Commit: 067dfb3e5274bb59cc63545fa1b73012e3fbd8c0
Author: Lukas Tönne
Date:   Fri Jan 29 11:56:15 2016 +0100
Branches: object_nodes
https://developer.blender.org/rB067dfb3e5274bb59cc63545fa1b73012e3fbd8c0

Adapted the node blockify procedure to the new concept of expressions and variables.

The internal bvm nodes now can contain (implicit) cyclic connections, owing to the
connection of variable inputs to local variable outputs of kernel nodes. These link
cycles are never created explicitly by the node parser (pynodes), but are a result
of the semi-functional programming nature of the nodes: each node constitutes a
function of the local variables defined inside a kernel block. When the nodes are first
constructed from the user-level nodes these inputs are left unbound, and are then
resolved backwards as the individual node functions are inlined.

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

M	source/blender/blenvm/compile/bvm_codegen.h
M	source/blender/blenvm/compile/bvm_nodegraph.cc
M	source/blender/blenvm/compile/bvm_nodegraph.h
M	source/blender/blenvm/intern/bvm_api.cc

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

diff --git a/source/blender/blenvm/compile/bvm_codegen.h b/source/blender/blenvm/compile/bvm_codegen.h
index 421fb83..ef44bb9 100644
--- a/source/blender/blenvm/compile/bvm_codegen.h
+++ b/source/blender/blenvm/compile/bvm_codegen.h
@@ -49,15 +49,6 @@ struct NodeGraph;
 struct NodeInstance;
 struct TypeDesc;
 
-struct NodeIndexCmp {
-	bool operator () (const NodeInstance *a, const NodeInstance *b) const
-	{
-		return a->index < b->index;
-	}
-};
-
-typedef std::set<const NodeInstance *, NodeIndexCmp> OrderedNodeSet;
-
 typedef std::map<ConstInputKey, StackIndex> InputIndexMap;
 typedef std::map<ConstOutputKey, StackIndex> OutputIndexMap;
 typedef std::map<ConstOutputKey, int> OutputUsersMap;
diff --git a/source/blender/blenvm/compile/bvm_nodegraph.cc b/source/blender/blenvm/compile/bvm_nodegraph.cc
index 737d7b7..7535c06 100644
--- a/source/blender/blenvm/compile/bvm_nodegraph.cc
+++ b/source/blender/blenvm/compile/bvm_nodegraph.cc
@@ -570,13 +570,6 @@ void NodeBlock::local_arg_set(const string &name, const ConstOutputKey &arg)
 	m_local_args[name] = arg;
 }
 
-void NodeBlock::insert(NodeInstance *node)
-{
-	m_nodes.insert(node);
-	assert(node->block == NULL);
-	node->block = this;
-}
-
 void NodeBlock::prune(const NodeSet &used_nodes)
 {
 	NodeSet used_block_nodes;
@@ -1091,143 +1084,98 @@ void NodeGraph::inline_function_calls()
 	}
 }
 
-void NodeGraph::make_args_local(NodeBlock &block, NodeMap &block_map, NodeSet &block_visited, const NodeInstance *arg_node)
+bool NodeGraph::add_block_node(NodeBlock &block, const OutputSet &local_vars,
+                               NodeInstance *node, NodeSet &visited)
 {
-	if (!arg_node->type->is_kernel_node())
-		return;
+	if (visited.find(node) != visited.end())
+		return block.nodes().find(node) != block.nodes().end();
+	visited.insert(node);
 	
-	for (int i = 0; i < arg_node->num_outputs(); ++i) {
-		const NodeOutput *output = arg_node->type->find_output(i);
-		
-		if (output->value_type == OUTPUT_VARIABLE) {
-			const Input *graph_input = get_input(output->name);
-			assert(graph_input);
-			
-			if (graph_input->key) {
-				block_visited.insert(graph_input->key.node);
-				OutputKey local_arg(copy_node(graph_input->key.node, block_map), graph_input->key.socket);
-				block.insert(local_arg.node);
-				block.local_arg_set(output->name, local_arg);
-			}
-		}
-	}
-}
-
-bool NodeGraph::add_block_node(NodeInstance *node, NodeBlock &block, NodeMap &block_map, NodeSet &block_visited)
-{
-	/* determines if the node is part of the block */
-	bool is_block_node = block_map.find(node) != block_map.end();
-	
-	if (block_visited.find(node) != block_visited.end())
-		return is_block_node;
-	assert(!is_block_node); /* can't have been mapped yet */
-	block_visited.insert(node);
+	bool uses_local_vars = false;
 	
 	for (int i = 0; i < node->num_inputs(); ++i) {
 		InputKey input = node->input(i);
-		if (input.value_type() == INPUT_CONSTANT) {
-			if (!block.parent())
-				is_block_node |= true;
-		}
-		else if (input.value_type() == INPUT_EXPRESSION) {
-			if (!block.parent())
-				is_block_node |= blockify_expression(input, block, block_map, block_visited);
-		}
-		else {
-			OutputKey output = input.link();
-			if (output) {
-				is_block_node |= add_block_node(output.node, block, block_map, block_visited);
-			}
+		OutputKey link = input.link();
+		if (link) {
+			uses_local_vars |= (local_vars.find(link) != local_vars.end());
+			uses_local_vars |= add_block_node(block, local_vars, link.node, visited);
 		}
 	}
 	
-	if (is_block_node) {
-		NodeInstance *block_node;
-		if (block.parent()) {
-			block_node = copy_node(node, block_map);
-		}
-		else {
-			block_node = node;
-			block_map[node] = node;
+	if (uses_local_vars) {
+		block.nodes().insert(node);
+		
+		/* create a sub-block for nested kernels */
+		if (node->type->is_kernel_node()) {
+			blocks.push_back(NodeBlock(node->name, &block));
+			NodeBlock &kernel_block = blocks.back();
+			NodeSet kernel_visited;
+			
+			OutputSet kernel_vars;
+			for (int i = 0; i < node->num_outputs(); ++i) {
+				OutputKey output = node->output(i);
+				if (output.value_type() == OUTPUT_VARIABLE)
+					kernel_vars.insert(output);
+			}
+			
+			for (int i = 0; i < node->num_inputs(); ++i) {
+				InputKey input = node->input(i);
+				OutputKey link = input.link();
+				if (link) {
+					add_block_node(kernel_block, kernel_vars, link.node, kernel_visited);
+				}
+			}
 		}
-		block.insert(block_node);
+		
 		return true;
 	}
 	else
 		return false;
 }
 
-bool NodeGraph::blockify_expression(const InputKey &input, NodeBlock &block, NodeMap &block_map, NodeSet &block_visited)
+void NodeGraph::blockify_nodes()
 {
-	OutputKey link_key = input.link();
-	if (!link_key)
-		return false;
-	NodeInstance *link_node = link_key.node;
-	
-	bool is_block_node = false;
-	
-	/* generate a local block for the input expression */
-	blocks.push_back(NodeBlock(input.node->name + ":" + input.socket->name, &block));
-	NodeBlock &expr_block = blocks.back();
-	NodeSet expr_visited;
-	NodeMap expr_block_map;
-	
-	make_args_local(expr_block, expr_block_map, expr_visited, input.node);
-	
-	add_block_node(link_node, expr_block, expr_block_map, expr_visited);
+	blocks.push_back(NodeBlock("main", NULL));
+	NodeBlock &main = blocks.back();
+	NodeSet main_visited;
 	
-	if (expr_block_map.find(link_node) != expr_block_map.end()) {
-		/* remap the input link */
-		input.link_set(OutputKey(expr_block_map.at(link_node), link_key.socket));
-	}
-	else {
-		/* use the input directly if no expression nodes are generated (no local arg dependencies) */
-		is_block_node |= add_block_node(link_node, block, block_map, block_visited);
+	/* add all nodes to main block by default */
+	for (NodeInstanceMap::iterator it = nodes.begin(); it != nodes.end(); ++it) {
+		NodeInstance *node = it->second;
+		main.nodes().insert(node);
 	}
 	
-	/* find node inputs in the expression block that use values outside of it,
-	 * which means these must be included in the parent block
-	 */
-	for (NodeSet::iterator it = expr_block.nodes().begin(); it != expr_block.nodes().end(); ++it) {
-		NodeInstance *node = *it;
-		for (int i = 0; i < node->num_inputs(); ++i) {
-			InputKey expr_input = node->input(i);
-			NodeInstance *link_node = expr_input.link().node;
-			if (link_node && expr_block.nodes().find(link_node) == expr_block.nodes().end())
-				is_block_node |= add_block_node(link_node, block, block_map, block_visited);
+	OutputSet local_vars;
+	for (OutputList::const_iterator it = outputs.begin(); it != outputs.end(); ++it) {
+		const Output &output = *it;
+		if (output.key) {
+			add_block_node(main, local_vars, output.key.node, main_visited);
 		}
 	}
 	
-	return is_block_node;
-}
-
-void NodeGraph::blockify_nodes()
-{
-	blocks.push_back(NodeBlock("main", NULL));
-	NodeBlock &main = blocks.back();
-	NodeSet main_visited;
-	NodeMap main_map;
-	
-	/* input argument nodes must always be included in main,
-	 * to provide reliable storage for caller arguments
+	/* remove nested block nodes from all parent blocks,
+	 * so that nodes are only assigned to the top-most block.
+	 * XXX this method could be implemented much more efficiently,
+	 * but in practice should be sufficient as long as nesting doesn't get too deep.
 	 */
-	for (InputList::const_iterator it = inputs.begin(); it != inputs.end(); ++it) {
-		const Input &input = *it;
-		if (input.key) {
-			NodeInstance *node = input.key.node;
-			main_visited.insert(node);
-			
-			NodeInstance *block_node = node; /* for main block: same as original node */
-			main_map[node] = block_node;
-			main.insert(block_node);
+	for (NodeBlockList::iterator it = blocks.begin(); it != blocks.end(); ++it) {
+		NodeBlock &block = *it;
+		
+		for (NodeBlock *parent = block.parent(); parent; parent = parent->parent()) {
+			for (NodeSet::iterator it_node = block.nodes().begin(); it_node != block.nodes().end(); ++it_node) {
+				NodeInstance *node = *it_node;
+				parent->nodes().erase(node);
+			}
+		}
+	}
+	/* finally set the node->block pointers */
+	for (NodeBlockList::iterator it = blocks.begin(); it != blocks.end(); ++it) {
+		NodeBlock &block = *it;
+		for (NodeSet::iterator it_node = block.nodes().begin(); it_node != block.nodes().end(); ++it_node) {
+			NodeInstance *node = *it_node;
+			node->block = █
 		}
 	}
-	
-//	for (OutputList::const_iterator it = outputs.begin(); it != outputs.end(); ++it) {
-//		const Output &output = *it;
-//		if (output.key)
-//			add_block_node(output.key.node, main, main_map, main_visited);
-//	}
 }
 
 static void used_nodes_append(NodeInstance *node, NodeSet &used_nodes)
@@ -1253,10 +1201,6 @@ void NodeGraph::remove_unused_nodes()
 		used_nodes_append(output.key.node, used_nodes);
 	}
 	/* make sure unused inputs don't leave dangling node pointers */
-	for (NodeGraph::NodeBlockList::iterator it = blocks.begin(); it != blocks.end(); ++it) {
-		NodeBlock &block = *it;
-		block.prune(used_nodes);
-	}
 	for (NodeGraph::InputList::iterator it = inputs.begin(); it != inputs.end(); ++it) {
 		Input &input = *it;
 		if (used_nodes.find(input.key.node) == used_nodes.end()) {
@@ -1288,9 +1232,9 @@ static void assign_node_index(NodeInstance *node, int *next_index)
 	node->index = 1;
 	
 	for (int i = 0; i < node->num_inputs(); ++i) {
-		NodeInstance *link_node = node->link(i).node;
-		if (link_node) {
-			assign_node_index(link_node, next_index);
+		OutputKey link = node->link(i);
+		if (link && link.value_type() == OUTPUT_EXPRESSION) {
+			assign_node_index(link.node, next_index);
 		}
 	}
 	
@@ -1310,10 +1254,10 @@ void NodeGraph::finalize()
 {
 	ensure_valid_expression_inputs();
 	skip_pass_nodes();
-//	blockify_nodes();
 	inline_function_calls();
 	remove_unused_nodes();
 	sort_nodes();
+	blockify_nodes();
 }
 
 /* ------------------------------------------------------------------------- */
diff --git a/source/blender/blenvm/compile/bvm_nodegraph.h b/source/blender/blenvm/compile/bvm_nodegraph.h
index 72f5964..1e97151 100644
--- a/source/blender/blenvm/compile/bvm_nodegraph.h
+++ b/source/blender/blenvm/compile/bvm_nodegraph.h
@@ -259,31 +259,42 @@ struct NodeInstance {
 typedef std::set<NodeInstance*> NodeSet;
 typedef std::map<const NodeInstance*, NodeInstance*> 

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list