diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2018-08-23 17:17:06 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2018-08-23 17:40:35 +0300 |
commit | f97d61c4bd2a9ab3c1dd0ae4902778bc9703a716 (patch) | |
tree | 1d426512c88b369396cc6885523570606f57347f /source/blender/depsgraph/intern/eval/deg_eval.cc | |
parent | a9ecfc965349241b858b1b23d0a3d9b987600b5d (diff) |
Depsgraph: Bring back visibility checks based on collection restrict flags
The title says it all actually, the idea is to speedup the following case:
- Visible duplicator of a restricted collection (reported as T56512),
One of the questionable change is that none of the view layer bases is
ignored now. This ensures corresponding objects will have copy-on-write
component evaluated, making it possible to access those pointers. The
evaluation of those objects is skipped.
Reviewers: brecht
Differential Revision: https://developer.blender.org/D3641
Diffstat (limited to 'source/blender/depsgraph/intern/eval/deg_eval.cc')
-rw-r--r-- | source/blender/depsgraph/intern/eval/deg_eval.cc | 111 |
1 files changed, 76 insertions, 35 deletions
diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc index f911383b273..fb8b8e73ef6 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval.cc @@ -103,6 +103,19 @@ typedef struct CalculatePengindData { Depsgraph *graph; } CalculatePengindData; +static bool check_operation_node_visible(OperationDepsNode *op_node) +{ + const ComponentDepsNode *comp_node = op_node->owner; + /* Special exception, copy on write component is to be always evaluated, + * to keep copied "database" in a consistent state. + */ + if (comp_node->type == DEG_NODE_TYPE_COPY_ON_WRITE) { + return true; + } + const IDDepsNode *id_node = comp_node->owner; + return id_node->is_visible; +} + static void calculate_pending_func( void *__restrict data_v, const int i, @@ -111,21 +124,35 @@ static void calculate_pending_func( CalculatePengindData *data = (CalculatePengindData *)data_v; Depsgraph *graph = data->graph; OperationDepsNode *node = graph->operations[i]; - + /* Update counters, applies for both visible and invisible IDs. */ node->num_links_pending = 0; node->scheduled = false; - - /* count number of inputs that need updates */ - if ((node->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0) { - foreach (DepsRelation *rel, node->inlinks) { - if (rel->from->type == DEG_NODE_TYPE_OPERATION && - (rel->flag & DEPSREL_FLAG_CYCLIC) == 0) - { - OperationDepsNode *from = (OperationDepsNode *)rel->from; - if ((from->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0) { - ++node->num_links_pending; - } + /* Invisible IDs requires no pending operations. */ + if (!check_operation_node_visible(node)) { + return; + } + /* No need to bother with anything if node is not tagged for update. */ + if ((node->flag & DEPSOP_FLAG_NEEDS_UPDATE) == 0) { + return; + } + foreach (DepsRelation *rel, node->inlinks) { + if (rel->from->type == DEG_NODE_TYPE_OPERATION && + (rel->flag & DEPSREL_FLAG_CYCLIC) == 0) + { + OperationDepsNode *from = (OperationDepsNode *)rel->from; + /* TODO(sergey): This is how old layer system was checking for the + * calculation, but how is it possible that visible object depends + * on an invisible? This is something what is prohibited after + * deg_graph_build_flush_layers(). + */ + if (!check_operation_node_visible(from)) { + continue; + } + /* No need to vait for operation which is up to date. */ + if ((from->flag & DEPSOP_FLAG_NEEDS_UPDATE) == 0) { + continue; } + ++node->num_links_pending; } } } @@ -166,30 +193,44 @@ static void schedule_node(TaskPool *pool, Depsgraph *graph, OperationDepsNode *node, bool dec_parents, const int thread_id) { - if ((node->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0) { - if (dec_parents) { - BLI_assert(node->num_links_pending > 0); - atomic_sub_and_fetch_uint32(&node->num_links_pending, 1); + /* No need to schedule nodes of invisible ID. */ + if (!check_operation_node_visible(node)) { + return; + } + /* No need to schedule operations which are not tagged for update, they are + * considered to be up to date. + */ + if ((node->flag & DEPSOP_FLAG_NEEDS_UPDATE) == 0) { + return; + } + /* TODO(sergey): This is not strictly speaking safe to read + * num_links_pending. + */ + if (dec_parents) { + BLI_assert(node->num_links_pending > 0); + atomic_sub_and_fetch_uint32(&node->num_links_pending, 1); + } + /* Cal not schedule operation while its dependencies are not yet + * evaluated. + */ + if (node->num_links_pending != 0) { + return; + } + bool is_scheduled = atomic_fetch_and_or_uint8( + (uint8_t *)&node->scheduled, (uint8_t)true); + if (!is_scheduled) { + if (node->is_noop()) { + /* skip NOOP node, schedule children right away */ + schedule_children(pool, graph, node, thread_id); } - - if (node->num_links_pending == 0) { - bool is_scheduled = atomic_fetch_and_or_uint8( - (uint8_t *)&node->scheduled, (uint8_t)true); - if (!is_scheduled) { - if (node->is_noop()) { - /* skip NOOP node, schedule children right away */ - schedule_children(pool, graph, node, thread_id); - } - else { - /* children are scheduled once this task is completed */ - BLI_task_pool_push_from_thread(pool, - deg_task_run_func, - node, - false, - TASK_PRIORITY_HIGH, - thread_id); - } - } + else { + /* children are scheduled once this task is completed */ + BLI_task_pool_push_from_thread(pool, + deg_task_run_func, + node, + false, + TASK_PRIORITY_HIGH, + thread_id); } } } |