2013-09-13 13:36:47 +00:00
|
|
|
/*
|
|
|
|
|
* 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.
|
2019-02-18 07:21:50 +11:00
|
|
|
*
|
|
|
|
|
* Copyright 2013, Blender Foundation.
|
2013-09-13 13:36:47 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "COM_Debug.h"
|
|
|
|
|
|
2021-03-30 09:18:40 +02:00
|
|
|
#include <map>
|
|
|
|
|
#include <typeinfo>
|
|
|
|
|
#include <vector>
|
2013-09-13 13:36:47 +00:00
|
|
|
|
|
|
|
|
extern "C" {
|
2021-03-30 09:18:40 +02:00
|
|
|
#include "BLI_fileops.h"
|
|
|
|
|
#include "BLI_path_util.h"
|
|
|
|
|
#include "BLI_string.h"
|
|
|
|
|
#include "BLI_sys_types.h"
|
|
|
|
|
|
|
|
|
|
#include "BKE_appdir.h"
|
|
|
|
|
#include "BKE_node.h"
|
|
|
|
|
#include "DNA_node_types.h"
|
2021-07-19 19:55:15 +02:00
|
|
|
#include "IMB_imbuf.h"
|
|
|
|
|
#include "IMB_imbuf_types.h"
|
2013-09-13 13:36:47 +00:00
|
|
|
}
|
|
|
|
|
|
2021-03-30 09:18:40 +02:00
|
|
|
#include "COM_ExecutionSystem.h"
|
|
|
|
|
#include "COM_Node.h"
|
2013-09-13 13:36:47 +00:00
|
|
|
|
2021-03-30 09:18:40 +02:00
|
|
|
#include "COM_ReadBufferOperation.h"
|
2021-07-06 16:37:23 +02:00
|
|
|
#include "COM_SetValueOperation.h"
|
2021-03-30 09:18:40 +02:00
|
|
|
#include "COM_ViewerOperation.h"
|
|
|
|
|
#include "COM_WriteBufferOperation.h"
|
|
|
|
|
|
|
|
|
|
namespace blender::compositor {
|
|
|
|
|
|
2013-09-13 13:36:47 +00:00
|
|
|
int DebugInfo::m_file_index = 0;
|
|
|
|
|
DebugInfo::NodeNameMap DebugInfo::m_node_names;
|
2014-04-15 16:06:12 +02:00
|
|
|
DebugInfo::OpNameMap DebugInfo::m_op_names;
|
2013-09-13 13:36:47 +00:00
|
|
|
std::string DebugInfo::m_current_node_name;
|
2014-04-15 16:06:12 +02:00
|
|
|
std::string DebugInfo::m_current_op_name;
|
2013-09-13 13:36:47 +00:00
|
|
|
DebugInfo::GroupStateMap DebugInfo::m_group_states;
|
|
|
|
|
|
2021-07-19 19:55:15 +02:00
|
|
|
static std::string operation_class_name(const NodeOperation *op)
|
2021-07-06 16:37:23 +02:00
|
|
|
{
|
|
|
|
|
std::string full_name = typeid(*op).name();
|
2021-07-07 12:55:19 +10:00
|
|
|
/* Remove name-spaces. */
|
2021-07-06 16:37:23 +02:00
|
|
|
size_t pos = full_name.find_last_of(':');
|
|
|
|
|
BLI_assert(pos != std::string::npos);
|
|
|
|
|
return full_name.substr(pos + 1);
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-15 16:06:12 +02:00
|
|
|
std::string DebugInfo::node_name(const Node *node)
|
2013-09-13 13:36:47 +00:00
|
|
|
{
|
|
|
|
|
NodeNameMap::const_iterator it = m_node_names.find(node);
|
2019-04-23 11:21:22 +10:00
|
|
|
if (it != m_node_names.end()) {
|
2013-09-13 13:36:47 +00:00
|
|
|
return it->second;
|
2019-04-23 11:21:22 +10:00
|
|
|
}
|
2021-03-12 14:32:24 +01:00
|
|
|
return "";
|
2013-09-13 13:36:47 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-15 16:06:12 +02:00
|
|
|
std::string DebugInfo::operation_name(const NodeOperation *op)
|
|
|
|
|
{
|
|
|
|
|
OpNameMap::const_iterator it = m_op_names.find(op);
|
2019-04-23 11:21:22 +10:00
|
|
|
if (it != m_op_names.end()) {
|
2014-04-15 16:06:12 +02:00
|
|
|
return it->second;
|
2019-04-23 11:21:22 +10:00
|
|
|
}
|
2021-03-12 14:32:24 +01:00
|
|
|
return "";
|
2014-04-15 16:06:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int DebugInfo::graphviz_operation(const ExecutionSystem *system,
|
2021-03-30 09:18:40 +02:00
|
|
|
NodeOperation *operation,
|
2014-04-15 16:06:12 +02:00
|
|
|
const ExecutionGroup *group,
|
|
|
|
|
char *str,
|
|
|
|
|
int maxlen)
|
2013-09-13 13:36:47 +00:00
|
|
|
{
|
|
|
|
|
int len = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-13 13:36:47 +00:00
|
|
|
std::string fillcolor = "gainsboro";
|
2021-03-30 09:18:40 +02:00
|
|
|
if (operation->get_flags().is_viewer_operation) {
|
2014-04-15 16:06:12 +02:00
|
|
|
const ViewerOperation *viewer = (const ViewerOperation *)operation;
|
2013-09-13 13:36:47 +00:00
|
|
|
if (viewer->isActiveViewerOutput()) {
|
|
|
|
|
fillcolor = "lightskyblue1";
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
fillcolor = "lightskyblue3";
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2013-09-13 13:36:47 +00:00
|
|
|
}
|
|
|
|
|
else if (operation->isOutputOperation(system->getContext().isRendering())) {
|
|
|
|
|
fillcolor = "dodgerblue1";
|
|
|
|
|
}
|
2021-03-30 09:18:40 +02:00
|
|
|
else if (operation->get_flags().is_set_operation) {
|
2013-09-13 13:36:47 +00:00
|
|
|
fillcolor = "khaki1";
|
|
|
|
|
}
|
2021-03-29 16:54:02 +02:00
|
|
|
else if (operation->get_flags().is_read_buffer_operation) {
|
2013-09-13 13:36:47 +00:00
|
|
|
fillcolor = "darkolivegreen3";
|
|
|
|
|
}
|
2021-03-29 16:54:02 +02:00
|
|
|
else if (operation->get_flags().is_write_buffer_operation) {
|
2013-09-13 13:36:47 +00:00
|
|
|
fillcolor = "darkorange";
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-18 23:08:23 +00:00
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "// OPERATION: %p\r\n", operation);
|
2019-04-23 11:21:22 +10:00
|
|
|
if (group) {
|
2013-09-18 23:08:23 +00:00
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "\"O_%p_%p\"", operation, group);
|
2019-04-23 11:21:22 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2013-09-18 23:08:23 +00:00
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "\"O_%p\"", operation);
|
2019-04-23 11:21:22 +10:00
|
|
|
}
|
2013-09-18 23:08:23 +00:00
|
|
|
len += snprintf(str + len,
|
|
|
|
|
maxlen > len ? maxlen - len : 0,
|
|
|
|
|
" [fillcolor=%s,style=filled,shape=record,label=\"{",
|
|
|
|
|
fillcolor.c_str());
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-13 13:36:47 +00:00
|
|
|
int totinputs = operation->getNumberOfInputSockets();
|
|
|
|
|
if (totinputs != 0) {
|
2013-09-18 23:08:23 +00:00
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "{");
|
2013-09-13 13:36:47 +00:00
|
|
|
for (int k = 0; k < totinputs; k++) {
|
2014-04-15 16:06:12 +02:00
|
|
|
NodeOperationInput *socket = operation->getInputSocket(k);
|
2013-09-13 13:36:47 +00:00
|
|
|
if (k != 0) {
|
2013-09-18 23:08:23 +00:00
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "|");
|
2013-09-13 13:36:47 +00:00
|
|
|
}
|
2013-09-18 23:08:23 +00:00
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "<IN_%p>", socket);
|
2013-09-13 13:36:47 +00:00
|
|
|
switch (socket->getDataType()) {
|
2021-03-19 14:26:24 +01:00
|
|
|
case DataType::Value:
|
2013-09-18 23:08:23 +00:00
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Value");
|
2013-09-13 13:36:47 +00:00
|
|
|
break;
|
2021-03-19 14:26:24 +01:00
|
|
|
case DataType::Vector:
|
2013-09-18 23:08:23 +00:00
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Vector");
|
2013-09-13 13:36:47 +00:00
|
|
|
break;
|
2021-03-19 14:26:24 +01:00
|
|
|
case DataType::Color:
|
2013-09-18 23:08:23 +00:00
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Color");
|
2013-09-13 13:36:47 +00:00
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2013-09-13 13:36:47 +00:00
|
|
|
}
|
2013-09-18 23:08:23 +00:00
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "}");
|
|
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "|");
|
2013-09-13 13:36:47 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-07-06 16:37:23 +02:00
|
|
|
if (COM_GRAPHVIZ_SHOW_NODE_NAME) {
|
|
|
|
|
std::string op_node_name = operation->get_name();
|
|
|
|
|
if (!op_node_name.empty()) {
|
|
|
|
|
len += snprintf(
|
|
|
|
|
str + len, maxlen > len ? maxlen - len : 0, "%s\\n", (op_node_name + " Node").c_str());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-15 16:06:12 +02:00
|
|
|
len += snprintf(str + len,
|
|
|
|
|
maxlen > len ? maxlen - len : 0,
|
2021-07-06 16:37:23 +02:00
|
|
|
"%s\\n",
|
|
|
|
|
operation_class_name(operation).c_str());
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-10-02 15:18:10 +05:00
|
|
|
len += snprintf(str + len,
|
|
|
|
|
maxlen > len ? maxlen - len : 0,
|
2021-07-06 16:37:23 +02:00
|
|
|
"#%d (%u,%u)",
|
|
|
|
|
operation->get_id(),
|
2017-10-02 15:18:10 +05:00
|
|
|
operation->getWidth(),
|
|
|
|
|
operation->getHeight());
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-13 13:36:47 +00:00
|
|
|
int totoutputs = operation->getNumberOfOutputSockets();
|
|
|
|
|
if (totoutputs != 0) {
|
2013-09-18 23:08:23 +00:00
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "|");
|
|
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "{");
|
2013-09-13 13:36:47 +00:00
|
|
|
for (int k = 0; k < totoutputs; k++) {
|
2014-04-15 16:06:12 +02:00
|
|
|
NodeOperationOutput *socket = operation->getOutputSocket(k);
|
2013-09-13 13:36:47 +00:00
|
|
|
if (k != 0) {
|
2013-09-18 23:08:23 +00:00
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "|");
|
2013-09-13 13:36:47 +00:00
|
|
|
}
|
2013-09-18 23:08:23 +00:00
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "<OUT_%p>", socket);
|
2013-09-13 13:36:47 +00:00
|
|
|
switch (socket->getDataType()) {
|
2021-08-10 15:24:28 +02:00
|
|
|
case DataType::Value: {
|
|
|
|
|
ConstantOperation *constant = operation->get_flags().is_constant_operation ?
|
|
|
|
|
static_cast<ConstantOperation *>(operation) :
|
|
|
|
|
nullptr;
|
|
|
|
|
if (constant && constant->can_get_constant_elem()) {
|
|
|
|
|
const float value = *constant->get_constant_elem();
|
2021-07-06 16:37:23 +02:00
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Value\\n%12.4g", value);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Value");
|
|
|
|
|
}
|
2013-09-13 13:36:47 +00:00
|
|
|
break;
|
2021-08-10 15:24:28 +02:00
|
|
|
}
|
|
|
|
|
case DataType::Vector: {
|
2013-09-18 23:08:23 +00:00
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Vector");
|
2013-09-13 13:36:47 +00:00
|
|
|
break;
|
2021-08-10 15:24:28 +02:00
|
|
|
}
|
|
|
|
|
case DataType::Color: {
|
2013-09-18 23:08:23 +00:00
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Color");
|
2013-09-13 13:36:47 +00:00
|
|
|
break;
|
2021-08-10 15:24:28 +02:00
|
|
|
}
|
2013-09-13 13:36:47 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2013-09-18 23:08:23 +00:00
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "}");
|
2013-09-13 13:36:47 +00:00
|
|
|
}
|
2013-09-18 23:08:23 +00:00
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "}\"]");
|
|
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "\r\n");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-13 13:36:47 +00:00
|
|
|
return len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int DebugInfo::graphviz_legend_color(const char *name, const char *color, char *str, int maxlen)
|
|
|
|
|
{
|
|
|
|
|
int len = 0;
|
2013-09-18 23:08:23 +00:00
|
|
|
len += snprintf(str + len,
|
|
|
|
|
maxlen > len ? maxlen - len : 0,
|
|
|
|
|
"<TR><TD>%s</TD><TD BGCOLOR=\"%s\"></TD></TR>\r\n",
|
|
|
|
|
name,
|
|
|
|
|
color);
|
2013-09-13 13:36:47 +00:00
|
|
|
return len;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-27 16:47:11 +05:00
|
|
|
int DebugInfo::graphviz_legend_line(
|
|
|
|
|
const char * /*name*/, const char * /*color*/, const char * /*style*/, char *str, int maxlen)
|
2013-09-13 13:36:47 +00:00
|
|
|
{
|
|
|
|
|
/* XXX TODO */
|
|
|
|
|
int len = 0;
|
2013-09-18 23:08:23 +00:00
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "\r\n");
|
2013-09-13 13:36:47 +00:00
|
|
|
return len;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-27 16:47:11 +05:00
|
|
|
int DebugInfo::graphviz_legend_group(
|
|
|
|
|
const char *name, const char *color, const char * /*style*/, char *str, int maxlen)
|
2013-09-13 13:36:47 +00:00
|
|
|
{
|
|
|
|
|
int len = 0;
|
2013-09-18 23:08:23 +00:00
|
|
|
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);
|
2013-09-13 13:36:47 +00:00
|
|
|
return len;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-01 10:25:38 +02:00
|
|
|
int DebugInfo::graphviz_legend(char *str, int maxlen, const bool has_execution_groups)
|
2013-09-13 13:36:47 +00:00
|
|
|
{
|
|
|
|
|
int len = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-18 23:08:23 +00:00
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "{\r\n");
|
2021-06-01 10:25:38 +02:00
|
|
|
if (has_execution_groups) {
|
|
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "rank = sink;\r\n");
|
|
|
|
|
}
|
2013-09-18 23:08:23 +00:00
|
|
|
len += snprintf(
|
|
|
|
|
str + len, maxlen > len ? maxlen - len : 0, "Legend [shape=none, margin=0, label=<\r\n");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-18 23:08:23 +00:00
|
|
|
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");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-04-15 16:06:12 +02:00
|
|
|
len += graphviz_legend_color(
|
|
|
|
|
"NodeOperation", "gainsboro", str + len, maxlen > len ? maxlen - len : 0);
|
2013-09-18 23:08:23 +00:00
|
|
|
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);
|
2021-06-01 10:25:38 +02:00
|
|
|
if (has_execution_groups) {
|
|
|
|
|
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);
|
|
|
|
|
}
|
2013-09-18 23:08:23 +00:00
|
|
|
len += graphviz_legend_color(
|
|
|
|
|
"Input Value", "khaki1", str + len, maxlen > len ? maxlen - len : 0);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-06-01 10:25:38 +02:00
|
|
|
if (has_execution_groups) {
|
|
|
|
|
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);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-18 23:08:23 +00:00
|
|
|
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");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-13 13:36:47 +00:00
|
|
|
return len;
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-15 16:06:12 +02:00
|
|
|
bool DebugInfo::graphviz_system(const ExecutionSystem *system, char *str, int maxlen)
|
2013-09-13 13:36:47 +00:00
|
|
|
{
|
|
|
|
|
char strbuf[64];
|
|
|
|
|
int len = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-18 23:08:23 +00:00
|
|
|
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");
|
2014-04-15 16:06:12 +02:00
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "rankdir=LR\r\n");
|
2013-09-18 23:08:23 +00:00
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "splines=false\r\n");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-13 13:36:47 +00:00
|
|
|
std::map<NodeOperation *, std::vector<std::string>> op_groups;
|
2021-03-16 13:45:26 +01:00
|
|
|
int index = 0;
|
|
|
|
|
for (const ExecutionGroup *group : system->m_groups) {
|
|
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "// GROUP: %d\r\n", index);
|
|
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "subgraph cluster_%d{\r\n", index);
|
2013-09-13 13:36:47 +00:00
|
|
|
/* used as a check for executing group */
|
|
|
|
|
if (m_group_states[group] == EG_WAIT) {
|
2013-09-18 23:08:23 +00:00
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "style=dashed\r\n");
|
2013-09-13 13:36:47 +00:00
|
|
|
}
|
|
|
|
|
else if (m_group_states[group] == EG_RUNNING) {
|
2013-09-18 23:08:23 +00:00
|
|
|
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");
|
2013-09-13 13:36:47 +00:00
|
|
|
}
|
|
|
|
|
else if (m_group_states[group] == EG_FINISHED) {
|
2013-09-18 23:08:23 +00:00
|
|
|
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");
|
2013-09-13 13:36:47 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-03-12 14:32:24 +01:00
|
|
|
for (NodeOperation *operation : group->m_operations) {
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-13 13:36:47 +00:00
|
|
|
sprintf(strbuf, "_%p", group);
|
|
|
|
|
op_groups[operation].push_back(std::string(strbuf));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-18 23:08:23 +00:00
|
|
|
len += graphviz_operation(
|
|
|
|
|
system, operation, group, str + len, maxlen > len ? maxlen - len : 0);
|
2013-09-13 13:36:47 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-18 23:08:23 +00:00
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "}\r\n");
|
2021-03-16 13:45:26 +01:00
|
|
|
index++;
|
2013-09-13 13:36:47 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-13 13:36:47 +00:00
|
|
|
/* operations not included in any group */
|
2021-03-16 13:45:26 +01:00
|
|
|
for (NodeOperation *operation : system->m_operations) {
|
2019-04-23 11:21:22 +10:00
|
|
|
if (op_groups.find(operation) != op_groups.end()) {
|
2013-09-13 13:36:47 +00:00
|
|
|
continue;
|
2019-04-23 11:21:22 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-13 13:36:47 +00:00
|
|
|
op_groups[operation].push_back(std::string(""));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-03-12 14:32:24 +01:00
|
|
|
len += graphviz_operation(
|
|
|
|
|
system, operation, nullptr, str + len, maxlen > len ? maxlen - len : 0);
|
2013-09-13 13:36:47 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-03-16 13:45:26 +01:00
|
|
|
for (NodeOperation *operation : system->m_operations) {
|
2021-03-29 16:54:02 +02:00
|
|
|
if (operation->get_flags().is_read_buffer_operation) {
|
2013-09-13 13:36:47 +00:00
|
|
|
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];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int k = 0; k < write_groups.size(); k++) {
|
|
|
|
|
for (int l = 0; l < read_groups.size(); l++) {
|
2013-09-18 23:08:23 +00:00
|
|
|
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());
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
2013-09-13 13:36:47 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-03-16 13:45:26 +01:00
|
|
|
for (NodeOperation *op : system->m_operations) {
|
2021-03-30 09:18:40 +02:00
|
|
|
for (NodeOperationInput &to : op->m_inputs) {
|
|
|
|
|
NodeOperationOutput *from = to.getLink();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-23 11:21:22 +10:00
|
|
|
if (!from) {
|
2014-04-15 16:06:12 +02:00
|
|
|
continue;
|
2019-04-23 11:21:22 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-04-15 16:06:12 +02:00
|
|
|
std::string color;
|
|
|
|
|
switch (from->getDataType()) {
|
2021-03-19 14:26:24 +01:00
|
|
|
case DataType::Value:
|
2015-03-19 14:14:48 +11:00
|
|
|
color = "gray";
|
2013-09-13 13:36:47 +00:00
|
|
|
break;
|
2021-03-19 14:26:24 +01:00
|
|
|
case DataType::Vector:
|
2013-09-13 13:36:47 +00:00
|
|
|
color = "blue";
|
|
|
|
|
break;
|
2021-03-19 14:26:24 +01:00
|
|
|
case DataType::Color:
|
2013-09-13 13:36:47 +00:00
|
|
|
color = "orange";
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-03-30 09:18:40 +02:00
|
|
|
NodeOperation *to_op = &to.getOperation();
|
2014-04-15 16:06:12 +02:00
|
|
|
NodeOperation *from_op = &from->getOperation();
|
2013-09-13 13:36:47 +00:00
|
|
|
std::vector<std::string> &from_groups = op_groups[from_op];
|
|
|
|
|
std::vector<std::string> &to_groups = op_groups[to_op];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-04-15 16:06:12 +02:00
|
|
|
len += snprintf(str + len,
|
|
|
|
|
maxlen > len ? maxlen - len : 0,
|
|
|
|
|
"// CONNECTION: %p.%p -> %p.%p\r\n",
|
|
|
|
|
from_op,
|
|
|
|
|
from,
|
|
|
|
|
to_op,
|
2021-03-30 09:18:40 +02:00
|
|
|
&to);
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int k = 0; k < from_groups.size(); k++) {
|
|
|
|
|
for (int l = 0; l < to_groups.size(); l++) {
|
2014-04-15 16:06:12 +02:00
|
|
|
len += snprintf(str + len,
|
|
|
|
|
maxlen > len ? maxlen - len : 0,
|
2021-03-12 14:32:24 +01:00
|
|
|
R"("O_%p%s":"OUT_%p":e -> "O_%p%s":"IN_%p":w)",
|
2014-04-15 16:06:12 +02:00
|
|
|
from_op,
|
|
|
|
|
from_groups[k].c_str(),
|
|
|
|
|
from,
|
|
|
|
|
to_op,
|
|
|
|
|
to_groups[l].c_str(),
|
2021-03-30 09:18:40 +02:00
|
|
|
&to);
|
2013-09-18 23:08:23 +00:00
|
|
|
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");
|
2013-09-13 13:36:47 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2021-06-01 10:25:38 +02:00
|
|
|
const bool has_execution_groups = system->getContext().get_execution_model() ==
|
2021-09-04 16:59:02 +02:00
|
|
|
eExecutionModel::Tiled &&
|
|
|
|
|
system->m_groups.size() > 0;
|
2021-06-01 10:25:38 +02:00
|
|
|
len += graphviz_legend(str + len, maxlen > len ? maxlen - len : 0, has_execution_groups);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-18 23:08:23 +00:00
|
|
|
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "}\r\n");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-13 13:36:47 +00:00
|
|
|
return (len < maxlen);
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-06 16:16:08 +02:00
|
|
|
void DebugInfo::graphviz(const ExecutionSystem *system, StringRefNull name)
|
2013-09-13 13:36:47 +00:00
|
|
|
{
|
2021-04-28 07:56:11 +02:00
|
|
|
if (!COM_EXPORT_GRAPHVIZ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2013-09-13 13:36:47 +00:00
|
|
|
char str[1000000];
|
2013-09-18 23:08:23 +00:00
|
|
|
if (graphviz_system(system, str, sizeof(str) - 1)) {
|
2013-09-13 13:36:47 +00:00
|
|
|
char basename[FILE_MAX];
|
|
|
|
|
char filename[FILE_MAX];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-07-06 16:16:08 +02:00
|
|
|
if (name.is_empty()) {
|
|
|
|
|
BLI_snprintf(basename, sizeof(basename), "compositor_%d.dot", m_file_index);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
BLI_strncpy(basename, (name + ".dot").c_str(), sizeof(basename));
|
|
|
|
|
}
|
2014-11-23 15:54:29 +01:00
|
|
|
BLI_join_dirfile(filename, sizeof(filename), BKE_tempdir_session(), basename);
|
2019-09-08 00:12:26 +10:00
|
|
|
m_file_index++;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-04-09 15:37:09 +02:00
|
|
|
std::cout << "Writing compositor debug to: " << filename << "\n";
|
|
|
|
|
|
2013-09-13 13:36:47 +00:00
|
|
|
FILE *fp = BLI_fopen(filename, "wb");
|
|
|
|
|
fputs(str, fp);
|
|
|
|
|
fclose(fp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-19 19:55:15 +02:00
|
|
|
static std::string get_operations_export_dir()
|
|
|
|
|
{
|
|
|
|
|
return std::string(BKE_tempdir_session()) + "COM_operations" + SEP_STR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DebugInfo::export_operation(const NodeOperation *op, MemoryBuffer *render)
|
|
|
|
|
{
|
|
|
|
|
ImBuf *ibuf = IMB_allocFromBuffer(nullptr,
|
|
|
|
|
render->getBuffer(),
|
|
|
|
|
render->getWidth(),
|
|
|
|
|
render->getHeight(),
|
|
|
|
|
render->get_num_channels());
|
|
|
|
|
|
|
|
|
|
const std::string file_name = operation_class_name(op) + "_" + std::to_string(op->get_id()) +
|
|
|
|
|
".png";
|
|
|
|
|
const std::string path = get_operations_export_dir() + file_name;
|
|
|
|
|
BLI_make_existing_file(path.c_str());
|
|
|
|
|
IMB_saveiff(ibuf, path.c_str(), ibuf->flags);
|
|
|
|
|
IMB_freeImBuf(ibuf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DebugInfo::delete_operation_exports()
|
|
|
|
|
{
|
|
|
|
|
const std::string dir = get_operations_export_dir();
|
|
|
|
|
if (BLI_exists(dir.c_str())) {
|
|
|
|
|
struct direntry *file_list;
|
|
|
|
|
int num_files = BLI_filelist_dir_contents(dir.c_str(), &file_list);
|
|
|
|
|
for (int i = 0; i < num_files; i++) {
|
|
|
|
|
direntry *file = &file_list[i];
|
|
|
|
|
const eFileAttributes file_attrs = BLI_file_attributes(file->path);
|
|
|
|
|
if (file_attrs & FILE_ATTR_ANY_LINK) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (BLI_is_file(file->path) && BLI_path_extension_check(file->path, ".png")) {
|
|
|
|
|
BLI_delete(file->path, false, false);
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-07-26 19:10:16 +02:00
|
|
|
BLI_filelist_free(file_list, num_files);
|
2021-07-19 19:55:15 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-23 17:12:27 +01:00
|
|
|
} // namespace blender::compositor
|