[Bf-blender-cvs] [2030217] object_nodes: Use derivative functions for calculating dual values using the forward accumulation method.

Lukas Tönne noreply at git.blender.org
Wed May 25 11:58:52 CEST 2016


Commit: 2030217042ef4ad83ce292f3ec80308689d00ab9
Author: Lukas Tönne
Date:   Tue May 24 18:14:11 2016 +0200
Branches: object_nodes
https://developer.blender.org/rB2030217042ef4ad83ce292f3ec80308689d00ab9

Use derivative functions for calculating dual values using the forward accumulation method.

Only a few functions have derivatives defined yet.

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

M	source/blender/blenvm/llvm/llvm_compiler.h
M	source/blender/blenvm/llvm/llvm_compiler_dual.cc
M	source/blender/blenvm/llvm/llvm_engine.cc
M	source/blender/blenvm/llvm/llvm_engine.h
M	source/blender/blenvm/llvm/llvm_modules.cc
M	source/blender/blenvm/llvm/llvm_modules.h
M	source/blender/blenvm/modules/mod_defines.h
M	source/blender/blenvm/modules/mod_math.h

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

diff --git a/source/blender/blenvm/llvm/llvm_compiler.h b/source/blender/blenvm/llvm/llvm_compiler.h
index 4579095..535150a 100644
--- a/source/blender/blenvm/llvm/llvm_compiler.h
+++ b/source/blender/blenvm/llvm/llvm_compiler.h
@@ -72,8 +72,7 @@ struct LLVMCompilerBase {
 	FunctionLLVM *compile_function(const string &name, const NodeGraph &graph, int opt_level);
 	void debug_function(const string &name, const NodeGraph &graph, int opt_level, FILE *file);
 	
-	/* XXX TODO some methods are used by static template functions, which require public access ... */
-//protected:
+protected:
 	LLVMCompilerBase();
 	
 	llvm::LLVMContext &context() const;
@@ -130,7 +129,9 @@ private:
 
 struct LLVMTextureCompiler : public LLVMCompilerBase {
 	llvm::Type *get_value_type(const TypeSpec *spec, bool is_constant);
-	llvm::Function *declare_elementary_node_function(llvm::Module *mod, const NodeType *nodetype, const string &name);
+	llvm::Function *declare_elementary_node_function(
+	        llvm::Module *mod, const NodeType *nodetype, const string &name,
+	        bool with_derivatives);
 	
 	llvm::Module *get_nodes_module() const { return m_nodes_module; }
 	
@@ -140,8 +141,8 @@ struct LLVMTextureCompiler : public LLVMCompilerBase {
 	llvm::Constant *create_node_value_constant(const NodeValue *node_value);
 	
 	bool set_node_function_impl(OpCode op, const NodeType *nodetype,
-	                            llvm::Function *value_func,
-	                            std::vector<llvm::Function*> deriv_funcs);
+	                            llvm::Function *value_func, llvm::Function * dual_func);
+	void define_elementary_functions(OpCode op, llvm::Module *mod, const string &nodetype_name);
 	void define_dual_function_wrapper(llvm::Module *mod, const string &nodetype_name);
 	void define_nodes_module();
 	
diff --git a/source/blender/blenvm/llvm/llvm_compiler_dual.cc b/source/blender/blenvm/llvm/llvm_compiler_dual.cc
index 91ebb0e..340f979 100644
--- a/source/blender/blenvm/llvm/llvm_compiler_dual.cc
+++ b/source/blender/blenvm/llvm/llvm_compiler_dual.cc
@@ -127,31 +127,46 @@ llvm::Constant *LLVMTextureCompiler::create_node_value_constant(const NodeValue
 	return bvm_create_llvm_constant(context(), node_value);
 }
 
-llvm::Function *LLVMTextureCompiler::declare_elementary_node_function(llvm::Module *mod, const NodeType *nodetype, const string &name)
+llvm::Function *LLVMTextureCompiler::declare_elementary_node_function(
+        llvm::Module *mod, const NodeType *nodetype, const string &name,
+        bool with_derivatives)
 {
 	using namespace llvm;
 	
+	bool error;
+	
 	std::vector<Type *> input_types, output_types;
 	for (int i = 0; i < nodetype->num_inputs(); ++i) {
 		const NodeInput *input = nodetype->find_input(i);
 		const TypeSpec *typespec = input->typedesc.get_typespec();
+		
 		Type *type = bvm_get_llvm_type(context(), typespec, false);
-		if (type == NULL)
+		if (type == NULL) {
+			error = true;
 			break;
+		}
 		if (use_elementary_argument_pointer(typespec))
 			type = type->getPointerTo();
+		
 		input_types.push_back(type);
+		if (with_derivatives && bvm_type_has_dual_value(typespec)) {
+			/* second argument for derivative */
+			input_types.push_back(type);
+		}
 	}
 	for (int i = 0; i < nodetype->num_outputs(); ++i) {
 		const NodeOutput *output = nodetype->find_output(i);
 		const TypeSpec *typespec = output->typedesc.get_typespec();
+		
 		Type *type = bvm_get_llvm_type(context(), typespec, false);
-		if (type == NULL)
+		if (type == NULL) {
+			error = true;
 			break;
+		}
+		
 		output_types.push_back(type);
 	}
-	if (input_types.size() != nodetype->num_inputs() ||
-	    output_types.size() != nodetype->num_outputs()) {
+	if (error) {
 		/* some arguments could not be handled */
 		return NULL;
 	}
@@ -162,28 +177,22 @@ llvm::Function *LLVMTextureCompiler::declare_elementary_node_function(llvm::Modu
 	return func;
 }
 
-bool LLVMTextureCompiler::set_node_function_impl(OpCode op, const NodeType *nodetype,
-                                                     llvm::Function *value_func,
-                                                     std::vector<llvm::Function*> deriv_funcs)
+bool LLVMTextureCompiler::set_node_function_impl(OpCode op, const NodeType *UNUSED(nodetype),
+                                                 llvm::Function *value_func, llvm::Function *deriv_func)
 {
 	using namespace llvm;
 	
 	typedef std::vector<Value*> ValueList;
 	
+	/* XXX TODO needs implementation for derivatives */
+	UNUSED_VARS(deriv_func);
+	return false;
+	
 	ValueList value_args;
 	value_args.reserve(value_func->arg_size());
 	for (Function::arg_iterator a = value_func->arg_begin(); a != value_func->arg_end(); ++a)
 		value_args.push_back(a);
 	
-#if 0 /* TODO only do the value function for now */
-	std::vector<ValueList> deriv_args(nodetype->num_inputs());
-	for (int n = 0; n < nodetype->num_inputs(); ++n) {
-		deriv_args[n].reserve(deriv_funcs[n]->arg_size());
-		for (Function::arg_iterator a = deriv_funcs[n]->arg_begin(); a != deriv_funcs[n]->arg_end(); ++a)
-			deriv_args[n].push_back(a);
-	}
-#endif
-	
 	switch (op) {
 		case OP_VALUE_FLOAT: {
 			BasicBlock *block = BasicBlock::Create(context(), "entry", value_func);
@@ -216,8 +225,7 @@ bool LLVMTextureCompiler::set_node_function_impl(OpCode op, const NodeType *node
 	}
 }
 
-template <OpCode op>
-static void define_elementary_functions(LLVMTextureCompiler &C, llvm::Module *mod, const string &nodetype_name)
+void LLVMTextureCompiler::define_elementary_functions(OpCode op, llvm::Module *mod, const string &nodetype_name)
 {
 	using namespace llvm;
 	
@@ -225,19 +233,18 @@ static void define_elementary_functions(LLVMTextureCompiler &C, llvm::Module *mo
 	if (nodetype == NULL)
 		return;
 	
-	string value_name = llvm_value_function_name(nodetype->name());
 	/* declare function */
-	Function *value_func = C.declare_elementary_node_function(mod, nodetype, value_name);
-	/* declare partial derivatives wrt. the input arguments */
-	std::vector<Function *> deriv_funcs(nodetype->num_inputs());
-#if 0 /* TODO only do the value function for now */
-	for (int arg_n = -1; arg_n < nodetype->num_inputs(); ++arg_n) {
-		string deriv_name = llvm_deriv_function_name(nodetype->name(), arg_n);
-		deriv_funcs[arg_n] = C.declare_elementary_node_function(mod, nodetype, deriv_name);
+	BLI_assert(llvm_has_external_impl_value(op));
+	Function *value_func = declare_elementary_node_function(
+	                           mod, nodetype, llvm_value_function_name(nodetype->name()), false);
+	
+	Function *deriv_func = NULL;
+	if (llvm_has_external_impl_deriv(op)) {
+		deriv_func = declare_elementary_node_function(
+		                mod, nodetype, llvm_deriv_function_name(nodetype->name()), true);
 	}
-#endif
 	
-	C.set_node_function_impl(op, nodetype, value_func, deriv_funcs);
+	set_node_function_impl(op, nodetype, value_func, deriv_func);
 }
 
 void LLVMTextureCompiler::define_dual_function_wrapper(llvm::Module *mod, const string &nodetype_name)
@@ -253,13 +260,8 @@ void LLVMTextureCompiler::define_dual_function_wrapper(llvm::Module *mod, const
 	Function *value_func = llvm_find_external_function(mod, value_name);
 	BLI_assert(value_func != NULL && "Could not find node function!");
 	
-#if 0 /* TODO only do the value function for now */
-	std::vector<Function *> deriv_funcs(nodetype->num_inputs());
-	for (int n = -1; n < nodetype->num_inputs(); ++n) {
-		string deriv_name = llvm_deriv_function_name(nodetype->name(), n);
-		deriv_funcs[n] = llvm_find_external_function(mod, deriv_name);
-	}
-#endif
+	string deriv_name = llvm_deriv_function_name(nodetype->name());
+	Function *deriv_func = llvm_find_external_function(mod, deriv_name);
 	
 	/* wrapper function */
 	Function *func = declare_node_function(mod, nodetype);
@@ -275,7 +277,7 @@ void LLVMTextureCompiler::define_dual_function_wrapper(llvm::Module *mod, const
 	std::vector<Value*> in_value, in_dx, in_dy;
 	std::vector<Value*> out_value, out_dx, out_dy; 
 	/* arguments for calculating main value and partial derivatives */
-	std::vector<Value*> call_args;
+	std::vector<Value*> call_args_value, call_args_dx, call_args_dy;
 	
 	Function::arg_iterator arg_it = func->arg_begin();
 	/* output arguments */
@@ -297,7 +299,10 @@ void LLVMTextureCompiler::define_dual_function_wrapper(llvm::Module *mod, const
 		out_value.push_back(val);
 		out_dx.push_back(dx);
 		out_dy.push_back(dy);
-		call_args.push_back(val);
+		
+		call_args_value.push_back(val);
+		call_args_dx.push_back(dx);
+		call_args_dy.push_back(dy);
 	}
 	/* input arguments */
 	for (int i = 0; i < nodetype->num_inputs(); ++i, ++arg_it) {
@@ -325,22 +330,27 @@ void LLVMTextureCompiler::define_dual_function_wrapper(llvm::Module *mod, const
 		in_value.push_back(val);
 		in_dx.push_back(dx);
 		in_dy.push_back(dy);
-		call_args.push_back(val);
+		
+		call_args_value.push_back(val);
+		
+		/* derivative functions take input value as well as its derivative */
+		call_args_dx.push_back(val);
+		call_args_dx.push_back(dx);
+		
+		call_args_dy.push_back(val);
+		call_args_dy.push_back(dy);
 	}
 	
 	/* calculate value */
-	builder.CreateCall(value_func, call_args);
-#if 0 /* TODO only do the value function for now */
-	/* calculate partial derivatives wrt. each input */
-	for (int i = 0; i < nodetype->num_inputs(); ++i, ++arg_it) {
-		const NodeInput *input = nodetype->find_input(i);
-		const TypeSpec *typespec = input->typedesc.get_typespec();
+	builder.CreateCall(value_func, call_args_value);
+	
+	if (deriv_func) {
+		builder.CreateCall(deriv_func, call_args_dx);
+		builder.CreateCall(deriv_func, call_args_dy);
+	}
+	else {
 		
-		if (deriv_funcs[i] != NULL) {
-			
-		}
 	}
-#endif
 	
 	builder.CreateRetVoid();
 }
@@ -352,7 +362,7 @@ void LLVMTextureCompiler::define_nodes_module()
 	Module *mod = new llvm::Module("texture_nodes", context());
 	
 #define DEF_OPCODE(op) \
-	define_elementary_functions<OP_##op>(*this, mod, STRINGIFY(op));
+	define_elementary_functions(OP_##op, mod, STRINGIFY(op));
 	
 	BVM_DEFINE_OPCODES
 	
diff --git a/source/blender/blenvm/llvm/llvm_engine.cc b/source/blender/blenvm/llvm/llvm_engine.cc
index a5f1f8a..7223f0c 100644
--- a/source/blender/blenvm/llvm/llvm_engine.cc
+++ b/source/blender/blenvm/llvm/l

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list