Depsgraph: Small optimization to update flushing
authorSergey Sharybin <sergey.vfx@gmail.com>
Mon, 30 May 2016 14:53:04 +0000 (16:53 +0200)
committerSergey Sharybin <sergey.vfx@gmail.com>
Mon, 30 May 2016 14:56:05 +0000 (16:56 +0200)
Gives about 5% speedup in scene with lots of nodes (army_of_clones.blend)

source/blender/depsgraph/intern/eval/deg_eval_flush.cc

index 873138267633c0b0f68fc5d306cd43eea7bc0483..af68f5c55c423e447d472e14c5c39a3296b9af53 100644 (file)
@@ -121,12 +121,7 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
         */
        GSET_FOREACH_BEGIN(OperationDepsNode *, node, graph->entry_tags)
        {
-               IDDepsNode *id_node = node->owner->owner;
                queue.push(node);
-               if (id_node->done == 0) {
-                       deg_editors_id_update(bmain, id_node->id);
-                       id_node->done = 1;
-               }
                node->scheduled = true;
        }
        GSET_FOREACH_END();
@@ -135,56 +130,74 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
                OperationDepsNode *node = queue.front();
                queue.pop();
 
-               IDDepsNode *id_node = node->owner->owner;
-               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;
-                       }
-                       else if (comp_node->type == DEPSNODE_TYPE_TRANSFORM) {
-                               object->recalc |= OB_RECALC_OB;
+               for (;;) {
+                       node->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
+
+                       IDDepsNode *id_node = node->owner->owner;
+
+                       if (id_node->done == 0) {
+                               deg_editors_id_update(bmain, id_node->id);
+                               id_node->done = 1;
                        }
-                       else {
-                               object->recalc |= OB_RECALC_DATA;
+
+                       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;
+                               }
+                               else if (comp_node->type == DEPSNODE_TYPE_TRANSFORM) {
+                                       object->recalc |= OB_RECALC_OB;
+                               }
+                               else {
+                                       object->recalc |= OB_RECALC_DATA;
+                               }
                        }
-               }
 
-               /* Flush to nodes along links... */
-               foreach (DepsRelation *rel, node->outlinks) {
-                       OperationDepsNode *to_node = (OperationDepsNode *)rel->to;
-                       if (to_node->scheduled == false) {
-                               to_node->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
-                               queue.push(to_node);
-                               to_node->scheduled = true;
-                               if (id_node->done == 0) {
-                                       deg_editors_id_update(bmain, id_node->id);
-                                       id_node->done = 1;
+                       /* 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;
                        }
-               }
 
-               /* 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;
+                       /* Flush to nodes along links... */
+                       if (node->outlinks.size() == 1) {
+                               OperationDepsNode *to_node = (OperationDepsNode *)node->outlinks[0]->to;
+                               if (to_node->scheduled == false) {
+                                       to_node->scheduled = true;
+                                       node = to_node;
+                               }
+                               else {
+                                       break;
+                               }
+                       }
+                       else {
+                               foreach (DepsRelation *rel, node->outlinks) {
+                                       OperationDepsNode *to_node = (OperationDepsNode *)rel->to;
+                                       if (to_node->scheduled == false) {
+                                               queue.push(to_node);
+                                               to_node->scheduled = true;
+                                       }
+                               }
+                               break;
                        }
-                       component->flags |= DEPSCOMP_FULLY_SCHEDULED;
                }
        }
 }