[Bf-blender-cvs] [831a4a3] strand_nodes: Support dual values for autodiff'ing in GLSL codegen right from the start.

Lukas Tönne noreply at git.blender.org
Thu Jul 21 17:41:12 CEST 2016


Commit: 831a4a3f96c9ab1ffae5ce62aedf7547749a9e37
Author: Lukas Tönne
Date:   Thu Jul 21 17:38:33 2016 +0200
Branches: strand_nodes
https://developer.blender.org/rB831a4a3f96c9ab1ffae5ce62aedf7547749a9e37

Support dual values for autodiff'ing in GLSL codegen right from the start.

Note that for the hair displacement function we would only be interested
in a single derivative (the tangent). For now we just use the existing
2-variable duals, later on this can be generalized to avoid unnecessary
and confusing code emission.

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

M	source/blender/blenvm/glsl/glsl_codegen.cc
M	source/blender/blenvm/glsl/glsl_codegen.h
M	source/blender/blenvm/llvm/llvm_codegen.cc
M	source/blender/blenvm/llvm/llvm_modules.cc
M	source/blender/blenvm/llvm/llvm_types.cc
M	source/blender/blenvm/llvm/llvm_types.h

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

diff --git a/source/blender/blenvm/glsl/glsl_codegen.cc b/source/blender/blenvm/glsl/glsl_codegen.cc
index 9095c4f..f23001b 100644
--- a/source/blender/blenvm/glsl/glsl_codegen.cc
+++ b/source/blender/blenvm/glsl/glsl_codegen.cc
@@ -43,6 +43,19 @@ extern "C" {
 
 namespace blenvm {
 
+/* replace non-alphanumeric chars with underscore */
+static string sanitize_name(const string &name)
+{
+	string s = name;
+	for (string::iterator it = s.begin(); it != s.end(); ++it) {
+		char &c = *it;
+		if (c != '_' && !isalnum(c))
+			c = '_';
+	}
+	return s;
+}
+
+
 GLSLValue::GLSLValue(const string &name) :
     m_name(name)
 {
@@ -62,14 +75,23 @@ GLSLCodeGenerator::~GLSLCodeGenerator()
 {
 }
 
-ValueHandle GLSLCodeGenerator::get_handle(const GLSLValue *value)
+ValueHandle GLSLCodeGenerator::get_handle(const GLSLCodeGenerator::DualValue &value)
 {
-	return (ValueHandle)value;
+	return (ValueHandle)value.value();
 }
 
-GLSLValue *GLSLCodeGenerator::get_value(ValueHandle handle)
+ValueHandle GLSLCodeGenerator::register_value(const DualValue &value)
 {
-	return (GLSLValue *)handle;
+	ValueHandle handle = get_handle(value);
+	bool ok = m_valuemap.insert(HandleValueMap::value_type(handle, value)).second;
+	BLI_assert(ok && "Could not register value");
+	UNUSED_VARS(ok);
+	return handle;
+}
+
+const GLSLCodeGenerator::DualValue &GLSLCodeGenerator::get_value(ValueHandle handle) const
+{
+	return m_valuemap.at(handle);
 }
 
 GLSLValue *GLSLCodeGenerator::create_value(const TypeSpec *UNUSED(typespec), const string &name, bool make_unique)
@@ -105,14 +127,33 @@ void GLSLCodeGenerator::node_graph_begin(const string &name, const NodeGraph *gr
 	for (int i = 0; i < num_inputs; ++i) {
 		const NodeGraph::Input *input = graph->get_input(i);
 		const TypeSpec *typespec = input->typedesc.get_typespec();
+		string typestring = bvm_glsl_get_type(typespec, true);
+		string basename = sanitize_name(input->name);
 		
-		/* Note: argument names are unique! */
-		GLSLValue *value = create_value(typespec, input->name, false);
-		m_input_args.push_back(value);
+		DualValue dval;
+		if (bvm_glsl_type_has_dual_value(typespec)) {
+			/* Note: argument names are already unique */
+			dval = DualValue(create_value(typespec, basename + "_V", false),
+			                 create_value(typespec, basename + "_DX", false),
+			                 create_value(typespec, basename + "_DY", false));
+			
+			if (i > 0)
+				m_code << ", ";
+			m_code << "in " << typestring << " " << dval.value()->name()
+			       << ", in " << typestring << " " << dval.dx()->name()
+			       << ", in " << typestring << " " << dval.dy()->name();
+		}
+		else {
+			/* Note: argument names are already unique */
+			dval = DualValue(create_value(typespec, basename, false), NULL, NULL);
+			
+			if (i > 0)
+				m_code << ", ";
+			m_code << "in " << typestring << " " << dval.value()->name();
+		}
 		
-		if (i > 0)
-			m_code << ", ";
-		m_code << "in " << bvm_glsl_get_type(typespec, true)<< " " << value->name();
+		register_value(dval);
+		m_input_args.push_back(dval);
 	}
 	
 	size_t num_outputs = graph->outputs.size();
@@ -121,14 +162,33 @@ void GLSLCodeGenerator::node_graph_begin(const string &name, const NodeGraph *gr
 	for (int i = 0; i < num_outputs; ++i) {
 		const NodeGraph::Output *output = graph->get_output(i);
 		const TypeSpec *typespec = output->typedesc.get_typespec();
+		string typestring = bvm_glsl_get_type(typespec, true);
+		string basename = sanitize_name(output->name);
 		
-		/* Note: argument names are unique! */
-		GLSLValue *value = create_value(typespec, output->name, false);
-		m_output_args.push_back(value);
+		DualValue dval;
+		if (bvm_glsl_type_has_dual_value(typespec)) {
+			/* Note: argument names are already unique */
+			dval = DualValue(create_value(typespec, basename + "_V", false),
+			                 create_value(typespec, basename + "_DX", false),
+			                 create_value(typespec, basename + "_DY", false));
+			
+			if (i > 0)
+				m_code << ", ";
+			m_code << "out " << typestring << " " << dval.value()->name()
+			       << ", out " << typestring << " " << dval.dx()->name()
+			       << ", out " << typestring << " " << dval.dy()->name();
+		}
+		else {
+			/* Note: argument names are already unique */
+			dval = DualValue(create_value(typespec, basename, false), NULL, NULL);
+			
+			if (i > 0)
+				m_code << ", ";
+			m_code << "out " << typestring << " " << dval.value()->name();
+		}
 		
-		if (i > 0)
-			m_code << ", ";
-		m_code << "out " << bvm_glsl_get_type(typespec, true)<< " " << value->name();
+		register_value(dval);
+		m_output_args.push_back(dval);
 	}
 	m_code << ")\n";
 	
@@ -142,42 +202,71 @@ void GLSLCodeGenerator::node_graph_end()
 
 void GLSLCodeGenerator::store_return_value(size_t output_index, const TypeSpec *typespec, ValueHandle handle)
 {
-	GLSLValue *arg = m_output_args[output_index];
-	GLSLValue *val = get_value(handle);
+	DualValue arg = m_output_args[output_index];
+	DualValue val = get_value(handle);
 	
-//	if (bvm_glsl_type_has_dual_value(typespec)) {
-//		Value *value_ptr = builder.CreateStructGEP(arg, 0, sanitize_name(arg->getName().str() + "_V"));
-//		Value *dx_ptr = builder.CreateStructGEP(arg, 1, sanitize_name(arg->getName().str() + "_DX"));
-//		Value *dy_ptr = builder.CreateStructGEP(arg, 2, sanitize_name(arg->getName().str() + "_DY"));
-		
-//		bvm_llvm_copy_value(context(), m_block, value_ptr, dval.value(), typespec);
-//		bvm_llvm_copy_value(context(), m_block, dx_ptr, dval.dx(), typespec);
-//		bvm_llvm_copy_value(context(), m_block, dy_ptr, dval.dy(), typespec);
-//	}
-//	else {
-		bvm_glsl_copy_value(m_code, arg, val, typespec);
-//	}
+	bvm_glsl_copy_value(m_code, arg.value(), val.value(), typespec);
+	if (bvm_glsl_type_has_dual_value(typespec)) {
+		bvm_glsl_copy_value(m_code, arg.dx(), val.dx(), typespec);
+		bvm_glsl_copy_value(m_code, arg.dy(), val.dy(), typespec);
+	}
 }
 
 ValueHandle GLSLCodeGenerator::map_argument(size_t input_index, const TypeSpec *UNUSED(typespec))
 {
-	GLSLValue *arg = m_input_args[input_index];
-	return get_handle(arg);
+	return get_handle(m_input_args[input_index]);
 }
 
 ValueHandle GLSLCodeGenerator::alloc_node_value(const TypeSpec *typespec, const string &name)
 {
-	GLSLValue *value = create_value(typespec, name, true);
-	m_code << bvm_glsl_get_type(typespec, true)<< " " << value->name() << ";\n";
-	return get_handle(value);
+	string typestring = bvm_glsl_get_type(typespec, false);
+	string basename = sanitize_name(name);
+	
+	DualValue dval;
+	if (bvm_glsl_type_has_dual_value(typespec)) {
+		dval = DualValue(create_value(typespec, basename + "_V", true),
+		                 create_value(typespec, basename + "_DX", true),
+		                 create_value(typespec, basename + "_DY", true));
+		
+		m_code << typestring << " " << dval.value()->name() << ";\n";
+		m_code << typestring << " " << dval.dx()->name() << ";\n";
+		m_code << typestring << " " << dval.dy()->name() << ";\n";
+	}
+	else {
+		dval = DualValue(create_value(typespec, basename + "_V", true), NULL, NULL);
+		
+		m_code << typestring << " " << dval.value()->name() << ";\n";
+	}
+	
+	return register_value(dval);
 }
 
 ValueHandle GLSLCodeGenerator::create_constant(const TypeSpec *typespec, const NodeConstant *node_value)
 {
-	GLSLValue *value = create_value(typespec, "constval", true);
-	m_code << "const " << bvm_glsl_get_type(typespec, true) << " " << value->name()
-	       << " = const " << bvm_glsl_create_constant(node_value) << ";\n";
-	return get_handle(value);
+	string typestring = bvm_glsl_get_type(typespec, false);
+	string basename = "constval";
+	
+	DualValue dval;
+	if (bvm_glsl_type_has_dual_value(typespec)) {
+		dval = DualValue(create_value(typespec, basename + "_V", true),
+		                 create_value(typespec, basename + "_DX", true),
+		                 create_value(typespec, basename + "_DY", true));
+		
+		m_code << "const " << typestring << " " << dval.value()->name()
+		       << " = const " << bvm_glsl_create_constant(node_value) << ";\n";
+		m_code << "const " << typestring << " " << dval.dx()->name()
+		       << " = const " << bvm_glsl_create_zero(typespec) << ";\n";
+		m_code << "const " << typestring << " " << dval.dy()->name()
+		       << " = const " << bvm_glsl_create_zero(typespec) << ";\n";
+	}
+	else {
+		dval = DualValue(create_value(typespec, basename + "_V", true), NULL, NULL);
+		
+		m_code << "const " << typestring << " " << dval.value()->name()
+		       << " = const " << bvm_glsl_create_constant(node_value) << ";\n";
+	}
+	
+	return register_value(dval);
 }
 
 void GLSLCodeGenerator::eval_node(const NodeType *nodetype,
diff --git a/source/blender/blenvm/glsl/glsl_codegen.h b/source/blender/blenvm/glsl/glsl_codegen.h
index 9e8d1dd..390fe30 100644
--- a/source/blender/blenvm/glsl/glsl_codegen.h
+++ b/source/blender/blenvm/glsl/glsl_codegen.h
@@ -55,15 +55,18 @@ struct TypeDesc;
 
 struct GLSLCodeGenerator : public CodeGenerator {
 	typedef std::list<GLSLValue> Values;
-	typedef std::vector<GLSLValue*> Arguments;
+	typedef Dual2<GLSLValue*> DualValue;
+	typedef std::map<ValueHandle, DualValue> HandleValueMap;
+	typedef std::vector<DualValue> Arguments;
 	
 	GLSLCodeGenerator();
 	~GLSLCodeGenerator();
 	
 	const stringstream &code() const { return m_code; }
 	
-	ValueHandle get_handle(const GLSLValue *value);
-	GLSLValue *get_value(ValueHandle handle);
+	static ValueHandle get_handle(const DualValue &value);
+	ValueHandle register_value(const DualValue &value);
+	const DualValue &get_value(ValueHandle handle) const;
 	
 	void finalize_function();
 	void debug_function(FILE *file);
@@ -86,6 +89,8 @@ protected:
 	
 private:
 	Values m_values;
+	HandleValueMap m_valuemap;
+	
 	Arguments m_input_args;
 	Arguments m_output_args;
 	
diff --git a/source/blender/blenvm/llvm/llvm_codegen.cc b/source/blender/blenvm/llvm/llvm_codegen.cc
index 729d9d2..9f93155 100644
--- a/source/blender/blenvm/llvm/llvm_codegen.cc
+++ b/source/blender/blenvm/llvm/llvm_codegen.cc
@@ -260,7 +260,7 @@ void LLVMCodeGenerator::store_return_value(size_t output_index, const TypeSpec *
 	Argument *arg = m_output_args[output_index];
 	DualValue dval = m_values.at(handle);
 	
-	if (bvm_type_has_dual_value(typespec)) {
+	if (bvm

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list