52struct DepsgraphEvalState;
54void deg_task_run_func(
TaskPool *pool,
void *taskdata);
56void schedule_children(DepsgraphEvalState *
state,
58 FunctionRef<
void(OperationNode *node)> schedule_fn);
61enum class EvaluationStage {
77 SINGLE_THREADED_WORKAROUND,
80struct DepsgraphEvalState {
88void evaluate_node(
const DepsgraphEvalState *
state, OperationNode *operation_node)
90 ::Depsgraph *
depsgraph =
reinterpret_cast<::Depsgraph *
>(
state->graph);
93 BLI_assert_msg(!operation_node->is_noop(),
"NOOP nodes should not actually be scheduled");
95 if (
state->do_stats) {
108 operation_node->flag &= ~DEPSOP_FLAG_CLEAR_ON_EVAL;
111void deg_task_run_func(
TaskPool *pool,
void *taskdata)
114 DepsgraphEvalState *
state = (DepsgraphEvalState *)userdata_v;
117 OperationNode *operation_node =
reinterpret_cast<OperationNode *
>(taskdata);
118 evaluate_node(
state, operation_node);
121 schedule_children(
state, operation_node, [&](OperationNode *node) {
126bool check_operation_node_visible(
const DepsgraphEvalState *
state, OperationNode *op_node)
128 const ComponentNode *comp_node = op_node->owner;
137 if (
state->stage == EvaluationStage::DYNAMIC_VISIBILITY) {
141 return comp_node->affects_visible_id;
144void calculate_pending_parents_for_node(
const DepsgraphEvalState *
state, OperationNode *node)
147 node->num_links_pending = 0;
148 node->scheduled =
false;
150 if (!check_operation_node_visible(
state, node)) {
157 for (Relation *rel : node->inlinks) {
159 OperationNode *from = (OperationNode *)rel->from;
164 if (!check_operation_node_visible(
state, from)) {
171 ++node->num_links_pending;
176void calculate_pending_parents_if_needed(DepsgraphEvalState *
state)
178 if (!
state->need_update_pending_parents) {
182 for (OperationNode *node :
state->graph->operations) {
183 calculate_pending_parents_for_node(
state, node);
186 state->need_update_pending_parents =
false;
189void initialize_execution(DepsgraphEvalState *
state, Depsgraph *graph)
192 if (
state->do_stats) {
193 for (OperationNode *node : graph->operations) {
194 node->stats.reset_current();
199bool is_metaball_object_operation(
const OperationNode *operation_node)
201 const ComponentNode *component_node = operation_node->owner;
202 const IDNode *
id_node = component_node->owner;
210bool need_evaluate_operation_at_stage(DepsgraphEvalState *
state,
211 const OperationNode *operation_node)
213 const ComponentNode *component_node = operation_node->owner;
214 switch (
state->stage) {
215 case EvaluationStage::COPY_ON_EVAL:
218 case EvaluationStage::DYNAMIC_VISIBILITY:
221 case EvaluationStage::THREADED_EVALUATION:
222 if (is_metaball_object_operation(operation_node)) {
223 state->need_single_thread_pass =
true;
228 case EvaluationStage::SINGLE_THREADED_WORKAROUND:
231 BLI_assert_msg(0,
"Unhandled evaluation stage, should never happen.");
239void schedule_node(DepsgraphEvalState *
state,
242 const FunctionRef<
void(OperationNode *node)> schedule_fn)
245 if (!check_operation_node_visible(
state, node)) {
261 if (node->num_links_pending != 0) {
265 if (!need_evaluate_operation_at_stage(
state, node)) {
271 if (node->is_noop()) {
274 node->flag &= ~DEPSOP_FLAG_CLEAR_ON_EVAL;
277 schedule_children(
state, node, schedule_fn);
286void schedule_graph(DepsgraphEvalState *
state,
287 const FunctionRef<
void(OperationNode *node)> schedule_fn)
289 for (OperationNode *node :
state->graph->operations) {
290 schedule_node(
state, node,
false, schedule_fn);
294void schedule_children(DepsgraphEvalState *
state,
296 const FunctionRef<
void(OperationNode *node)> schedule_fn)
298 for (Relation *rel : node->outlinks) {
299 OperationNode *child = (OperationNode *)rel->to;
301 if (child->scheduled) {
312void evaluate_graph_threaded_stage(DepsgraphEvalState *
state,
314 const EvaluationStage
stage)
318 calculate_pending_parents_if_needed(
state);
320 schedule_graph(
state, [&](OperationNode *node) {
327void evaluate_graph_single_threaded_if_needed(DepsgraphEvalState *
state)
329 if (!
state->need_single_thread_pass) {
335 state->stage = EvaluationStage::SINGLE_THREADED_WORKAROUND;
338 auto schedule_node_to_queue = [&](OperationNode *
node) {
341 schedule_graph(
state, schedule_node_to_queue);
344 OperationNode *operation_node;
347 evaluate_node(
state, operation_node);
348 schedule_children(
state, operation_node, schedule_node_to_queue);
354void depsgraph_ensure_view_layer(Depsgraph *graph)
360 Scene *scene_cow = graph->scene_cow;
367 const IDNode *scene_id_node = graph->find_id_node(&graph->scene->id);
371TaskPool *deg_evaluate_task_pool_create(DepsgraphEvalState *
state)
385 if (graph->entry_tags.is_empty()) {
389 graph->update_count++;
391 graph->debug.begin_graph_evaluation();
398 graph->is_evaluating =
true;
399 depsgraph_ensure_view_layer(graph);
402 DepsgraphEvalState
state;
407 initialize_execution(&
state, graph);
428 evaluate_graph_threaded_stage(&
state,
task_pool, EvaluationStage::COPY_ON_EVAL);
430 if (graph->has_animated_visibility || graph->need_update_nodes_visibility) {
433 state.need_update_pending_parents =
true;
435 evaluate_graph_threaded_stage(&
state,
task_pool, EvaluationStage::DYNAMIC_VISIBILITY);
444 state.need_update_pending_parents =
true;
447 evaluate_graph_threaded_stage(&
state,
task_pool, EvaluationStage::THREADED_EVALUATION);
451 evaluate_graph_single_threaded_if_needed(&
state);
456 if (
state.do_stats) {
462 graph->is_evaluating =
false;
468 graph->debug.end_graph_evaluation();
@ G_DEBUG_DEPSGRAPH_NO_THREADS
#define BLI_assert_msg(a, msg)
void BLI_gsqueue_free(GSQueue *queue)
void BLI_gsqueue_push(GSQueue *queue, const void *item)
void BLI_gsqueue_pop(GSQueue *queue, void *r_item)
GSQueue * BLI_gsqueue_new(size_t elem_size)
bool BLI_gsqueue_is_empty(const GSQueue *queue)
TaskPool * BLI_task_pool_create_suspended(void *userdata, eTaskPriority priority)
void * BLI_task_pool_user_data(TaskPool *pool)
TaskPool * BLI_task_pool_create_no_threads(void *userdata)
void BLI_task_pool_work_and_wait(TaskPool *pool)
void BLI_task_pool_free(TaskPool *pool)
void BLI_task_pool_push(TaskPool *pool, TaskRunFunction run, void *taskdata, bool free_taskdata, TaskFreeFunction freedata)
Platform independent time functions.
double BLI_time_now_seconds(void)
#define BPy_BEGIN_ALLOW_THREADS
#define BPy_END_ALLOW_THREADS
Object is a sort of wrapper for general info.
Provides wrapper around system-specific atomic primitives, and some extensions (faked-atomic operatio...
ATOMIC_INLINE uint8_t atomic_fetch_and_or_uint8(uint8_t *p, uint8_t b)
ATOMIC_INLINE uint32_t atomic_sub_and_fetch_uint32(uint32_t *p, uint32_t x)
bool do_time_debug() const
bool need_update_pending_parents
bool need_single_thread_pass
const Depsgraph * depsgraph
void deg_eval_stats_aggregate(Depsgraph *graph)
bool deg_eval_copy_is_expanded(const ID *id_cow)
void deg_graph_clear_tags(Depsgraph *graph)
ID * deg_update_eval_copy_datablock(const Depsgraph *depsgraph, const IDNode *id_node)
void deg_evaluate_on_refresh(Depsgraph *graph)
@ DEPSOP_FLAG_NEEDS_UPDATE
@ DEPSOP_FLAG_AFFECTS_VISIBILITY
void deg_graph_flush_visibility_flags_if_needed(Depsgraph *graph)