51struct DepsgraphEvalState;
53void deg_task_run_func(
TaskPool *pool,
void *taskdata);
55void schedule_children(DepsgraphEvalState *
state,
57 FunctionRef<
void(OperationNode *
node)> schedule_fn);
60enum class EvaluationStage {
76 SINGLE_THREADED_WORKAROUND,
79struct DepsgraphEvalState {
87void evaluate_node(
const DepsgraphEvalState *
state, OperationNode *operation_node)
89 ::Depsgraph *
depsgraph =
reinterpret_cast<::Depsgraph *
>(
state->graph);
92 BLI_assert_msg(!operation_node->is_noop(),
"NOOP nodes should not actually be scheduled");
94 if (
state->do_stats) {
107 operation_node->flag &= ~DEPSOP_FLAG_CLEAR_ON_EVAL;
110void deg_task_run_func(
TaskPool *pool,
void *taskdata)
113 DepsgraphEvalState *
state = (DepsgraphEvalState *)userdata_v;
116 OperationNode *operation_node =
reinterpret_cast<OperationNode *
>(taskdata);
117 evaluate_node(
state, operation_node);
120 schedule_children(
state, operation_node, [&](OperationNode *
node) {
125bool check_operation_node_visible(
const DepsgraphEvalState *
state, OperationNode *op_node)
127 const ComponentNode *comp_node = op_node->owner;
136 if (
state->stage == EvaluationStage::DYNAMIC_VISIBILITY) {
140 return comp_node->affects_visible_id;
143void calculate_pending_parents_for_node(
const DepsgraphEvalState *
state, OperationNode *
node)
149 if (!check_operation_node_visible(
state,
node)) {
156 for (Relation *rel :
node->inlinks) {
158 OperationNode *
from = (OperationNode *)rel->from;
163 if (!check_operation_node_visible(
state,
from)) {
175void calculate_pending_parents_if_needed(DepsgraphEvalState *
state)
177 if (!
state->need_update_pending_parents) {
182 calculate_pending_parents_for_node(
state,
node);
185 state->need_update_pending_parents =
false;
188void initialize_execution(DepsgraphEvalState *
state, Depsgraph *
graph)
191 if (
state->do_stats) {
192 for (OperationNode *
node :
graph->operations) {
198bool is_metaball_object_operation(
const OperationNode *operation_node)
200 const ComponentNode *component_node = operation_node->owner;
201 const IDNode *
id_node = component_node->owner;
209bool need_evaluate_operation_at_stage(DepsgraphEvalState *
state,
210 const OperationNode *operation_node)
212 const ComponentNode *component_node = operation_node->owner;
213 switch (
state->stage) {
214 case EvaluationStage::COPY_ON_EVAL:
217 case EvaluationStage::DYNAMIC_VISIBILITY:
220 case EvaluationStage::THREADED_EVALUATION:
221 if (is_metaball_object_operation(operation_node)) {
222 state->need_single_thread_pass =
true;
227 case EvaluationStage::SINGLE_THREADED_WORKAROUND:
230 BLI_assert_msg(0,
"Unhandled evaluation stage, should never happen.");
238void schedule_node(DepsgraphEvalState *
state,
241 const FunctionRef<
void(OperationNode *
node)> schedule_fn)
244 if (!check_operation_node_visible(
state,
node)) {
264 if (!need_evaluate_operation_at_stage(
state,
node)) {
273 node->
flag &= ~DEPSOP_FLAG_CLEAR_ON_EVAL;
276 schedule_children(
state,
node, schedule_fn);
285void schedule_graph(DepsgraphEvalState *
state,
286 const FunctionRef<
void(OperationNode *
node)> schedule_fn)
289 schedule_node(
state,
node,
false, schedule_fn);
293void schedule_children(DepsgraphEvalState *
state,
295 const FunctionRef<
void(OperationNode *
node)> schedule_fn)
297 for (Relation *rel :
node->outlinks) {
298 OperationNode *child = (OperationNode *)rel->to;
300 if (child->scheduled) {
311void evaluate_graph_threaded_stage(DepsgraphEvalState *
state,
313 const EvaluationStage
stage)
317 calculate_pending_parents_if_needed(
state);
319 schedule_graph(
state, [&](OperationNode *
node) {
326void evaluate_graph_single_threaded_if_needed(DepsgraphEvalState *
state)
328 if (!
state->need_single_thread_pass) {
334 state->stage = EvaluationStage::SINGLE_THREADED_WORKAROUND;
337 auto schedule_node_to_queue = [&](OperationNode *
node) {
340 schedule_graph(
state, schedule_node_to_queue);
343 OperationNode *operation_node;
346 evaluate_node(
state, operation_node);
347 schedule_children(
state, operation_node, schedule_node_to_queue);
353void depsgraph_ensure_view_layer(Depsgraph *
graph)
370TaskPool *deg_evaluate_task_pool_create(DepsgraphEvalState *
state)
396 static std::atomic<uint64_t> global_update_count = 0;
407 depsgraph_ensure_view_layer(
graph);
410 DepsgraphEvalState
state;
436 evaluate_graph_threaded_stage(&
state,
task_pool, EvaluationStage::COPY_ON_EVAL);
441 state.need_update_pending_parents =
true;
443 evaluate_graph_threaded_stage(&
state,
task_pool, EvaluationStage::DYNAMIC_VISIBILITY);
452 state.need_update_pending_parents =
true;
455 evaluate_graph_threaded_stage(&
state,
task_pool, EvaluationStage::THREADED_EVALUATION);
459 evaluate_graph_single_threaded_if_needed(&
state);
464 if (
state.do_stats) {
@ 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)
void begin_graph_evaluation()
void end_graph_evaluation()
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)
IDNode * find_id_node(const ID *id) const
bool need_update_nodes_visibility
bool has_animated_visibility
Set< OperationNode * > entry_tags
uint32_t num_links_pending