Merge branch 'master' into blender2.8
authorSergey Sharybin <sergey.vfx@gmail.com>
Thu, 21 Dec 2017 15:36:02 +0000 (16:36 +0100)
committerSergey Sharybin <sergey.vfx@gmail.com>
Thu, 21 Dec 2017 15:36:02 +0000 (16:36 +0100)
1  2 
source/blender/depsgraph/CMakeLists.txt
source/blender/depsgraph/DEG_depsgraph_debug.h
source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc
source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc
source/blender/depsgraph/intern/eval/deg_eval.cc
source/blender/depsgraph/intern/nodes/deg_node.cc
source/blender/makesrna/intern/rna_depsgraph.c

index f5e43c71f93d4907ac85fd0c768b456581723734,af2c2ecb67fbf07a26791f434f84bcbc2adb6f64..c42d06bd0a296f8aad74dc4e6fab0b66454663ca
@@@ -49,14 -48,14 +49,16 @@@ set(SR
        intern/builder/deg_builder_pchanmap.cc
        intern/builder/deg_builder_relations.cc
        intern/builder/deg_builder_relations_keys.cc
 +      intern/builder/deg_builder_relations_layer_collection.cc
        intern/builder/deg_builder_relations_rig.cc
 -      intern/builder/deg_builder_relations_scene.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
@@@ -85,8 -83,8 +87,9 @@@
        intern/builder/deg_builder_relations_impl.h
        intern/builder/deg_builder_transitive.h
        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
index 0000000000000000000000000000000000000000,ecef4ff55a79be1d4cbfdb7e27f38925cf149f34..3e20196c2ea1f90bce5de3d287da4e66aea6637a
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,126 +1,126 @@@
 -                                id_node->id->name + 2,
+ /*
+  * ***** 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);
+ }
index 583261024ee2a8e32e9ab147e7518a576c39d452,09d25be41d6e12e7b1d46affa72b16205ae11455..ee58a3b02a5751f4e89ddb132010f6c95bb14466
@@@ -70,40 -74,31 +71,30 @@@ static void schedule_children(TaskPool 
  struct DepsgraphEvalState {
        EvaluationContext *eval_ctx;
        Depsgraph *graph;
 -      unsigned int layers;
+       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, state->layers, thread_id);
 +      schedule_children(pool, state->graph, node, thread_id);
        BLI_task_pool_delayed_push_end(pool, thread_id);
  }
  
@@@ -148,6 -152,19 +139,19 @@@ static void calculate_pending_parents(D
                                do_threads);
  }
  
 -      calculate_pending_parents(graph, state->layers);
+ 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.
@@@ -219,30 -244,29 +223,25 @@@ static void schedule_children(TaskPool 
   * \note Time sources should be all valid!
   */
  void deg_evaluate_on_refresh(EvaluationContext *eval_ctx,
 -                             Depsgraph *graph,
 -                             const unsigned int layers)
 +                             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;
        }
 -      DEG_DEBUG_PRINTF("%s: layers:%u, graph->layers:%u\n",
 -                       __func__,
 -                       layers,
 -                       graph->layers);
        /* 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.layers = layers;
+       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;
                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, layers);
 +      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);
        }
index a5b8845b120ffdedb60e62a87daeb5bea0cdd440,1091239805f56d5ccaf92cfb1dddfd144840be26..20ce54a4a012e95dbe019d86062ce9eb048c5f3c
  
  #ifdef RNA_RUNTIME
  
 +#include "BLI_iterator.h"
 +
  #include "DEG_depsgraph_build.h"
  #include "DEG_depsgraph_debug.h"
 +#include "DEG_depsgraph_query.h"
 +
 +#include "MEM_guardedalloc.h"
 +
 +/* **************** Depsgraph **************** */
 +
 +static PointerRNA rna_DepsgraphIter_object_get(PointerRNA *ptr)
 +{
 +      BLI_Iterator *iterator = ptr->data;
 +      return rna_pointer_inherit_refine(ptr, &RNA_Object, iterator->current);
 +}
 +
 +static PointerRNA rna_DepsgraphIter_instance_object_get(PointerRNA *ptr)
 +{
 +      BLI_Iterator *iterator = ptr->data;
 +      DEGObjectIterData *deg_iter = (DEGObjectIterData *)iterator->data;
 +      Object *instance_object = NULL;
 +      if (deg_iter->dupli_object_current != NULL) {
 +              instance_object = deg_iter->dupli_object_current->ob;
 +      }
 +      return rna_pointer_inherit_refine(ptr, &RNA_Object, instance_object);
 +}
 +
 +static PointerRNA rna_DepsgraphIter_parent_get(PointerRNA *ptr)
 +{
 +      BLI_Iterator *iterator = ptr->data;
 +      DEGObjectIterData *deg_iter = (DEGObjectIterData *)iterator->data;
 +      Object *dupli_parent = NULL;
 +      if (deg_iter->dupli_object_current != NULL) {
 +              dupli_parent = deg_iter->dupli_parent;
 +      }
 +      return rna_pointer_inherit_refine(ptr, &RNA_Object, dupli_parent);
 +}
 +
 +static void rna_DepsgraphIter_persistent_id_get(PointerRNA *ptr, int *persistent_id)
 +{
 +      BLI_Iterator *iterator = ptr->data;
 +      DEGObjectIterData *deg_iter = (DEGObjectIterData *)iterator->data;
 +      memcpy(persistent_id, deg_iter->dupli_object_current->persistent_id,
 +             sizeof(deg_iter->dupli_object_current->persistent_id));
 +}
 +
 +static void rna_DepsgraphIter_orco_get(PointerRNA *ptr, float *orco)
 +{
 +      BLI_Iterator *iterator = ptr->data;
 +      DEGObjectIterData *deg_iter = (DEGObjectIterData *)iterator->data;
 +      memcpy(orco, deg_iter->dupli_object_current->orco,
 +             sizeof(deg_iter->dupli_object_current->orco));
 +}
 +
 +static unsigned int rna_DepsgraphIter_random_id_get(PointerRNA *ptr)
 +{
 +      BLI_Iterator *iterator = ptr->data;
 +      DEGObjectIterData *deg_iter = (DEGObjectIterData *)iterator->data;
 +      return deg_iter->dupli_object_current->random_id;
 +}
 +
 +static void rna_DepsgraphIter_uv_get(PointerRNA *ptr, float *uv)
 +{
 +      BLI_Iterator *iterator = ptr->data;
 +      DEGObjectIterData *deg_iter = (DEGObjectIterData *)iterator->data;
 +      memcpy(uv, deg_iter->dupli_object_current->uv,
 +             sizeof(deg_iter->dupli_object_current->uv));
 +}
 +
 +static int rna_DepsgraphIter_is_instance_get(PointerRNA *ptr)
 +{
 +      BLI_Iterator *iterator = ptr->data;
 +      DEGObjectIterData *deg_iter = (DEGObjectIterData *)iterator->data;
 +      return (deg_iter->dupli_object_current != NULL);
 +}
 +
 +/* **************** 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) {