Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Tönne <lukas.toenne@gmail.com>2016-04-28 12:10:54 +0300
committerLukas Tönne <lukas.toenne@gmail.com>2016-04-28 13:10:58 +0300
commitc01c47f79d707289f96dfc052cf1b06c11227614 (patch)
tree66f8f495791a6c9125ad8e193459c1d819b4c427
parentaaf5ee73f0d987940aa95e6fb603e2045d2fea2b (diff)
Depsgraph optimization: Don't schedule tasks for empty "NOOP" nodes.
Currently a lot of the nodes in the new dependency graph are empty placeholders for organizational purposes. These nodes would, however, still be assigned a task which gets scheduled and takes up some time for worker threads to pop from the queue and run. This can be avoided by skipping these nodes during depsgraph scheduling, and scheduling their childrent right away. Gives a few percent speedup in BlenRig.
-rw-r--r--source/blender/depsgraph/intern/depsgraph_eval.cc115
1 files changed, 62 insertions, 53 deletions
diff --git a/source/blender/depsgraph/intern/depsgraph_eval.cc b/source/blender/depsgraph/intern/depsgraph_eval.cc
index e8065766332..fb6722cc893 100644
--- a/source/blender/depsgraph/intern/depsgraph_eval.cc
+++ b/source/blender/depsgraph/intern/depsgraph_eval.cc
@@ -137,29 +137,29 @@ static void deg_task_run_func(TaskPool *pool,
DepsgraphEvalState *state = (DepsgraphEvalState *)BLI_task_pool_userdata(pool);
OperationDepsNode *node = (OperationDepsNode *)taskdata;
- if (!node->is_noop()) {
- /* Get context. */
- // TODO: who initialises this? "Init" operations aren't able to initialise it!!!
- /* TODO(sergey): Wedon't use component contexts at this moment. */
- /* ComponentDepsNode *comp = node->owner; */
- BLI_assert(node->owner != NULL);
-
- /* Take note of current time. */
- double start_time = PIL_check_seconds_timer();
- DepsgraphDebug::task_started(state->graph, node);
-
- /* Should only be the case for NOOPs, which never get to this point. */
- BLI_assert(node->evaluate);
-
- /* Perform operation. */
- node->evaluate(state->eval_ctx);
-
- /* Note how long this took. */
- double end_time = PIL_check_seconds_timer();
- DepsgraphDebug::task_completed(state->graph,
- node,
- end_time - start_time);
- }
+ BLI_assert(!node->is_noop() && "NOOP nodes should not actually be scheduled");
+
+ /* Get context. */
+ // TODO: who initialises this? "Init" operations aren't able to initialise it!!!
+ /* TODO(sergey): Wedon't use component contexts at this moment. */
+ /* ComponentDepsNode *comp = node->owner; */
+ BLI_assert(node->owner != NULL);
+
+ /* Take note of current time. */
+ double start_time = PIL_check_seconds_timer();
+ DepsgraphDebug::task_started(state->graph, node);
+
+ /* Should only be the case for NOOPs, which never get to this point. */
+ BLI_assert(node->evaluate);
+
+ /* Perform operation. */
+ node->evaluate(state->eval_ctx);
+
+ /* Note how long this took. */
+ double end_time = PIL_check_seconds_timer();
+ DepsgraphDebug::task_completed(state->graph,
+ node,
+ end_time - start_time);
schedule_children(pool, state->graph, node, state->layers);
}
@@ -230,26 +230,54 @@ static void calculate_eval_priority(OperationDepsNode *node)
}
}
+/* 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.
+ */
+static void schedule_node(TaskPool *pool, Depsgraph *graph, int layers,
+ OperationDepsNode *node, bool dec_parents)
+{
+ int id_layers = node->owner->owner->layers;
+
+ if ((node->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0 &&
+ (id_layers & layers) != 0)
+ {
+ if (dec_parents) {
+ BLI_assert(node->num_links_pending > 0);
+ atomic_sub_uint32(&node->num_links_pending, 1);
+ }
+
+ if (node->num_links_pending == 0) {
+ BLI_spin_lock(&graph->lock);
+ bool need_schedule = !node->scheduled;
+ node->scheduled = true;
+ BLI_spin_unlock(&graph->lock);
+
+ if (need_schedule) {
+ if (node->is_noop()) {
+ /* skip NOOP node, schedule children right away */
+ schedule_children(pool, graph, node, layers);
+ }
+ else {
+ /* children are scheduled once this task is completed */
+ BLI_task_pool_push(pool, deg_task_run_func, node, false, TASK_PRIORITY_LOW);
+ }
+ }
+ }
+ }
+}
+
static void schedule_graph(TaskPool *pool,
Depsgraph *graph,
const int layers)
{
- BLI_spin_lock(&graph->lock);
for (Depsgraph::OperationNodes::const_iterator it = graph->operations.begin();
it != graph->operations.end();
++it)
{
OperationDepsNode *node = *it;
- IDDepsNode *id_node = node->owner->owner;
- if ((node->flag & DEPSOP_FLAG_NEEDS_UPDATE) &&
- node->num_links_pending == 0 &&
- (id_node->layers & layers) != 0)
- {
- BLI_task_pool_push(pool, deg_task_run_func, node, false, TASK_PRIORITY_LOW);
- node->scheduled = true;
- }
+ schedule_node(pool, graph, layers, node, false);
}
- BLI_spin_unlock(&graph->lock);
}
static void schedule_children(TaskPool *pool,
@@ -270,26 +298,7 @@ static void schedule_children(TaskPool *pool,
continue;
}
- IDDepsNode *id_child = child->owner->owner;
- if ((id_child->layers & layers) != 0 &&
- (child->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0)
- {
- if ((rel->flag & DEPSREL_FLAG_CYCLIC) == 0) {
- BLI_assert(child->num_links_pending > 0);
- atomic_sub_uint32(&child->num_links_pending, 1);
- }
-
- if (child->num_links_pending == 0) {
- BLI_spin_lock(&graph->lock);
- bool need_schedule = !child->scheduled;
- child->scheduled = true;
- BLI_spin_unlock(&graph->lock);
-
- if (need_schedule) {
- BLI_task_pool_push(pool, deg_task_run_func, child, false, TASK_PRIORITY_LOW);
- }
- }
- }
+ schedule_node(pool, graph, layers, child, (rel->flag & DEPSREL_FLAG_CYCLIC) == 0);
}
}