Merge branch 'master' into blender2.8
This commit is contained in:
@@ -117,61 +117,58 @@ ccl_device void kernel_filter_detect_outliers(int x, int y,
|
||||
{
|
||||
int buffer_w = align_up(rect.z - rect.x, 4);
|
||||
|
||||
int n = 0;
|
||||
float values[25];
|
||||
for(int y1 = max(y-2, rect.y); y1 < min(y+3, rect.w); y1++) {
|
||||
for(int x1 = max(x-2, rect.x); x1 < min(x+3, rect.z); x1++) {
|
||||
int idx = (y1-rect.y)*buffer_w + (x1-rect.x);
|
||||
float3 color = make_float3(image[idx], image[idx+pass_stride], image[idx+2*pass_stride]);
|
||||
color = max(color, make_float3(0.0f, 0.0f, 0.0f));
|
||||
float L = average(color);
|
||||
|
||||
/* Find the position of L. */
|
||||
int i;
|
||||
for(i = 0; i < n; i++) {
|
||||
if(values[i] > L) break;
|
||||
}
|
||||
/* Make space for L by shifting all following values to the right. */
|
||||
for(int j = n; j > i; j--) {
|
||||
values[j] = values[j-1];
|
||||
}
|
||||
/* Insert L. */
|
||||
values[i] = L;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
int idx = (y-rect.y)*buffer_w + (x-rect.x);
|
||||
float3 color = make_float3(image[idx], image[idx+pass_stride], image[idx+2*pass_stride]);
|
||||
color = max(color, make_float3(0.0f, 0.0f, 0.0f));
|
||||
float L = average(color);
|
||||
|
||||
float fac = 1.0f;
|
||||
if(color.x < 0.0f || color.y < 0.0f || color.z < 0.0f) {
|
||||
depth[idx] = -depth[idx];
|
||||
fac = 0.0f;
|
||||
}
|
||||
else {
|
||||
float L = average(color);
|
||||
int n = 0;
|
||||
float values[25];
|
||||
for(int y1 = max(y-2, rect.y); y1 < min(y+3, rect.w); y1++) {
|
||||
for(int x1 = max(x-2, rect.x); x1 < min(x+3, rect.z); x1++) {
|
||||
int idx = (y1-rect.y)*buffer_w + (x1-rect.x);
|
||||
float L = average(make_float3(image[idx], image[idx+pass_stride], image[idx+2*pass_stride]));
|
||||
|
||||
/* Find the position of L. */
|
||||
int i;
|
||||
for(i = 0; i < n; i++) {
|
||||
if(values[i] > L) break;
|
||||
}
|
||||
/* Make space for L by shifting all following values to the right. */
|
||||
for(int j = n; j > i; j--) {
|
||||
values[j] = values[j-1];
|
||||
}
|
||||
/* Insert L. */
|
||||
values[i] = L;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
float ref = 2.0f*values[(int)(n*0.75f)];
|
||||
if(L > ref) {
|
||||
/* The pixel appears to be an outlier.
|
||||
* However, it may just be a legitimate highlight. Therefore, it is checked how likely it is that the pixel
|
||||
* should actually be at the reference value:
|
||||
* If the reference is within the 3-sigma interval, the pixel is assumed to be a statistical outlier.
|
||||
* Otherwise, it is very unlikely that the pixel should be darker, which indicates a legitimate highlight.
|
||||
*/
|
||||
float stddev = sqrtf(average(make_float3(variance[idx], variance[idx+pass_stride], variance[idx+2*pass_stride])));
|
||||
if(L - 3*stddev < ref) {
|
||||
/* The pixel is an outlier, so negate the depth value to mark it as one.
|
||||
* Also, scale its brightness down to the outlier threshold to avoid trouble with the NLM weights. */
|
||||
depth[idx] = -depth[idx];
|
||||
fac = ref/L;
|
||||
variance[idx ] *= fac*fac;
|
||||
variance[idx + pass_stride] *= fac*fac;
|
||||
variance[idx+2*pass_stride] *= fac*fac;
|
||||
}
|
||||
float ref = 2.0f*values[(int)(n*0.75f)];
|
||||
if(L > ref) {
|
||||
/* The pixel appears to be an outlier.
|
||||
* However, it may just be a legitimate highlight. Therefore, it is checked how likely it is that the pixel
|
||||
* should actually be at the reference value:
|
||||
* If the reference is within the 3-sigma interval, the pixel is assumed to be a statistical outlier.
|
||||
* Otherwise, it is very unlikely that the pixel should be darker, which indicates a legitimate highlight.
|
||||
*/
|
||||
float stddev = sqrtf(average(make_float3(variance[idx], variance[idx+pass_stride], variance[idx+2*pass_stride])));
|
||||
if(L - 3*stddev < ref) {
|
||||
/* The pixel is an outlier, so negate the depth value to mark it as one.
|
||||
* Also, scale its brightness down to the outlier threshold to avoid trouble with the NLM weights. */
|
||||
depth[idx] = -depth[idx];
|
||||
float fac = ref/L;
|
||||
color *= fac;
|
||||
variance[idx ] *= fac*fac;
|
||||
variance[idx + pass_stride] *= fac*fac;
|
||||
variance[idx+2*pass_stride] *= fac*fac;
|
||||
}
|
||||
}
|
||||
out[idx ] = fac*image[idx];
|
||||
out[idx + pass_stride] = fac*image[idx + pass_stride];
|
||||
out[idx+2*pass_stride] = fac*image[idx+2*pass_stride];
|
||||
out[idx ] = color.x;
|
||||
out[idx + pass_stride] = color.y;
|
||||
out[idx+2*pass_stride] = color.z;
|
||||
}
|
||||
|
||||
/* Combine A/B buffers.
|
||||
|
||||
@@ -53,10 +53,12 @@ set(SRC
|
||||
intern/builder/deg_builder_relations_rig.cc
|
||||
intern/builder/deg_builder_relations_view_layer.cc
|
||||
intern/builder/deg_builder_transitive.cc
|
||||
intern/debug/deg_debug_graphviz.cc
|
||||
intern/debug/deg_debug_relations_graphviz.cc
|
||||
intern/debug/deg_debug_stats_gnuplot.cc
|
||||
intern/eval/deg_eval.cc
|
||||
intern/eval/deg_eval_copy_on_write.cc
|
||||
intern/eval/deg_eval_flush.cc
|
||||
intern/eval/deg_eval_stats.cc
|
||||
intern/nodes/deg_node.cc
|
||||
intern/nodes/deg_node_component.cc
|
||||
intern/nodes/deg_node_id.cc
|
||||
@@ -87,6 +89,7 @@ set(SRC
|
||||
intern/eval/deg_eval.h
|
||||
intern/eval/deg_eval_copy_on_write.h
|
||||
intern/eval/deg_eval_flush.h
|
||||
intern/eval/deg_eval_stats.h
|
||||
intern/nodes/deg_node.h
|
||||
intern/nodes/deg_node_component.h
|
||||
intern/nodes/deg_node_id.h
|
||||
|
||||
@@ -53,7 +53,14 @@ void DEG_stats_simple(const struct Depsgraph *graph,
|
||||
/* ************************************************ */
|
||||
/* Diagram-Based Graph Debugging */
|
||||
|
||||
void DEG_debug_graphviz(const struct Depsgraph *graph, FILE *stream, const char *label);
|
||||
void DEG_debug_relations_graphviz(const struct Depsgraph *graph,
|
||||
FILE *stream,
|
||||
const char *label);
|
||||
|
||||
void DEG_debug_stats_gnuplot(const struct Depsgraph *graph,
|
||||
FILE *stream,
|
||||
const char *label,
|
||||
const char *output_filename);
|
||||
|
||||
/* ************************************************ */
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/depsgraph/intern/debug/deg_debug_graphviz.cc
|
||||
/** \file blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc
|
||||
* \ingroup depsgraph
|
||||
*
|
||||
* Implementation of tools for debugging the depsgraph
|
||||
@@ -517,7 +517,9 @@ static void deg_debug_graphviz_graph_relations(const DebugContext &ctx,
|
||||
|
||||
} // namespace DEG
|
||||
|
||||
void DEG_debug_graphviz(const Depsgraph *graph, FILE *f, const char *label)
|
||||
void DEG_debug_relations_graphviz(const Depsgraph *graph,
|
||||
FILE *f,
|
||||
const char *label)
|
||||
{
|
||||
if (!graph) {
|
||||
return;
|
||||
126
source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc
Normal file
126
source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2017 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Original Author: Sergey Sharybin
|
||||
* Contributor(s): None Yet
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc
|
||||
* \ingroup depsgraph
|
||||
*/
|
||||
|
||||
#include "DEG_depsgraph_debug.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "BLI_compiler_attrs.h"
|
||||
|
||||
#include "intern/depsgraph.h"
|
||||
#include "intern/nodes/deg_node_id.h"
|
||||
|
||||
#include "util/deg_util_foreach.h"
|
||||
|
||||
extern "C" {
|
||||
#include "DNA_ID.h"
|
||||
} /* extern "C" */
|
||||
|
||||
#define NL "\r\n"
|
||||
|
||||
namespace DEG {
|
||||
namespace {
|
||||
|
||||
struct DebugContext {
|
||||
FILE *file;
|
||||
const Depsgraph *graph;
|
||||
const char *label;
|
||||
const char *output_filename;
|
||||
};
|
||||
|
||||
/* TODO(sergey): De-duplicate with graphviz relation debugger. */
|
||||
static void deg_debug_fprintf(const DebugContext &ctx,
|
||||
const char *fmt,
|
||||
...) ATTR_PRINTF_FORMAT(2, 3);
|
||||
static void deg_debug_fprintf(const DebugContext &ctx, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vfprintf(ctx.file, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void write_stats_data(const DebugContext& ctx)
|
||||
{
|
||||
deg_debug_fprintf(ctx, "$data << EOD" NL);
|
||||
// TODO(sergey): Sort nodes by time.
|
||||
foreach (const IDDepsNode *id_node, ctx.graph->id_nodes) {
|
||||
// TODO(sergey): Figure out a nice way to define which exact time
|
||||
// we want to show.
|
||||
const double time = id_node->stats.current_time;
|
||||
if (time == 0.0) {
|
||||
continue;
|
||||
}
|
||||
deg_debug_fprintf(ctx, "\"%s\",%f" NL,
|
||||
id_node->id_orig->name + 2,
|
||||
time);
|
||||
}
|
||||
deg_debug_fprintf(ctx, "EOD" NL);
|
||||
}
|
||||
|
||||
void deg_debug_stats_gnuplot(const DebugContext& ctx)
|
||||
{
|
||||
// Data itself.
|
||||
write_stats_data(ctx);
|
||||
// Optional label.
|
||||
if (ctx.label && ctx.label[0]) {
|
||||
deg_debug_fprintf(ctx, "set title \"%s\"" NL, ctx.label);
|
||||
}
|
||||
// Rest of the commands.
|
||||
// TODO(sergey): Need to decide on the resolution somehow.
|
||||
deg_debug_fprintf(ctx, "set terminal pngcairo size 1920,1080" NL);
|
||||
deg_debug_fprintf(ctx, "set output \"%s\"" NL, ctx.output_filename);
|
||||
deg_debug_fprintf(ctx, "set grid" NL);
|
||||
deg_debug_fprintf(ctx, "set datafile separator ','" NL);
|
||||
deg_debug_fprintf(ctx, "set style fill solid" NL);
|
||||
deg_debug_fprintf(ctx, "plot \"$data\" using " \
|
||||
"($2*0.5):0:($2*0.5):(0.2):yticlabels(1) "
|
||||
"with boxxyerrorbars t '' lt rgb \"#406090\"" NL);
|
||||
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace DEG
|
||||
|
||||
void DEG_debug_stats_gnuplot(const Depsgraph *depsgraph,
|
||||
FILE *f,
|
||||
const char *label,
|
||||
const char *output_filename)
|
||||
{
|
||||
if (depsgraph == NULL) {
|
||||
return;
|
||||
}
|
||||
DEG::DebugContext ctx;
|
||||
ctx.file = f;
|
||||
ctx.graph = (DEG::Depsgraph *)depsgraph;
|
||||
ctx.label = label;
|
||||
ctx.output_filename = output_filename;
|
||||
DEG::deg_debug_stats_gnuplot(ctx);
|
||||
}
|
||||
@@ -46,6 +46,7 @@
|
||||
#include "atomic_ops.h"
|
||||
|
||||
#include "intern/eval/deg_eval_flush.h"
|
||||
#include "intern/eval/deg_eval_stats.h"
|
||||
#include "intern/nodes/deg_node.h"
|
||||
#include "intern/nodes/deg_node_component.h"
|
||||
#include "intern/nodes/deg_node_id.h"
|
||||
@@ -70,38 +71,28 @@ static void schedule_children(TaskPool *pool,
|
||||
struct DepsgraphEvalState {
|
||||
EvaluationContext *eval_ctx;
|
||||
Depsgraph *graph;
|
||||
bool do_stats;
|
||||
};
|
||||
|
||||
static void deg_task_run_func(TaskPool *pool,
|
||||
void *taskdata,
|
||||
int thread_id)
|
||||
{
|
||||
DepsgraphEvalState *state =
|
||||
reinterpret_cast<DepsgraphEvalState *>(BLI_task_pool_userdata(pool));
|
||||
OperationDepsNode *node = reinterpret_cast<OperationDepsNode *>(taskdata);
|
||||
|
||||
void *userdata_v = BLI_task_pool_userdata(pool);
|
||||
DepsgraphEvalState *state = (DepsgraphEvalState *)userdata_v;
|
||||
OperationDepsNode *node = (OperationDepsNode *)taskdata;
|
||||
/* Sanity checks. */
|
||||
BLI_assert(!node->is_noop() && "NOOP nodes should not actually be scheduled");
|
||||
|
||||
/* Should only be the case for NOOPs, which never get to this point. */
|
||||
BLI_assert(node->evaluate);
|
||||
|
||||
/* Get context. */
|
||||
/* TODO: Who initialises this? "Init" operations aren't able to
|
||||
* initialise it!!!
|
||||
*/
|
||||
/* TODO(sergey): We don't use component contexts at this moment. */
|
||||
/* ComponentDepsNode *comp = node->owner; */
|
||||
BLI_assert(node->owner != NULL);
|
||||
|
||||
/* Since we're not leaving the thread for until the graph branches it is
|
||||
* possible to have NO-OP on the way. for which evaluate() will be NULL.
|
||||
* but that's all fine, we'll just scheduler it's children.
|
||||
*/
|
||||
if (node->evaluate) {
|
||||
/* Perform operation. */
|
||||
/* Perform operation. */
|
||||
if (state->do_stats) {
|
||||
const double start_time = PIL_check_seconds_timer();
|
||||
node->evaluate(state->eval_ctx);
|
||||
node->stats.current_time += PIL_check_seconds_timer() - start_time;
|
||||
}
|
||||
else {
|
||||
node->evaluate(state->eval_ctx);
|
||||
}
|
||||
|
||||
/* Schedule children. */
|
||||
BLI_task_pool_delayed_push_begin(pool, thread_id);
|
||||
schedule_children(pool, state->graph, node, thread_id);
|
||||
BLI_task_pool_delayed_push_end(pool, thread_id);
|
||||
@@ -148,6 +139,19 @@ static void calculate_pending_parents(Depsgraph *graph)
|
||||
do_threads);
|
||||
}
|
||||
|
||||
static void initialize_execution(DepsgraphEvalState *state, Depsgraph *graph)
|
||||
{
|
||||
const bool do_stats = state->do_stats;
|
||||
calculate_pending_parents(graph);
|
||||
/* Clear tags and other things which needs to be clear. */
|
||||
foreach (OperationDepsNode *node, graph->operations) {
|
||||
node->done = 0;
|
||||
if (do_stats) {
|
||||
node->stats.reset_current();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Schedule a node if it needs evaluation.
|
||||
* dec_parents: Decrement pending parents count, true when child nodes are
|
||||
* scheduled after a task has been completed.
|
||||
@@ -221,28 +225,23 @@ static void schedule_children(TaskPool *pool,
|
||||
void deg_evaluate_on_refresh(EvaluationContext *eval_ctx,
|
||||
Depsgraph *graph)
|
||||
{
|
||||
/* Generate base evaluation context, upon which all the others are derived. */
|
||||
// TODO: this needs both main and scene access...
|
||||
|
||||
/* Nothing to update, early out. */
|
||||
if (BLI_gset_size(graph->entry_tags) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set time for the current graph evaluation context. */
|
||||
TimeSourceDepsNode *time_src = graph->find_time_source();
|
||||
eval_ctx->depsgraph = (::Depsgraph *)graph;
|
||||
eval_ctx->view_layer = DEG_get_evaluated_view_layer((::Depsgraph *)graph);
|
||||
eval_ctx->ctime = time_src->cfra;
|
||||
|
||||
/* XXX could use a separate pool for each eval context */
|
||||
/* Set up evaluation context for depsgraph itself. */
|
||||
DepsgraphEvalState state;
|
||||
state.eval_ctx = eval_ctx;
|
||||
state.graph = graph;
|
||||
|
||||
state.do_stats = (G.debug_value != 0);
|
||||
/* Set up task scheduler and pull for threaded evaluation. */
|
||||
TaskScheduler *task_scheduler;
|
||||
bool need_free_scheduler;
|
||||
|
||||
if (G.debug & G_DEBUG_DEPSGRAPH_NO_THREADS) {
|
||||
task_scheduler = BLI_task_scheduler_create(1);
|
||||
need_free_scheduler = true;
|
||||
@@ -251,24 +250,22 @@ void deg_evaluate_on_refresh(EvaluationContext *eval_ctx,
|
||||
task_scheduler = BLI_task_scheduler_get();
|
||||
need_free_scheduler = false;
|
||||
}
|
||||
|
||||
TaskPool *task_pool = BLI_task_pool_create_suspended(task_scheduler, &state);
|
||||
|
||||
calculate_pending_parents(graph);
|
||||
|
||||
/* Clear tags. */
|
||||
foreach (OperationDepsNode *node, graph->operations) {
|
||||
node->done = 0;
|
||||
}
|
||||
|
||||
/* Prepare all nodes for evaluation. */
|
||||
initialize_execution(&state, graph);
|
||||
/* Do actual evaluation now. */
|
||||
schedule_graph(task_pool, graph);
|
||||
|
||||
BLI_task_pool_work_and_wait(task_pool);
|
||||
BLI_task_pool_free(task_pool);
|
||||
|
||||
/* Finalize statistics gathering. This is because we only gather single
|
||||
* operation timing here, without aggregating anything to avoid any extra
|
||||
* synchronization.
|
||||
*/
|
||||
if (state.do_stats) {
|
||||
deg_eval_stats_aggregate(graph);
|
||||
}
|
||||
/* Clear any uncleared tags - just in case. */
|
||||
deg_graph_clear_tags(graph);
|
||||
|
||||
if (need_free_scheduler) {
|
||||
BLI_task_scheduler_free(task_scheduler);
|
||||
}
|
||||
|
||||
70
source/blender/depsgraph/intern/eval/deg_eval_stats.cc
Normal file
70
source/blender/depsgraph/intern/eval/deg_eval_stats.cc
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2017 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Original Author: Sergey Sharybin
|
||||
* Contributor(s): None Yet
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/depsgraph/intern/eval/deg_eval_stats.cc
|
||||
* \ingroup depsgraph
|
||||
*/
|
||||
|
||||
#include "intern/eval/deg_eval_stats.h"
|
||||
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_ghash.h"
|
||||
|
||||
#include "intern/depsgraph.h"
|
||||
|
||||
#include "intern/nodes/deg_node.h"
|
||||
#include "intern/nodes/deg_node_component.h"
|
||||
#include "intern/nodes/deg_node_id.h"
|
||||
#include "intern/nodes/deg_node_operation.h"
|
||||
|
||||
#include "util/deg_util_foreach.h"
|
||||
|
||||
namespace DEG {
|
||||
|
||||
void deg_eval_stats_aggregate(Depsgraph *graph)
|
||||
{
|
||||
/* Reset current evaluation stats for ID and component nodes.
|
||||
* Those are not filled in by the evaluation engine.
|
||||
*/
|
||||
foreach (DepsNode *node, graph->id_nodes) {
|
||||
IDDepsNode *id_node = (IDDepsNode *)node;
|
||||
GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, id_node->components)
|
||||
{
|
||||
comp_node->stats.reset_current();
|
||||
}
|
||||
GHASH_FOREACH_END();
|
||||
id_node->stats.reset_current();
|
||||
}
|
||||
/* Now accumulate operation timings to components and IDs. */
|
||||
foreach (OperationDepsNode *op_node, graph->operations) {
|
||||
ComponentDepsNode *comp_node = op_node->owner;
|
||||
IDDepsNode *id_node = comp_node->owner;
|
||||
id_node->stats.current_time += op_node->stats.current_time;
|
||||
comp_node->stats.current_time += op_node->stats.current_time;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace DEG
|
||||
40
source/blender/depsgraph/intern/eval/deg_eval_stats.h
Normal file
40
source/blender/depsgraph/intern/eval/deg_eval_stats.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2017 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Original Author: Sergey Sharybin
|
||||
* Contributor(s): None Yet
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/depsgraph/intern/eval/deg_eval_stats.h
|
||||
* \ingroup depsgraph
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace DEG {
|
||||
|
||||
struct Depsgraph;
|
||||
|
||||
/* Aggregate operation timings to overall component and ID nodes timing. */
|
||||
void deg_eval_stats_aggregate(Depsgraph *graph);
|
||||
|
||||
} // namespace DEG
|
||||
@@ -46,10 +46,9 @@
|
||||
|
||||
namespace DEG {
|
||||
|
||||
/* *************** */
|
||||
/* Node Management */
|
||||
|
||||
/* Add ------------------------------------------------ */
|
||||
/*******************************************************************************
|
||||
* Type information.
|
||||
*/
|
||||
|
||||
DepsNode::TypeInfo::TypeInfo(eDepsNode_Type type,
|
||||
const char *tname,
|
||||
@@ -60,6 +59,29 @@ DepsNode::TypeInfo::TypeInfo(eDepsNode_Type type,
|
||||
{
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Evaluation statistics.
|
||||
*/
|
||||
|
||||
DepsNode::Stats::Stats()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void DepsNode::Stats::reset()
|
||||
{
|
||||
current_time = 0.0;
|
||||
}
|
||||
|
||||
void DepsNode::Stats::reset_current()
|
||||
{
|
||||
current_time = 0.0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Node itself.
|
||||
*/
|
||||
|
||||
DepsNode::DepsNode()
|
||||
{
|
||||
name = "";
|
||||
@@ -99,8 +121,10 @@ eDepsNode_Class DepsNode::get_class() const {
|
||||
}
|
||||
}
|
||||
|
||||
/* Generic Nodes */
|
||||
|
||||
/*******************************************************************************
|
||||
* Generic nodes definition.
|
||||
*/
|
||||
\
|
||||
DEG_DEPSNODE_DEFINE(TimeSourceDepsNode, DEG_NODE_TYPE_TIMESOURCE, "Time Source");
|
||||
static DepsNodeFactoryImpl<TimeSourceDepsNode> DNTI_TIMESOURCE;
|
||||
|
||||
|
||||
@@ -56,6 +56,19 @@ struct DepsNode {
|
||||
const char *tname;
|
||||
int id_recalc_tag;
|
||||
};
|
||||
struct Stats {
|
||||
Stats();
|
||||
/* Reset all the counters. Including all stats needed for average
|
||||
* evaluation time calculation.
|
||||
*/
|
||||
void reset();
|
||||
/* Reset counters needed for the current graph evaluation, does not
|
||||
* touch averaging accumulators.
|
||||
*/
|
||||
void reset_current();
|
||||
/* Time spend on this node during current graph evaluation. */
|
||||
double current_time;
|
||||
};
|
||||
/* Relationships between nodes
|
||||
* The reason why all depsgraph nodes are descended from this type (apart
|
||||
* from basic serialization benefits - from the typeinfo) is that we can have
|
||||
@@ -67,7 +80,8 @@ struct DepsNode {
|
||||
eDepsNode_Type type; /* Structural type of node. */
|
||||
Relations inlinks; /* Nodes which this one depends on. */
|
||||
Relations outlinks; /* Nodes which depend on this one. */
|
||||
int done; /* Generic tags for traversal algorithms. */
|
||||
int done; /* Generic tags for traversal algorithms. */
|
||||
Stats stats; /* Evaluation statistics. */
|
||||
|
||||
/* Methods. */
|
||||
DepsNode();
|
||||
|
||||
@@ -120,13 +120,26 @@ static int rna_DepsgraphIter_is_instance_get(PointerRNA *ptr)
|
||||
|
||||
/* **************** Depsgraph **************** */
|
||||
|
||||
static void rna_Depsgraph_debug_graphviz(Depsgraph *graph, const char *filename)
|
||||
static void rna_Depsgraph_debug_relations_graphviz(Depsgraph *graph,
|
||||
const char *filename)
|
||||
{
|
||||
FILE *f = fopen(filename, "w");
|
||||
if (f == NULL) {
|
||||
return;
|
||||
}
|
||||
DEG_debug_graphviz(graph, f, "Depsgraph");
|
||||
DEG_debug_relations_graphviz(graph, f, "Depsgraph");
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
static void rna_Depsgraph_debug_stats_gnuplot(Depsgraph *graph,
|
||||
const char *filename,
|
||||
const char *output_filename)
|
||||
{
|
||||
FILE *f = fopen(filename, "w");
|
||||
if (f == NULL) {
|
||||
return;
|
||||
}
|
||||
DEG_debug_stats_gnuplot(graph, f, "Timing Statistics", output_filename);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
@@ -297,11 +310,19 @@ static void rna_def_depsgraph(BlenderRNA *brna)
|
||||
srna = RNA_def_struct(brna, "Depsgraph", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Dependency Graph", "");
|
||||
|
||||
func = RNA_def_function(srna, "debug_graphviz", "rna_Depsgraph_debug_graphviz");
|
||||
func = RNA_def_function(srna, "debug_relations_graphviz", "rna_Depsgraph_debug_relations_graphviz");
|
||||
parm = RNA_def_string_file_path(func, "filename", NULL, FILE_MAX, "File Name",
|
||||
"File in which to store graphviz debug output");
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
|
||||
func = RNA_def_function(srna, "debug_stats_gnuplot", "rna_Depsgraph_debug_stats_gnuplot");
|
||||
parm = RNA_def_string_file_path(func, "filename", NULL, FILE_MAX, "File Name",
|
||||
"File in which to store graphviz debug output");
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
parm = RNA_def_string_file_path(func, "output_filename", NULL, FILE_MAX, "Output File Name",
|
||||
"File name where gnuplot script will save the result");
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
|
||||
func = RNA_def_function(srna, "debug_tag_update", "rna_Depsgraph_debug_tag_update");
|
||||
|
||||
func = RNA_def_function(srna, "debug_stats", "rna_Depsgraph_debug_stats");
|
||||
|
||||
Reference in New Issue
Block a user