[Bf-blender-cvs] [498ca41] object_nodes: Added graphviz debug output for parsed bvm node graphs.

Lukas Tönne noreply at git.blender.org
Tue Nov 24 09:43:51 CET 2015


Commit: 498ca41b8adf55b939e26f066d1887629088a2fd
Author: Lukas Tönne
Date:   Tue Nov 3 13:51:32 2015 +0100
Branches: object_nodes
https://developer.blender.org/rB498ca41b8adf55b939e26f066d1887629088a2fd

Added graphviz debug output for parsed bvm node graphs.

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

M	source/blender/blenvm/BVM_api.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
M	source/blender/makesrna/intern/rna_blenvm.c
M	source/blender/makesrna/intern/rna_texture_api.c

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

diff --git a/source/blender/blenvm/BVM_api.h b/source/blender/blenvm/BVM_api.h
index a91a4ae..b24b217 100644
--- a/source/blender/blenvm/BVM_api.h
+++ b/source/blender/blenvm/BVM_api.h
@@ -32,6 +32,8 @@
  *  \ingroup bvm
  */
 
+#include <stdio.h>
+
 #include "BVM_types.h"
 
 #ifdef __cplusplus
@@ -114,7 +116,8 @@ void BVM_eval_forcefield(struct BVMEvalGlobals *globals, struct BVMEvalContext *
 struct Tex;
 struct TexResult;
 
-struct BVMExpression *BVM_gen_texture_expression(const struct BVMEvalGlobals *globals, struct Tex *tex, struct bNodeTree *btree);
+struct BVMExpression *BVM_gen_texture_expression(const struct BVMEvalGlobals *globals, struct Tex *tex,
+                                                 struct bNodeTree *btree, FILE *debug_file);
 
 void BVM_eval_texture(struct BVMEvalContext *context, struct BVMExpression *expr,
                       struct TexResult *target,
diff --git a/source/blender/blenvm/compile/bvm_nodegraph.cc b/source/blender/blenvm/compile/bvm_nodegraph.cc
index 3554878..5e02277 100644
--- a/source/blender/blenvm/compile/bvm_nodegraph.cc
+++ b/source/blender/blenvm/compile/bvm_nodegraph.cc
@@ -501,6 +501,10 @@ void NodeGraph::set_output_link(const string &name, NodeInstance *link_node, con
 	}
 }
 
+/* === DEBUGGING === */
+
+#define NL "\r\n"
+
 void NodeGraph::dump(std::ostream &s)
 {
 	s << "NodeGraph\n";
@@ -546,6 +550,142 @@ void NodeGraph::dump(std::ostream &s)
 	}
 }
 
+static const char *debug_graphviz_fontname = "helvetica";
+static float debug_graphviz_graph_label_size = 20.0f;
+static float debug_graphviz_node_label_size = 14.0f;
+
+struct DebugContext {
+	FILE *file;
+};
+
+static void debug_fprintf(const DebugContext &ctx, const char *fmt, ...) ATTR_PRINTF_FORMAT(2, 3);
+static void debug_fprintf(const DebugContext &ctx, const char *fmt, ...)
+{
+	va_list args;
+	va_start(args, fmt);
+	vfprintf(ctx.file, fmt, args);
+	va_end(args);
+}
+
+static void debug_graphviz_node(const DebugContext &ctx, const NodeInstance *node)
+{
+	const char *shape = "box";
+	const char *style = "filled,rounded";
+	const char *color = "black";
+	const char *fillcolor = "gainsboro";
+	float penwidth = 1.0f;
+	string name = node->type->name;
+	
+	debug_fprintf(ctx, "// %s\n", node->name.c_str());
+	debug_fprintf(ctx, "\"node_%p\"", node);
+	debug_fprintf(ctx, "[");
+	
+	/* html label including rows for input/output sockets
+	 * http://www.graphviz.org/doc/info/shapes.html#html
+	 */
+	debug_fprintf(ctx, "label=<<TABLE BORDER=\"0\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"4\">");
+	debug_fprintf(ctx, "<TR><TD COLSPAN=\"2\">%s</TD></TR>", name.c_str());
+	int numin = node->type->inputs.size();
+	int numout = node->type->outputs.size();
+	for (int i = 0; i < numin || i < numout; ++i) {
+		debug_fprintf(ctx, "<TR>");
+		
+		if (i < numin) {
+			string name_in = node->type->inputs[i].name;
+			debug_fprintf(ctx, "<TD PORT=\"%s\" BORDER=\"1\">%s</TD>", name_in.c_str(), name_in.c_str());
+		}
+		else
+			debug_fprintf(ctx, "<TD></TD>");
+			
+		if (i < numout) {
+			string name_out = node->type->outputs[i].name;
+			debug_fprintf(ctx, "<TD PORT=\"%s\" BORDER=\"1\">%s</TD>", name_out.c_str(), name_out.c_str());
+		}
+		else
+			debug_fprintf(ctx, "<TD></TD>");
+		
+		debug_fprintf(ctx, "</TR>");
+	}
+	debug_fprintf(ctx, "</TABLE>>");
+	
+	debug_fprintf(ctx, ",fontname=\"%s\"", debug_graphviz_fontname);
+	debug_fprintf(ctx, ",fontsize=\"%f\"", debug_graphviz_node_label_size);
+	debug_fprintf(ctx, ",shape=\"%s\"", shape);
+	debug_fprintf(ctx, ",style=\"%s\"", style);
+	debug_fprintf(ctx, ",color=\"%s\"", color);
+	debug_fprintf(ctx, ",fillcolor=\"%s\"", fillcolor);
+	debug_fprintf(ctx, ",penwidth=\"%f\"", penwidth);
+	debug_fprintf(ctx, "];" NL);
+	debug_fprintf(ctx, NL);
+}
+
+static void debug_graphviz_node_links(const DebugContext &ctx, const NodeInstance *node)
+{
+	for (NodeInstance::InputMap::const_iterator it = node->inputs.begin(); it != node->inputs.end(); ++it) {
+		const NodeInstance::InputInstance &input = it->second;
+		
+		if (input.link_node && input.link_socket) {
+			float penwidth = 2.0f;
+			
+			const NodeInstance *tail = input.link_node;
+			const string &tail_socket = input.link_socket->name;
+			const NodeInstance *head = node;
+			const string &head_socket = it->first;
+			debug_fprintf(ctx, "// %s:%s -> %s:%s\n",
+			              tail->name.c_str(), tail_socket.c_str(),
+			              head->name.c_str(), head_socket.c_str());
+			debug_fprintf(ctx, "\"node_%p\":%s", tail, tail_socket.c_str());
+			debug_fprintf(ctx, " -> ");
+			debug_fprintf(ctx, "\"node_%p\":%s", head, head_socket.c_str());
+	
+			debug_fprintf(ctx, "[");
+			/* Note: without label an id seem necessary to avoid bugs in graphviz/dot */
+			debug_fprintf(ctx, "id=\"%s\"", (string("A") + head->name.c_str() + "B" + tail->name.c_str()).c_str());
+			
+			debug_fprintf(ctx, ",penwidth=\"%f\"", penwidth);
+			debug_fprintf(ctx, "];" NL);
+			debug_fprintf(ctx, NL);
+		}
+		else {
+			
+		}
+	}
+}
+
+void NodeGraph::dump_graphviz(FILE *f, const string &label)
+{
+	DebugContext ctx;
+	ctx.file = f;
+	
+	debug_fprintf(ctx, "digraph depgraph {" NL);
+	debug_fprintf(ctx, "rankdir=LR;" NL);
+	debug_fprintf(ctx, "graph [");
+	debug_fprintf(ctx, "labelloc=\"t\"");
+	debug_fprintf(ctx, ",fontsize=%f", debug_graphviz_graph_label_size);
+	debug_fprintf(ctx, ",fontname=\"%s\"", debug_graphviz_fontname);
+	debug_fprintf(ctx, ",label=\"%s\"", label.c_str());
+//	debug_fprintf(ctx, ",splines=ortho");
+	debug_fprintf(ctx, "];" NL);
+
+	for (NodeInstanceMap::const_iterator it = nodes.begin(); it != nodes.end(); ++it) {
+		const NodeInstance *node = &it->second;
+		
+		debug_graphviz_node(ctx, node);
+	}
+	
+	for (NodeInstanceMap::const_iterator it = nodes.begin(); it != nodes.end(); ++it) {
+		const NodeInstance *node = &it->second;
+		
+		debug_graphviz_node_links(ctx, node);
+	}
+
+//	deg_debug_graphviz_legend(ctx);
+
+	debug_fprintf(ctx, "}" NL);
+}
+
+#undef NL
+
 /* ------------------------------------------------------------------------- */
 
 OpCode get_opcode_from_node_type(const string &node)
diff --git a/source/blender/blenvm/compile/bvm_nodegraph.h b/source/blender/blenvm/compile/bvm_nodegraph.h
index 0857fa9..ab0f416 100644
--- a/source/blender/blenvm/compile/bvm_nodegraph.h
+++ b/source/blender/blenvm/compile/bvm_nodegraph.h
@@ -258,6 +258,7 @@ struct NodeGraph {
 	}
 	
 	void dump(std::ostream &stream = std::cout);
+	void dump_graphviz(FILE *f, const string &label);
 	
 	NodeInstanceMap nodes;
 	InputList inputs;
diff --git a/source/blender/blenvm/intern/bvm_api.cc b/source/blender/blenvm/intern/bvm_api.cc
index a1f67e7..15101a7 100644
--- a/source/blender/blenvm/intern/bvm_api.cc
+++ b/source/blender/blenvm/intern/bvm_api.cc
@@ -451,7 +451,8 @@ static void parse_tex_nodes(CompileContext */*_context*/, bNodeTree *btree, bvm:
 }
 
 
-struct BVMExpression *BVM_gen_texture_expression(const struct BVMEvalGlobals *globals, struct Tex *tex, bNodeTree *btree)
+struct BVMExpression *BVM_gen_texture_expression(const struct BVMEvalGlobals *globals, struct Tex *tex,
+                                                 bNodeTree *btree, FILE *debug_file)
 {
 	using namespace bvm;
 	
@@ -465,6 +466,10 @@ struct BVMExpression *BVM_gen_texture_expression(const struct BVMEvalGlobals *gl
 	CompileContext comp(_GLOBALS(globals));
 	parse_tex_nodes(&comp, btree, &graph);
 	
+	if (debug_file) {
+		graph.dump_graphviz(debug_file, "Texture Expression Graph");
+	}
+	
 	BVMCompiler compiler;
 	Expression *expr = compiler.codegen_expression(graph);
 	
@@ -530,7 +535,7 @@ struct BVMExpression *BVM_texture_cache_acquire(Tex *tex)
 	else if (tex->use_nodes && tex->nodetree) {
 		EvalGlobals globals;
 		
-		BVMExpression *expr = BVM_gen_texture_expression((BVMEvalGlobals *)(&globals), tex, tex->nodetree);
+		BVMExpression *expr = BVM_gen_texture_expression((BVMEvalGlobals *)(&globals), tex, tex->nodetree, NULL);
 		
 		bvm_tex_cache[tex] = _EXPR(expr);
 		
diff --git a/source/blender/makesrna/intern/rna_blenvm.c b/source/blender/makesrna/intern/rna_blenvm.c
index b0dc6bf..78e859d 100644
--- a/source/blender/makesrna/intern/rna_blenvm.c
+++ b/source/blender/makesrna/intern/rna_blenvm.c
@@ -29,6 +29,8 @@
 
 #include "MEM_guardedalloc.h"
 
+#include "BLI_path_util.h"
+
 #include "RNA_define.h"
 #include "RNA_enum_types.h"
 
@@ -65,6 +67,8 @@ static void rna_BVMNodeGraph_set_output(struct BVMNodeGraph *graph,
 	return BVM_nodegraph_set_output_link(graph, name, node, socket);
 }
 
+/* ------------------------------------------------------------------------- */
+
 static void rna_BVMNodeInstance_set_value_float(struct BVMNodeInstance *node, const char *socket, float value)
 {
 	BVM_node_set_input_value_float(node, socket, value);
diff --git a/source/blender/makesrna/intern/rna_texture_api.c b/source/blender/makesrna/intern/rna_texture_api.c
index a27ba6e..2cb8a79 100644
--- a/source/blender/makesrna/intern/rna_texture_api.c
+++ b/source/blender/makesrna/intern/rna_texture_api.c
@@ -44,6 +44,7 @@
 #include "BKE_global.h"
 #include "RE_pipeline.h"
 #include "RE_shader_ext.h"
+#include "BVM_api.h"
 
 static void save_envmap(struct EnvMap *env, bContext *C, ReportList *reports, const char *filepath,
                         struct Scene *scene, float layout[12])
@@ -82,6 +83,26 @@ static void texture_evaluate(struct Tex *tex, float value[3], float r_color[4])
 	r_color[3] = texres.tin;
 }
 
+static void rna_Texture_debug_nodes_graphviz(struct Tex *tex, const char *filename)
+{
+	FILE *f = fopen(filename, "w");
+	if (f == NULL)
+		return;
+	
+	if (tex->nodetree && tex->use_nodes) {
+		struct BVMEvalGlobals *globals;
+		struct BVMExpression *expr;
+		
+		globals = BVM_globals_create();
+		expr = BVM_gen_texture_expression(globals, tex, tex->nodetree, f);
+		
+		BVM_expression_free(expr);
+		BVM_globals_free(globals);
+	}
+	
+	fclose(f);
+}
+
 #else
 
 void RNA_api_texture(StructRNA *srna)
@@ -100,6 +121,10 @@ void RNA_api_texture(StructRNA *srna)
 	RNA_def_property_flag(parm, PROP_THICK_WRAP);
 	RNA_def_function_output(func, parm);
 
+	func = RNA_def_function(srna, "debug_nodes_graphviz", "rna_Texture_debug_nodes_graphviz");
+	parm = RNA_def_string_file_path(func, "filename", NULL, 

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list