[Bf-blender-cvs] [926819d] object_nodes: Use a Scope concept for avoiding codegen for existing nodes.

Lukas Tönne noreply at git.blender.org
Thu Jun 16 09:16:51 CEST 2016


Commit: 926819d82f7ab63d03c65197fd59f14259fc08fa
Author: Lukas Tönne
Date:   Thu Jun 16 09:10:35 2016 +0200
Branches: object_nodes
https://developer.blender.org/rB926819d82f7ab63d03c65197fd59f14259fc08fa

Use a Scope concept for avoiding codegen for existing nodes.

Rather than a single socket value map, use a "scope" to keep track of which
nodes are already generated. This reintroduces the "block" idea from earlier
versions, but at the later codegen stage rather than the node graph.

Describing scope on the level of nodes becomes quite clumsy and ambiguous,
and moves nodes further away from the UI representation. The compiler can
handle this more elegantly without requiring persistent data.

Scopes can be nested. This is not used yet, but will allow scoped variables
later on, where the variables being used for a node path depend on its scope.

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

M	source/blender/blenvm/llvm/llvm_compiler.cc
M	source/blender/blenvm/llvm/llvm_compiler.h

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

diff --git a/source/blender/blenvm/llvm/llvm_compiler.cc b/source/blender/blenvm/llvm/llvm_compiler.cc
index 98f8362..dd14637 100644
--- a/source/blender/blenvm/llvm/llvm_compiler.cc
+++ b/source/blender/blenvm/llvm/llvm_compiler.cc
@@ -48,6 +48,57 @@
 
 namespace blenvm {
 
+Scope::Scope(Scope *parent) :
+    parent(parent)
+{
+}
+
+bool Scope::has_node(const NodeInstance *node) const
+{
+	/* XXX this is not ideal, but we can expect all outputs
+	 * to be mapped once a node is added.
+	 */
+	ConstOutputKey key(node, node->type->find_output(0));
+	return has_value(key);
+}
+
+bool Scope::has_value(const ConstOutputKey &key) const
+{
+	const Scope *scope = this;
+	while (scope) {
+		SocketValueMap::const_iterator it = scope->values.find(key);
+		if (it != scope->values.end()) {
+			return true;
+		}
+		
+		scope = scope->parent;
+	}
+	return false;
+}
+
+ValueHandle Scope::find_value(const ConstOutputKey &key) const
+{
+	const Scope *scope = this;
+	while (scope) {
+		SocketValueMap::const_iterator it = scope->values.find(key);
+		if (it != scope->values.end()) {
+			return it->second;
+		}
+		
+		scope = scope->parent;
+	}
+	return ValueHandle(0);
+}
+
+void Scope::set_value(const ConstOutputKey &key, ValueHandle value)
+{
+	bool ok = values.insert(SocketValueMap::value_type(key, value)).second;
+	BLI_assert(ok && "Could not insert socket value!");
+	UNUSED_VARS(ok);
+}
+
+/* ------------------------------------------------------------------------- */
+
 LLVMCompilerBase::LLVMCompilerBase() :
     m_module(NULL),
     m_globals_ptr(NULL)
@@ -127,13 +178,14 @@ llvm::BasicBlock *LLVMCompilerBase::codegen_function_body_expression(const NodeG
 		}
 	}
 	
+	Scope scope_main(NULL);
+	
 	for (int i = 0; i < num_outputs; ++i) {
 		const NodeGraph::Output &output = graph.outputs[i];
 		const TypeSpec *typespec = output.typedesc.get_typespec();
 		
-		ExpressionMap node_outputs;
-		expand_node(block, output.key.node, node_outputs);
-		ValueHandle value = node_outputs.at(output.key);
+		expand_node(block, output.key.node, scope_main);
+		ValueHandle value = scope_main.find_value(output.key);
 		
 		store_return_value(block, typespec, value, output_args[i]);
 	}
@@ -171,23 +223,26 @@ llvm::Function *LLVMCompilerBase::codegen_node_function(const string &name, cons
 	return func;
 }
 
-void LLVMCompilerBase::expand_node(llvm::BasicBlock *block, const NodeInstance *node, ExpressionMap &outputs)
+void LLVMCompilerBase::expand_node(llvm::BasicBlock *block, const NodeInstance *node, Scope &scope)
 {
+	if (scope.has_node(node))
+		return;
+	
 	switch (node->type->kind()) {
 		case NODE_TYPE_FUNCTION:
 		case NODE_TYPE_KERNEL:
-			expand_expression_node(block, node, outputs);
+			expand_expression_node(block, node, scope);
 			break;
 		case NODE_TYPE_PASS:
-			expand_pass_node(block, node, outputs);
+			expand_pass_node(block, node, scope);
 			break;
 		case NODE_TYPE_ARG:
-			expand_argument_node(block, node, outputs);
+			expand_argument_node(block, node, scope);
 			break;
 	}
 }
 
-void LLVMCompilerBase::expand_pass_node(llvm::BasicBlock *block, const NodeInstance *node, ExpressionMap &outputs)
+void LLVMCompilerBase::expand_pass_node(llvm::BasicBlock *block, const NodeInstance *node, Scope &scope)
 {
 	using namespace llvm;
 	
@@ -195,28 +250,24 @@ void LLVMCompilerBase::expand_pass_node(llvm::BasicBlock *block, const NodeInsta
 	BLI_assert(node->num_outputs() == 1);
 	
 	ConstInputKey input = node->input(0);
-	ConstOutputKey output = node->output(0);
 	BLI_assert(input.value_type() == INPUT_EXPRESSION);
 	
-	ExpressionMap pass_outputs;
-	expand_node(block, input.link().node, pass_outputs);
-	
-	outputs[output] = pass_outputs.at(input.link());
+	expand_node(block, input.link().node, scope);
 }
 
-void LLVMCompilerBase::expand_argument_node(llvm::BasicBlock *block, const NodeInstance *node, ExpressionMap &outputs)
+void LLVMCompilerBase::expand_argument_node(llvm::BasicBlock *block, const NodeInstance *node, Scope &scope)
 {
 	using namespace llvm;
 	
 	BLI_assert(node->num_outputs() == 1);
 	
 	ConstOutputKey output = node->output(0);
-	outputs[output] = m_argument_values.at(output);
+	scope.set_value(output, m_argument_values.at(output));
 	
 	UNUSED_VARS(block);
 }
 
-void LLVMCompilerBase::expand_expression_node(llvm::BasicBlock *block, const NodeInstance *node, ExpressionMap &outputs)
+void LLVMCompilerBase::expand_expression_node(llvm::BasicBlock *block, const NodeInstance *node, Scope &scope)
 {
 	using namespace llvm;
 	
@@ -241,7 +292,7 @@ void LLVMCompilerBase::expand_expression_node(llvm::BasicBlock *block, const Nod
 		ValueHandle value = alloc_node_value(block, typespec);
 		append_output_arguments(args, typespec, value);
 		
-		outputs.insert(ExpressionMap::value_type(output, value));
+		scope.set_value(output, value);
 	}
 	
 	/* set input arguments */
@@ -255,10 +306,10 @@ void LLVMCompilerBase::expand_expression_node(llvm::BasicBlock *block, const Nod
 				break;
 			}
 			case INPUT_EXPRESSION: {
-				ExpressionMap link_outputs;
-				expand_node(block, input.link().node, link_outputs);
+				expand_node(block, input.link().node, scope);
 				
-				append_input_value(block, args, typespec, link_outputs.at(input.link()));
+				ValueHandle link_value = scope.find_value(input.link());
+				append_input_value(block, args, typespec, link_value);
 				break;
 			}
 			case INPUT_VARIABLE: {
diff --git a/source/blender/blenvm/llvm/llvm_compiler.h b/source/blender/blenvm/llvm/llvm_compiler.h
index 0851b84..44f8eb0 100644
--- a/source/blender/blenvm/llvm/llvm_compiler.h
+++ b/source/blender/blenvm/llvm/llvm_compiler.h
@@ -75,38 +75,18 @@ struct FunctionParameter {
 typedef std::vector<FunctionParameter> FunctionParameterList;
 
 typedef void* ValueHandle;
-typedef std::map<ConstOutputKey, ValueHandle> ExpressionMap;
-
-#if 0
-struct Expression {
-	explicit Expression(const NodeInstance *node) :
-	    m_node(node)
-	{}
+typedef std::map<ConstOutputKey, ValueHandle> SocketValueMap;
+struct Scope {
+	Scope(Scope *parent);
 	
-	bool operator < (const Expression &other) const
-	{
-		if (m_node == other.m_node) {
-			return false;
-		}
-		else
-			return m_node < other.m_node;
-	}
-	
-	bool operator == (const Expression &other) const
-	{
-		if (m_node == other.m_node) {
-			return true;
-		}
-		else
-			return false;
-	}
-	
-	const NodeInstance *node() const { return m_node; }
+	bool has_node(const NodeInstance *node) const;
+	bool has_value(const ConstOutputKey &key) const;
+	ValueHandle find_value(const ConstOutputKey &key) const;
+	void set_value(const ConstOutputKey &key, ValueHandle value);
 	
-private:
-	const NodeInstance *m_node;
+	Scope *parent;
+	SocketValueMap values;
 };
-#endif
 
 struct LLVMCompilerBase {
 	typedef std::map<ConstOutputKey, ValueHandle> ArgumentValueMap;
@@ -127,10 +107,10 @@ protected:
 	llvm::BasicBlock *codegen_function_body_expression(const NodeGraph &graph, llvm::Function *func);
 	llvm::Function *codegen_node_function(const string &name, const NodeGraph &graph);
 	
-	void expand_node(llvm::BasicBlock *block, const NodeInstance *node, ExpressionMap &outputs);
-	void expand_pass_node(llvm::BasicBlock *block, const NodeInstance *node, ExpressionMap &outputs);
-	void expand_argument_node(llvm::BasicBlock *block, const NodeInstance *node, ExpressionMap &outputs);
-	void expand_expression_node(llvm::BasicBlock *block, const NodeInstance *node, ExpressionMap &outputs);
+	void expand_node(llvm::BasicBlock *block, const NodeInstance *node, Scope &scope);
+	void expand_pass_node(llvm::BasicBlock *block, const NodeInstance *node, Scope &scope);
+	void expand_argument_node(llvm::BasicBlock *block, const NodeInstance *node, Scope &scope);
+	void expand_expression_node(llvm::BasicBlock *block, const NodeInstance *node, Scope &scope);
 	
 	virtual void node_graph_begin() = 0;
 	virtual void node_graph_end() = 0;




More information about the Bf-blender-cvs mailing list