Depsgraph: Remove workarounds from depsgraph for keeping threads alive
[blender-staging.git] / source / blender / depsgraph / intern / eval / deg_eval_flush.cc
index af68f5c55c423e447d472e14c5c39a3296b9af53..e10f86f6e95456b6f92d22cd20cdf036478c58cf 100644 (file)
@@ -24,7 +24,7 @@
  * ***** END GPL LICENSE BLOCK *****
  */
 
-/** \file blender/depsgraph/intern/depsgraph_tag.cc
+/** \file blender/depsgraph/intern/eval/deg_eval_flush.cc
  *  \ingroup depsgraph
  *
  * Core routines for how the Depsgraph works.
@@ -33,7 +33,7 @@
 #include "intern/eval/deg_eval_flush.h"
 
 // TODO(sergey): Use some sort of wrapper.
-#include <queue>
+#include <deque>
 
 extern "C" {
 #include "DNA_object_types.h"
@@ -71,7 +71,7 @@ void lib_id_recalc_data_tag(Main *bmain, ID *id)
 
 }  /* namespace */
 
-typedef std::queue<OperationDepsNode *> FlushQueue;
+typedef std::deque<OperationDepsNode *> FlushQueue;
 
 static void flush_init_func(void *data_v, int i)
 {
@@ -80,10 +80,11 @@ static void flush_init_func(void *data_v, int i)
         */
        Depsgraph *graph = (Depsgraph *)data_v;
        OperationDepsNode *node = graph->operations[i];
-       IDDepsNode *id_node = node->owner->owner;
+       ComponentDepsNode *comp_node = node->owner;
+       IDDepsNode *id_node = comp_node->owner;
        id_node->done = 0;
+       comp_node->done = 0;
        node->scheduled = false;
-       node->owner->flags &= ~DEPSCOMP_FULLY_SCHEDULED;
 }
 
 /* Flush updates from tagged nodes outwards until all affected nodes
@@ -121,63 +122,69 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
         */
        GSET_FOREACH_BEGIN(OperationDepsNode *, node, graph->entry_tags)
        {
-               queue.push(node);
+               queue.push_back(node);
                node->scheduled = true;
        }
        GSET_FOREACH_END();
 
+       int num_flushed_objects = 0;
        while (!queue.empty()) {
                OperationDepsNode *node = queue.front();
-               queue.pop();
+               queue.pop_front();
 
                for (;;) {
                        node->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
 
-                       IDDepsNode *id_node = node->owner->owner;
+                       ComponentDepsNode *comp_node = node->owner;
+                       IDDepsNode *id_node = comp_node->owner;
 
-                       if (id_node->done == 0) {
-                               deg_editors_id_update(bmain, id_node->id);
-                               id_node->done = 1;
+                       ID *id = id_node->id;
+                       if(id_node->done == 0) {
+                               deg_editors_id_update(bmain, id);
+                               lib_id_recalc_tag(bmain, id);
+                               /* TODO(sergey): For until we've got proper data nodes in the graph. */
+                               lib_id_recalc_data_tag(bmain, id);
                        }
 
-                       lib_id_recalc_tag(bmain, id_node->id);
-                       /* TODO(sergey): For until we've got proper data nodes in the graph. */
-                       lib_id_recalc_data_tag(bmain, id_node->id);
-
-                       ID *id = id_node->id;
-                       /* This code is used to preserve those areas which does direct
-                        * object update,
-                        *
-                        * Plus it ensures visibility changes and relations and layers
-                        * visibility update has proper flags to work with.
-                        */
-                       if (GS(id->name) == ID_OB) {
-                               Object *object = (Object *)id;
-                               ComponentDepsNode *comp_node = node->owner;
-                               if (comp_node->type == DEPSNODE_TYPE_ANIMATION) {
-                                       object->recalc |= OB_RECALC_TIME;
+                       if(comp_node->done == 0) {
+                               Object *object = NULL;
+                               if (GS(id->name) == ID_OB) {
+                                       object = (Object *)id;
+                                       if(id_node->done == 0) {
+                                               ++num_flushed_objects;
+                                       }
                                }
-                               else if (comp_node->type == DEPSNODE_TYPE_TRANSFORM) {
-                                       object->recalc |= OB_RECALC_OB;
+                               foreach (OperationDepsNode *op, comp_node->operations) {
+                                       op->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
                                }
-                               else {
-                                       object->recalc |= OB_RECALC_DATA;
+                               if (object != NULL) {
+                                       /* This code is used to preserve those areas which does
+                                        * direct object update,
+                                        *
+                                        * Plus it ensures visibility changes and relations and
+                                        * layers visibility update has proper flags to work with.
+                                        */
+                                       if (comp_node->type == DEPSNODE_TYPE_ANIMATION) {
+                                               object->recalc |= OB_RECALC_TIME;
+                                       }
+                                       else if (comp_node->type == DEPSNODE_TYPE_TRANSFORM) {
+                                               object->recalc |= OB_RECALC_OB;
+                                       }
+                                       else {
+                                               object->recalc |= OB_RECALC_DATA;
+                                       }
                                }
                        }
 
-                       /* TODO(sergey): For until incremental updates are possible
-                        * witin a component at least we tag the whole component
-                        * for update.
-                        */
-                       ComponentDepsNode *component = node->owner;
-                       if ((component->flags & DEPSCOMP_FULLY_SCHEDULED) == 0) {
-                               foreach (OperationDepsNode *op, component->operations) {
-                                       op->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
-                               }
-                               component->flags |= DEPSCOMP_FULLY_SCHEDULED;
-                       }
+                       id_node->done = 1;
+                       comp_node->done = 1;
 
                        /* Flush to nodes along links... */
+                       /* TODO(sergey): This is mainly giving speedup due ot less queue pushes, which
+                        * reduces number of memory allocations.
+                        *
+                        * We should try solve the allocation issue instead of doing crazy things here.
+                        */
                        if (node->outlinks.size() == 1) {
                                OperationDepsNode *to_node = (OperationDepsNode *)node->outlinks[0]->to;
                                if (to_node->scheduled == false) {
@@ -192,7 +199,7 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
                                foreach (DepsRelation *rel, node->outlinks) {
                                        OperationDepsNode *to_node = (OperationDepsNode *)rel->to;
                                        if (to_node->scheduled == false) {
-                                               queue.push(to_node);
+                                               queue.push_front(to_node);
                                                to_node->scheduled = true;
                                        }
                                }
@@ -200,6 +207,7 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
                        }
                }
        }
+       DEG_DEBUG_PRINTF("Update flushed to %d objects\n", num_flushed_objects);
 }
 
 static void graph_clear_func(void *data_v, int i)