Cleanup and improvements of the compositor debug output.
authorLukas Toenne <lukas.toenne@googlemail.com>
Fri, 13 Sep 2013 13:36:47 +0000 (13:36 +0000)
committerLukas Toenne <lukas.toenne@googlemail.com>
Fri, 13 Sep 2013 13:36:47 +0000 (13:36 +0000)
Debug code for graphviz output moved to a dedicated file COM_Debug.h/cpp.

The DebugInfo class has only static functions, which are called from a number of places to keep track of what is happening in the compositor. If debugging is disabled these are just inline stubs, so we
don't need #ifdefs everywhere and don't get any overhead.

The graphviz output is much more useful now. DebugInfo keeps track of node names in a static string map for meaningful names. It uses a number of colors for various special operation classes.
ExecutionGroups are indicated in graphviz with clusters.

Currently the graphviz .dot files are stored in the BLI_temporary_dir() folder. A separate dot file is generated for each stage of the ExecutionGroup scheduling, this is intended to give some idea of the
compositor progress, but could still be improved.

14 files changed:
source/blender/compositor/CMakeLists.txt
source/blender/compositor/intern/COM_Debug.cpp [new file with mode: 0644]
source/blender/compositor/intern/COM_Debug.h [new file with mode: 0644]
source/blender/compositor/intern/COM_ExecutionGroup.cpp
source/blender/compositor/intern/COM_ExecutionGroup.h
source/blender/compositor/intern/COM_ExecutionSystem.cpp
source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp
source/blender/compositor/intern/COM_ExecutionSystemHelper.h
source/blender/compositor/intern/COM_NodeBase.h
source/blender/compositor/intern/COM_NodeOperation.h
source/blender/compositor/operations/COM_SetColorOperation.h
source/blender/compositor/operations/COM_SetValueOperation.h
source/blender/compositor/operations/COM_SetVectorOperation.h
source/blender/compositor/operations/COM_TrackPositionOperation.h

index 2904951132127b65e57408072dbdb3e4940fd673..e6a3c33ea5d38d058bd676a8b9780ec9f7275c79 100644 (file)
@@ -101,6 +101,8 @@ set(SRC
        intern/COM_ChannelInfo.h
        intern/COM_SingleThreadedNodeOperation.cpp
        intern/COM_SingleThreadedNodeOperation.h
+       intern/COM_Debug.cpp
+       intern/COM_Debug.h
 
        operations/COM_QualityStepHelper.h
        operations/COM_QualityStepHelper.cpp
diff --git a/source/blender/compositor/intern/COM_Debug.cpp b/source/blender/compositor/intern/COM_Debug.cpp
new file mode 100644 (file)
index 0000000..c061044
--- /dev/null
@@ -0,0 +1,413 @@
+/*
+ * Copyright 2013, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor: 
+ *             Lukas Toenne
+ */
+
+#include "COM_Debug.h"
+
+#ifdef COM_DEBUG
+
+#include <typeinfo>
+#include <map>
+#include <vector>
+
+extern "C" {
+#include "BLI_fileops.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+#include "DNA_node_types.h"
+#include "BKE_node.h"
+}
+
+#include "COM_Node.h"
+#include "COM_ExecutionSystem.h"
+#include "COM_ExecutionGroup.h"
+
+#include "COM_ReadBufferOperation.h"
+#include "COM_ViewerOperation.h"
+#include "COM_WriteBufferOperation.h"
+
+
+int DebugInfo::m_file_index = 0;
+DebugInfo::NodeNameMap DebugInfo::m_node_names;
+std::string DebugInfo::m_current_node_name;
+DebugInfo::GroupStateMap DebugInfo::m_group_states;
+
+std::string DebugInfo::node_name(NodeBase *node)
+{
+       NodeNameMap::const_iterator it = m_node_names.find(node);
+       if (it != m_node_names.end())
+               return it->second;
+       else
+               return "";
+}
+
+void DebugInfo::convert_started()
+{
+       m_node_names.clear();
+}
+
+void DebugInfo::execute_started(ExecutionSystem *system)
+{
+       m_file_index = 1;
+       m_group_states.clear();
+       for (int i = 0; i < system->getExecutionGroups().size(); ++i)
+               m_group_states[system->getExecutionGroups()[i]] = EG_WAIT;
+}
+
+void DebugInfo::node_added(Node *node)
+{
+       m_node_names[node] = std::string(node->getbNode() ? node->getbNode()->name : "");
+}
+
+void DebugInfo::node_to_operations(Node *node)
+{
+       m_current_node_name = m_node_names[node];
+}
+
+void DebugInfo::operation_added(NodeOperation *operation)
+{
+       m_node_names[operation] = m_current_node_name;
+}
+
+void DebugInfo::operation_read_write_buffer(NodeOperation *operation)
+{
+       m_current_node_name = m_node_names[operation];
+}
+
+void DebugInfo::execution_group_started(ExecutionGroup *group)
+{
+       m_group_states[group] = EG_RUNNING;
+}
+
+void DebugInfo::execution_group_finished(ExecutionGroup *group)
+{
+       m_group_states[group] = EG_FINISHED;
+}
+
+int DebugInfo::graphviz_operation(ExecutionSystem *system, NodeOperation *operation, ExecutionGroup *group, char *str, int maxlen)
+{
+       int len = 0;
+       
+       std::string fillcolor = "gainsboro";
+       if (operation->isViewerOperation()) {
+               ViewerOperation *viewer = (ViewerOperation *)operation;
+               if (viewer->isActiveViewerOutput()) {
+                       fillcolor = "lightskyblue1";
+               }
+               else {
+                       fillcolor = "lightskyblue3";
+               }
+       }
+       else if (operation->isOutputOperation(system->getContext().isRendering())) {
+               fillcolor = "dodgerblue1";
+       }
+       else if (operation->isSetOperation()) {
+               fillcolor = "khaki1";
+       }
+       else if (operation->isReadBufferOperation()) {
+               fillcolor = "darkolivegreen3";
+       }
+       else if (operation->isWriteBufferOperation()) {
+               fillcolor = "darkorange";
+       }
+       
+       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "// OPERATION: %p\r\n", operation);
+       if (group)
+               len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "\"O_%p_%p\"", operation, group);
+       else
+               len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "\"O_%p\"", operation);
+       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, " [fillcolor=%s,style=filled,shape=record,label=\"{", fillcolor.c_str());
+       
+       int totinputs = operation->getNumberOfInputSockets();
+       if (totinputs != 0) {
+               len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "{");
+               for (int k = 0; k < totinputs; k++) {
+                       InputSocket *socket = operation->getInputSocket(k);
+                       if (k != 0) {
+                               len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "|");
+                       }
+                       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "<IN_%p>", socket);
+                       switch (socket->getDataType()) {
+                               case COM_DT_VALUE:
+                                       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "Value");
+                                       break;
+                               case COM_DT_VECTOR:
+                                       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "Vector");
+                                       break;
+                               case COM_DT_COLOR:
+                                       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "Color");
+                                       break;
+                       }
+               }
+               len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "}");
+               len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "|");
+       }
+       
+       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "%s\\n(%s)", m_node_names[operation].c_str(), typeid(*operation).name());
+       
+       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, " (%d,%d)", operation->getWidth(), operation->getHeight());
+       
+       int totoutputs = operation->getNumberOfOutputSockets();
+       if (totoutputs != 0) {
+               len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "|");
+               len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "{");
+               for (int k = 0; k < totoutputs; k++) {
+                       OutputSocket *socket = operation->getOutputSocket(k);
+                       if (k != 0) {
+                               len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "|");
+                       }
+                       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "<OUT_%p>", socket);
+                       switch (socket->getDataType()) {
+                               case COM_DT_VALUE:
+                                       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "Value");
+                                       break;
+                               case COM_DT_VECTOR:
+                                       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "Vector");
+                                       break;
+                               case COM_DT_COLOR:
+                                       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "Color");
+                                       break;
+                       }
+               }
+               len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "}");
+       }
+       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "}\"]");
+       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "\r\n");
+       
+       return len;
+}
+
+int DebugInfo::graphviz_legend_color(const char *name, const char *color, char *str, int maxlen)
+{
+       int len = 0;
+       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "<TR><TD>%s</TD><TD BGCOLOR=\"%s\"></TD></TR>\r\n", name, color);
+       return len;
+}
+
+int DebugInfo::graphviz_legend_line(const char *name, const char *color, const char *style, char *str, int maxlen)
+{
+       /* XXX TODO */
+       int len = 0;
+       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "\r\n");
+       return len;
+}
+
+int DebugInfo::graphviz_legend_group(const char *name, const char *color, const char *style, char *str, int maxlen)
+{
+       int len = 0;
+       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "<TR><TD>%s</TD><TD CELLPADDING=\"4\"><TABLE BORDER=\"1\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\"><TR><TD BGCOLOR=\"%s\"></TD></TR></TABLE></TD></TR>\r\n", name, color);
+       return len;
+}
+
+int DebugInfo::graphviz_legend(char *str, int maxlen)
+{
+       int len = 0;
+       
+       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "{\r\n");
+       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "rank = sink;\r\n");
+       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "Legend [shape=none, margin=0, label=<\r\n");
+       
+       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "  <TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"4\">\r\n");
+       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "<TR><TD COLSPAN=\"2\"><B>Legend</B></TD></TR>\r\n");
+       
+       len += graphviz_legend_color("Operation", "gainsboro", str+len, maxlen>len ? maxlen-len : 0);
+       len += graphviz_legend_color("Output", "dodgerblue1", str+len, maxlen>len ? maxlen-len : 0);
+       len += graphviz_legend_color("Viewer", "lightskyblue3", str+len, maxlen>len ? maxlen-len : 0);
+       len += graphviz_legend_color("Active Viewer", "lightskyblue1", str+len, maxlen>len ? maxlen-len : 0);
+       len += graphviz_legend_color("Write Buffer", "darkorange", str+len, maxlen>len ? maxlen-len : 0);
+       len += graphviz_legend_color("Read Buffer", "darkolivegreen3", str+len, maxlen>len ? maxlen-len : 0);
+       len += graphviz_legend_color("Input Value", "khaki1", str+len, maxlen>len ? maxlen-len : 0);
+
+       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "<TR><TD></TD></TR>\r\n");
+
+       len += graphviz_legend_group("Group Waiting", "white", "dashed", str+len, maxlen>len ? maxlen-len : 0);
+       len += graphviz_legend_group("Group Running", "firebrick1", "solid", str+len, maxlen>len ? maxlen-len : 0);
+       len += graphviz_legend_group("Group Finished", "chartreuse4", "solid", str+len, maxlen>len ? maxlen-len : 0);
+       
+       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "</TABLE>\r\n");
+       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, ">];\r\n");
+       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "}\r\n");
+
+       return len;
+}
+
+bool DebugInfo::graphviz_system(ExecutionSystem *system, char *str, int maxlen)
+{
+       char strbuf[64];
+       int len = 0;
+       
+       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "digraph compositorexecution {\r\n");
+       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "ranksep=1.5\r\n");
+       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "splines=false\r\n");
+       
+       int totnodes = system->getNodes().size();
+       for (int i = 0; i < totnodes; i++) {
+               Node *node = system->getNodes()[i];
+               len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "// NODE: %s\r\n", node->getbNode()->typeinfo->ui_name);
+       }
+       
+       int totgroups = system->getExecutionGroups().size();
+       int totops = system->getOperations().size();
+       std::map<NodeOperation *, std::vector<std::string> > op_groups;
+       for (int i = 0; i < totgroups; ++i) {
+               ExecutionGroup *group = system->getExecutionGroups()[i];
+               
+               len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "// GROUP: %d\r\n", i);
+               len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "subgraph cluster_%d{\r\n", i);
+               /* used as a check for executing group */
+               if (m_group_states[group] == EG_WAIT) {
+                       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "style=dashed\r\n");
+               }
+               else if (m_group_states[group] == EG_RUNNING) {
+                       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "style=filled\r\n");
+                       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "color=black\r\n");
+                       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "fillcolor=firebrick1\r\n");
+               }
+               else if (m_group_states[group] == EG_FINISHED) {
+                       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "style=filled\r\n");
+                       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "color=black\r\n");
+                       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "fillcolor=chartreuse4\r\n");
+               }
+               
+               for (int j = 0; j < totops; ++j) {
+                       NodeOperation *operation = system->getOperations()[j];
+                       if (!group->containsOperation(operation))
+                               continue;
+                       
+                       sprintf(strbuf, "_%p", group);
+                       op_groups[operation].push_back(std::string(strbuf));
+                       
+                       len += graphviz_operation(system, operation, group, str+len, maxlen>len ? maxlen-len : 0);
+               }
+               
+//             len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "//  OUTPUTOPERATION: %p\r\n", group->getOutputNodeOperation());
+//             len += snprintf(str+len, maxlen>len ? maxlen-len : 0, " O_%p\r\n", group->getOutputNodeOperation());
+               len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "}\r\n");
+       }
+       
+       /* operations not included in any group */
+       for (int j = 0; j < totops; ++j) {
+               NodeOperation *operation = system->getOperations()[j];
+               if (op_groups.find(operation) != op_groups.end())
+                       continue;
+               
+               op_groups[operation].push_back(std::string(""));
+               
+               len += graphviz_operation(system, operation, 0, str+len, maxlen>len ? maxlen-len : 0);
+       }
+       
+       for (int i = 0; i < totops; i++) {
+               NodeOperation *operation = system->getOperations()[i];
+               
+               if (operation->isReadBufferOperation()) {
+                       ReadBufferOperation *read = (ReadBufferOperation *)operation;
+                       WriteBufferOperation *write = read->getMemoryProxy()->getWriteBufferOperation();
+                       std::vector<std::string> &read_groups = op_groups[read];
+                       std::vector<std::string> &write_groups = op_groups[write];
+                       
+                       for (int k = 0; k < write_groups.size(); ++k) {
+                               for (int l = 0; l < read_groups.size(); ++l) {
+                                       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "\"O_%p%s\" -> \"O_%p%s\" [style=dotted]\r\n", write, write_groups[k].c_str(), read, read_groups[l].c_str());
+                               }
+                       }
+               }
+       }
+       
+       int totcon = system->getConnections().size();
+       for (int i = 0; i < totcon; i++) {
+               SocketConnection *connection = system->getConnections()[i];
+               
+               std::string color;
+               if (!connection->isValid()) {
+                       color = "red";
+               }
+               else {
+                       switch (connection->getFromSocket()->getDataType()) {
+                               case COM_DT_VALUE:
+                                       color = "grey";
+                                       break;
+                               case COM_DT_VECTOR:
+                                       color = "blue";
+                                       break;
+                               case COM_DT_COLOR:
+                                       color = "orange";
+                                       break;
+                       }
+               }
+               
+               NodeBase *from_node = connection->getFromNode();
+               NodeBase *to_node = connection->getToNode();
+               OutputSocket *from_sock = connection->getFromSocket();
+               InputSocket *to_sock = connection->getToSocket();
+               if (from_node->isOperation() && to_node->isOperation()) {
+                       NodeOperation *from_op = (NodeOperation *)from_node;
+                       NodeOperation *to_op = (NodeOperation *)to_node;
+                       std::vector<std::string> &from_groups = op_groups[from_op];
+                       std::vector<std::string> &to_groups = op_groups[to_op];
+                       
+                       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "// CONNECTION: %p.%p -> %p.%p\r\n", from_op, from_sock, to_op, to_sock);
+                       for (int k = 0; k < from_groups.size(); ++k) {
+                               for (int l = 0; l < to_groups.size(); ++l) {
+                                       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "\"O_%p%s\":\"OUT_%p\":s -> \"O_%p%s\":\"IN_%p\":n", from_op, from_groups[k].c_str(), from_sock, to_op, to_groups[l].c_str(), to_sock);
+                                       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, " [color=%s]", color.c_str());
+                                       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "\r\n");
+                               }
+                       }
+               }
+       }
+       
+       len += graphviz_legend(str+len, maxlen>len ? maxlen-len : 0);
+       
+       len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "}\r\n");
+       
+       return (len < maxlen);
+}
+
+void DebugInfo::graphviz(ExecutionSystem *system)
+{
+       char str[1000000];
+       if (graphviz_system(system, str, sizeof(str)-1)) {
+               char basename[FILE_MAX];
+               char filename[FILE_MAX];
+               
+               BLI_snprintf(basename, sizeof(basename), "compositor_%d.dot", m_file_index);
+               BLI_join_dirfile(filename, sizeof(filename), BLI_temporary_dir(), basename);
+               ++m_file_index;
+               
+               FILE *fp = BLI_fopen(filename, "wb");
+               fputs(str, fp);
+               fclose(fp);
+       }
+}
+
+#else
+
+std::string DebugInfo::node_name(NodeBase */*node*/) { return ""; }
+void DebugInfo::convert_started() {}
+void DebugInfo::execute_started(ExecutionSystem */*system*/) {}
+void DebugInfo::node_added(Node */*node*/) {}
+void DebugInfo::node_to_operations(Node */*node*/) {}
+void DebugInfo::operation_added(NodeOperation */*operation*/) {}
+void DebugInfo::operation_read_write_buffer(NodeOperation */*operation*/) {}
+void DebugInfo::execution_group_started(ExecutionGroup */*group*/) {}
+void DebugInfo::execution_group_finished(ExecutionGroup */*group*/) {}
+void DebugInfo::graphviz(ExecutionSystem */*system*/) {}
+
+#endif
diff --git a/source/blender/compositor/intern/COM_Debug.h b/source/blender/compositor/intern/COM_Debug.h
new file mode 100644 (file)
index 0000000..cc10815
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2013, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor: 
+ *             Lukas Toenne
+ */
+
+#ifndef _COM_Debug_h
+#define _COM_Debug_h
+
+#include <map>
+#include <string>
+
+#include "COM_defines.h"
+
+class NodeBase;
+class Node;
+class NodeOperation;
+class ExecutionSystem;
+class ExecutionGroup;
+
+class DebugInfo {
+public:
+       typedef enum {
+               EG_WAIT,
+               EG_RUNNING,
+               EG_FINISHED
+       } GroupState;
+       
+       typedef std::map<NodeBase *, std::string> NodeNameMap;
+       typedef std::map<ExecutionGroup *, GroupState> GroupStateMap;
+       
+       static std::string node_name(NodeBase *node);
+       
+       static void convert_started();
+       static void execute_started(ExecutionSystem *system);
+       
+       static void node_added(Node *node);
+       static void node_to_operations(Node *node);
+       static void operation_added(NodeOperation *operation);
+       static void operation_read_write_buffer(NodeOperation *operation);
+       
+       static void execution_group_started(ExecutionGroup *group);
+       static void execution_group_finished(ExecutionGroup *group);
+       
+       static void graphviz(ExecutionSystem *system);
+       
+#ifdef COM_DEBUG
+protected:
+       static int graphviz_operation(ExecutionSystem *system, NodeOperation *operation, ExecutionGroup *group, char *str, int maxlen);
+       static int graphviz_legend_color(const char *name, const char *color, char *str, int maxlen);
+       static int graphviz_legend_line(const char *name, const char *color, const char *style, char *str, int maxlen);
+       static int graphviz_legend_group(const char *name, const char *color, const char *style, char *str, int maxlen);
+       static int graphviz_legend(char *str, int maxlen);
+       static bool graphviz_system(ExecutionSystem *system, char *str, int maxlen);
+       
+private:
+       static int m_file_index;
+       static NodeNameMap m_node_names;                        /**< map nodes to usable names for debug output */
+       static std::string m_current_node_name;         /**< base name for all operations added by a node */
+       static GroupStateMap m_group_states;            /**< for visualizing group states */
+#endif
+};
+
+#endif
index 255630daff2db28dd377bde2b487d80b27a548b1..50434e1a2a48af7c7b65a007e8b457107fbce54e 100644 (file)
@@ -37,6 +37,7 @@
 #include "COM_ViewerOperation.h"
 #include "COM_ChunkOrder.h"
 #include "COM_ExecutionSystemHelper.h"
+#include "COM_Debug.h"
 
 #include "MEM_guardedalloc.h"
 #include "BLI_math.h"
@@ -343,6 +344,9 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
                        break;
        }
 
+       DebugInfo::execution_group_started(this);
+       DebugInfo::graphviz(graph);
+
        bool breaked = false;
        bool finished = false;
        unsigned int startIndex = 0;
@@ -383,6 +387,8 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
                        breaked = true;
                }
        }
+       DebugInfo::execution_group_finished(this);
+       DebugInfo::graphviz(graph);
 
        MEM_freeN(chunkOrder);
 }
index 537dcb5974a28f79d8bd617be2ae78ba62db784d..47f8447015d7d21655359455185d00278a29f7af 100644 (file)
@@ -422,6 +422,9 @@ public:
 #ifdef WITH_CXX_GUARDEDALLOC
        MEM_CXX_CLASS_ALLOC_FUNCS("COM:ExecutionGroup")
 #endif
+
+       /* allow the DebugInfo class to peek inside without having to add getters for everything */
+       friend class DebugInfo;
 };
 
 #endif
index ad29405d2e9578e8ac1c3199e7f6a2584ac99432..716e99a0fa347445f670eb09f752634d16b55ea4 100644 (file)
@@ -22,8 +22,6 @@
 
 #include "COM_ExecutionSystem.h"
 
-#include <sstream>
-
 #include "PIL_time.h"
 #include "BLI_utildefines.h"
 extern "C" {
@@ -40,6 +38,7 @@ extern "C" {
 #include "COM_WriteBufferOperation.h"
 #include "COM_ReadBufferOperation.h"
 #include "COM_ExecutionSystemHelper.h"
+#include "COM_Debug.h"
 
 #include "BKE_global.h"
 
@@ -101,9 +100,7 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool re
                }
        }
 
-#ifdef COM_DEBUG
-       ExecutionSystemHelper::debugDump(this);
-#endif
+//     DebugInfo::graphviz(this);
 }
 
 ExecutionSystem::~ExecutionSystem()
@@ -133,6 +130,8 @@ ExecutionSystem::~ExecutionSystem()
 
 void ExecutionSystem::execute()
 {
+       DebugInfo::execute_started(this);
+       
        unsigned int order = 0;
        for (vector<NodeOperation *>::iterator iter = this->m_operations.begin(); iter != this->m_operations.end(); ++iter) {
                NodeBase *node = *iter;
@@ -199,11 +198,13 @@ void ExecutionSystem::executeGroups(CompositorPriority priority)
 void ExecutionSystem::addOperation(NodeOperation *operation)
 {
        ExecutionSystemHelper::addOperation(this->m_operations, operation);
-//     operation->setBTree
+       DebugInfo::operation_added(operation);
 }
 
 void ExecutionSystem::addReadWriteBufferOperations(NodeOperation *operation)
 {
+       DebugInfo::operation_read_write_buffer(operation);
+       
        // for every input add write and read operation if input is not a read operation
        // only add read operation to other links when they are attached to buffered operations.
        unsigned int index;
@@ -283,8 +284,10 @@ static void debug_check_node_connections(Node *node)
 void ExecutionSystem::convertToOperations()
 {
        unsigned int index;
+
        for (index = 0; index < this->m_nodes.size(); index++) {
                Node *node = (Node *)this->m_nodes[index];
+               DebugInfo::node_to_operations(node);
                node->convertToOperations(this, &this->m_context);
 
                debug_check_node_connections(node);
index 9024cd33745dcd9bcf95d886fce7daf230b3c1aa..9516deee7e3304e62100eeb1bca1d634151b82ff 100644 (file)
@@ -22,9 +22,6 @@
 
 #include "COM_ExecutionSystemHelper.h"
 
-#include <sstream>
-#include <stdio.h>
-
 #include "PIL_time.h"
 
 #include "COM_Converter.h"
@@ -37,6 +34,7 @@
 #include "COM_WriteBufferOperation.h"
 #include "COM_ReadBufferOperation.h"
 #include "COM_ViewerOperation.h"
+#include "COM_Debug.h"
 
 extern "C" {
 #include "BKE_node.h"
@@ -93,6 +91,8 @@ Node *ExecutionSystemHelper::addNode(vector<Node *>& nodes, bNode *b_node, bool
        if (node) {
                node->setIsInActiveGroup(inActiveGroup);
                addNode(nodes, node);
+               
+               DebugInfo::node_added(node);
        }
        return node;
 }
@@ -166,144 +166,3 @@ SocketConnection *ExecutionSystemHelper::addLink(vector<SocketConnection *>& lin
        links.push_back(newconnection);
        return newconnection;
 }
-
-void ExecutionSystemHelper::debugDump(ExecutionSystem *system)
-{
-       Node *node;
-       NodeOperation *operation;
-       ExecutionGroup *group;
-       SocketConnection *connection;
-       int tot, tot2;
-       printf("-- BEGIN COMPOSITOR DUMP --\r\n");
-       printf("digraph compositorexecution {\r\n");
-       tot = system->getNodes().size();
-       for (int i = 0; i < tot; i++) {
-               node = system->getNodes()[i];
-               printf("// NODE: %s\r\n", node->getbNode()->typeinfo->ui_name);
-       }
-       tot = system->getOperations().size();
-       for (int i = 0; i < tot; i++) {
-               operation = system->getOperations()[i];
-               printf("// OPERATION: %p\r\n", operation);
-               printf("\t\"O_%p\"", operation);
-               printf(" [shape=record,label=\"{");
-               tot2 = operation->getNumberOfInputSockets();
-               if (tot2 != 0) {
-                       printf("{");
-                       for (int j = 0; j < tot2; j++) {
-                               InputSocket *socket = operation->getInputSocket(j);
-                               if (j != 0) {
-                                       printf("|");
-                               }
-                               printf("<IN_%p>", socket);
-                               switch (socket->getDataType()) {
-                                       case COM_DT_VALUE:
-                                               printf("Value");
-                                               break;
-                                       case COM_DT_VECTOR:
-                                               printf("Vector");
-                                               break;
-                                       case COM_DT_COLOR:
-                                               printf("Color");
-                                               break;
-                               }
-                       }
-                       printf("}");
-                       printf("|");
-               }
-               if (operation->isViewerOperation()) {
-                       ViewerOperation *viewer = (ViewerOperation *)operation;
-                       if (viewer->isActiveViewerOutput()) {
-                               printf("Active viewer");
-                       }
-                       else {
-                               printf("Viewer");
-                       }
-               }
-               else if (operation->isOutputOperation(system->getContext().isRendering())) {
-                       printf("Output");
-               }
-               else if (operation->isSetOperation()) {
-                       printf("Set");
-               }
-               else if (operation->isReadBufferOperation()) {
-                       printf("ReadBuffer");
-               }
-               else if (operation->isWriteBufferOperation()) {
-                       printf("WriteBuffer");
-               }
-               else {
-                       printf("O_%p", operation);
-               }
-               printf(" (%d,%d)", operation->getWidth(), operation->getHeight());
-               tot2 = operation->getNumberOfOutputSockets();
-               if (tot2 != 0) {
-                       printf("|");
-                       printf("{");
-                       for (int j = 0; j < tot2; j++) {
-                               OutputSocket *socket = operation->getOutputSocket(j);
-                               if (j != 0) {
-                                       printf("|");
-                               }
-                               printf("<OUT_%p>", socket);
-                               switch (socket->getDataType()) {
-                                       case COM_DT_VALUE:
-                                               printf("Value");
-                                               break;
-                                       case COM_DT_VECTOR:
-                                               printf("Vector");
-                                               break;
-                                       case COM_DT_COLOR:
-                                               printf("Color");
-                                               break;
-                               }
-                       }
-                       printf("}");
-               }
-               printf("}\"]");
-               printf("\r\n");
-       }
-       tot = system->getExecutionGroups().size();
-       for (int i = 0; i < tot; i++) {
-               group = system->getExecutionGroups()[i];
-               printf("// GROUP: %d\r\n", i);
-               printf("subgraph {\r\n");
-               printf("//  OUTPUTOPERATION: %p\r\n", group->getOutputNodeOperation());
-               printf(" O_%p\r\n", group->getOutputNodeOperation());
-               printf("}\r\n");
-       }
-       tot = system->getOperations().size();
-       for (int i = 0; i < tot; i++) {
-               operation = system->getOperations()[i];
-               if (operation->isReadBufferOperation()) {
-                       ReadBufferOperation *read = (ReadBufferOperation *)operation;
-                       WriteBufferOperation *write = read->getMemoryProxy()->getWriteBufferOperation();
-                       printf("\t\"O_%p\" -> \"O_%p\" [style=dotted]\r\n", write, read);
-               }
-       }
-       tot = system->getConnections().size();
-       for (int i = 0; i < tot; i++) {
-               connection = system->getConnections()[i];
-               printf("// CONNECTION: %p.%p -> %p.%p\r\n", connection->getFromNode(), connection->getFromSocket(), connection->getToNode(), connection->getToSocket());
-               printf("\t\"O_%p\":\"OUT_%p\" -> \"O_%p\":\"IN_%p\"", connection->getFromNode(), connection->getFromSocket(), connection->getToNode(), connection->getToSocket());
-               if (!connection->isValid()) {
-                       printf(" [color=red]");
-               }
-               else {
-                       switch (connection->getFromSocket()->getDataType()) {
-                               case COM_DT_VALUE:
-                                       printf(" [color=grey]");
-                                       break;
-                               case COM_DT_VECTOR:
-                                       printf(" [color=blue]");
-                                       break;
-                               case COM_DT_COLOR:
-                                       printf(" [color=orange]");
-                                       break;
-                       }
-               }
-               printf("\r\n");
-       }
-       printf("}\r\n");
-       printf("-- END COMPOSITOR DUMP --\r\n");
-}
index e05796b9127fdb040e462ac72f8f401db617efd6..002423c195cb591dc5369833ecebd17eb86b240f 100644 (file)
@@ -118,12 +118,6 @@ public:
         */
        static SocketConnection *addLink(vector<SocketConnection *>& links, OutputSocket *fromSocket, InputSocket *toSocket);
 
-       /**
-        * @brief dumps the content of the execution system to standard out
-        * @param system the execution system to dump
-        */
-       static void debugDump(ExecutionSystem *system);
-
 #ifdef WITH_CXX_GUARDEDALLOC
        MEM_CXX_CLASS_ALLOC_FUNCS("COM:ExecutionSystemHelper")
 #endif
index 41b6ab70bf9ec44abc639ba2e4c3bdea9d3905fb..e2072575509e9085996796fd71d93ccc55e03ab0 100644 (file)
@@ -153,9 +153,9 @@ public:
         */
        InputSocket *getInputSocket(const unsigned int index);
        
-       
        virtual bool isStatic() const { return false; }
        void getStaticValues(float *result) const { }
+
 protected:
        NodeBase();
        
index 114a00b9e8d9bff0cf099c8f50d11435547abcfd..160e493073e0f0f2fcc2c4c55652a123a4dd4516 100644 (file)
@@ -199,7 +199,8 @@ public:
         * Mostly Filter types (Blurs, Convolution, Defocus etc) need this to be set to true.
         */
        const bool isComplex() const { return this->m_complex; }
-       virtual const bool isSetOperation() const { return false; }
+
+       virtual bool isSetOperation() const { return false; }
 
        /**
         * @brief is this operation of type ReadBufferOperation
index 7895c34620b0ad4ea017173ca4276b801f833542..8377decdd7bcd621d1adbd1dcbd408aba1e09884 100644 (file)
@@ -58,7 +58,7 @@ public:
        void executePixel(float output[4], float x, float y, PixelSampler sampler);
 
        void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
-       const bool isSetOperation() const { return true; }
+       bool isSetOperation() const { return true; }
 
 };
 #endif
index 3ddc667bc7ed25bd1b964410a31658e4ffb58b65..b88b85d66f2e1d40c93ec2ac67775a1ebcf4d2b5 100644 (file)
@@ -49,6 +49,6 @@ public:
        void executePixel(float output[4], float x, float y, PixelSampler sampler);
        void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
        
-       const bool isSetOperation() const { return true; }
+       bool isSetOperation() const { return true; }
 };
 #endif
index e9d6a163e9f0adce44869144ee81fdcf386a4a7c..d15da58e58e9de07d8e245776a957fe24eaa2c5d 100644 (file)
@@ -57,7 +57,7 @@ public:
        void executePixel(float output[4], float x, float y, PixelSampler sampler);
 
        void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
-       const bool isSetOperation() const { return true; }
+       bool isSetOperation() const { return true; }
 
        void setVector(float vector[3]) {
                setX(vector[0]);
index b5499ab76b71d71084586e0e5ec83727404b40cc..7a4ce9f92130f84400bed23c3cff9f91b45bbdca 100644 (file)
@@ -72,7 +72,7 @@ public:
 
        void executePixel(float output[4], float x, float y, PixelSampler sampler);
 
-       const bool isSetOperation() const { return true; }
+       bool isSetOperation() const { return true; }
 };
 
 #endif