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:
Diffstat (limited to 'source/blender/depsgraph/intern/eval/deg_eval.cc')
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval.cc63
1 files changed, 44 insertions, 19 deletions
diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc
index 2d9d40aede6..9ac1f5275ac 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval.cc
@@ -302,8 +302,28 @@ void schedule_node_to_queue(OperationNode *node,
BLI_gsqueue_push(evaluation_queue, &node);
}
-void evaluate_graph_single_threaded(DepsgraphEvalState *state)
+/* Evaluate given stage of the dependency graph evaluation using multiple threads.
+ *
+ * NOTE: Will assign the `state->stage` to the given stage. */
+void evaluate_graph_threaded_stage(DepsgraphEvalState *state,
+ TaskPool *task_pool,
+ const EvaluationStage stage)
{
+ state->stage = stage;
+
+ schedule_graph(state, schedule_node_to_pool, task_pool);
+ BLI_task_pool_work_and_wait(task_pool);
+}
+
+/* Evaluate remaining operations of the dependency graph in a single threaded manner. */
+void evaluate_graph_single_threaded_if_needed(DepsgraphEvalState *state)
+{
+ if (!state->need_single_thread_pass) {
+ return;
+ }
+
+ state->stage = EvaluationStage::SINGLE_THREADED_WORKAROUND;
+
GSQueue *evaluation_queue = BLI_gsqueue_new(sizeof(OperationNode *));
schedule_graph(state, schedule_node_to_queue, evaluation_queue);
@@ -334,9 +354,7 @@ void depsgraph_ensure_view_layer(Depsgraph *graph)
deg_update_copy_on_write_datablock(graph, scene_id_node);
}
-} // namespace
-
-static TaskPool *deg_evaluate_task_pool_create(DepsgraphEvalState *state)
+TaskPool *deg_evaluate_task_pool_create(DepsgraphEvalState *state)
{
if (G.debug & G_DEBUG_DEPSGRAPH_NO_THREADS) {
return BLI_task_pool_create_no_threads(state);
@@ -345,6 +363,8 @@ static TaskPool *deg_evaluate_task_pool_create(DepsgraphEvalState *state)
return BLI_task_pool_create_suspended(state, TASK_PRIORITY_HIGH);
}
+} // namespace
+
void deg_evaluate_on_refresh(Depsgraph *graph)
{
/* Nothing to update, early out. */
@@ -361,33 +381,37 @@ void deg_evaluate_on_refresh(Depsgraph *graph)
graph->is_evaluating = true;
depsgraph_ensure_view_layer(graph);
+
/* Set up evaluation state. */
DepsgraphEvalState state;
state.graph = graph;
state.do_stats = graph->debug.do_time_debug();
state.need_single_thread_pass = false;
+
/* Prepare all nodes for evaluation. */
initialize_execution(&state, graph);
- /* Do actual evaluation now. */
- /* First, process all Copy-On-Write nodes. */
- state.stage = EvaluationStage::COPY_ON_WRITE;
+ /* Evaluation happens in several incremental steps:
+ *
+ * - Start with the copy-on-write operations which never form dependency cycles. This will ensure
+ * that if a dependency graph has a cycle evaluation functions will always "see" valid expanded
+ * datablock. It might not be evaluated yet, but at least the datablock will be valid.
+ *
+ * - Multi-threaded evaluation of all possible nodes.
+ * Certain operations (and their subtrees) could be ignored. For example, meta-balls are not
+ * safe from threading point of view, so the threaded evaluation will stop at the metaball
+ * operation node.
+ *
+ * - Single-threaded pass of all remaining operations. */
+
TaskPool *task_pool = deg_evaluate_task_pool_create(&state);
- schedule_graph(&state, schedule_node_to_pool, task_pool);
- BLI_task_pool_work_and_wait(task_pool);
- BLI_task_pool_free(task_pool);
- /* After that, process all other nodes. */
- state.stage = EvaluationStage::THREADED_EVALUATION;
- task_pool = deg_evaluate_task_pool_create(&state);
- schedule_graph(&state, schedule_node_to_pool, task_pool);
- BLI_task_pool_work_and_wait(task_pool);
+ evaluate_graph_threaded_stage(&state, task_pool, EvaluationStage::COPY_ON_WRITE);
+ evaluate_graph_threaded_stage(&state, task_pool, EvaluationStage::THREADED_EVALUATION);
+
BLI_task_pool_free(task_pool);
- if (state.need_single_thread_pass) {
- state.stage = EvaluationStage::SINGLE_THREADED_WORKAROUND;
- evaluate_graph_single_threaded(&state);
- }
+ evaluate_graph_single_threaded_if_needed(&state);
/* Finalize statistics gathering. This is because we only gather single
* operation timing here, without aggregating anything to avoid any extra
@@ -395,6 +419,7 @@ void deg_evaluate_on_refresh(Depsgraph *graph)
if (state.do_stats) {
deg_eval_stats_aggregate(graph);
}
+
/* Clear any uncleared tags - just in case. */
deg_graph_clear_tags(graph);
graph->is_evaluating = false;