51 struct DepsgraphEvalState;
55 template<
typename ScheduleFunction,
typename... ScheduleFunctionArgs>
56 void schedule_children(DepsgraphEvalState *
state,
58 ScheduleFunction *schedule_function,
59 ScheduleFunctionArgs... schedule_function_args);
67 enum class EvaluationStage {
83 SINGLE_THREADED_WORKAROUND,
86 struct DepsgraphEvalState {
94 void evaluate_node(
const DepsgraphEvalState *
state, OperationNode *operation_node)
99 BLI_assert_msg(!operation_node->is_noop(),
"NOOP nodes should not actually be scheduled");
101 if (
state->do_stats) {
121 DepsgraphEvalState *
state = (DepsgraphEvalState *)userdata_v;
124 OperationNode *operation_node =
reinterpret_cast<OperationNode *
>(taskdata);
125 evaluate_node(
state, operation_node);
128 schedule_children(
state, operation_node, schedule_node_to_pool,
pool);
131 bool check_operation_node_visible(
const DepsgraphEvalState *
state, OperationNode *op_node)
133 const ComponentNode *comp_node = op_node->owner;
142 if (
state->stage == EvaluationStage::DYNAMIC_VISIBILITY) {
146 return comp_node->affects_visible_id;
149 void calculate_pending_parents_for_node(
const DepsgraphEvalState *
state, OperationNode *
node)
155 if (!check_operation_node_visible(
state,
node)) {
164 OperationNode *
from = (OperationNode *)rel->from;
181 void calculate_pending_parents_if_needed(DepsgraphEvalState *
state)
183 if (!
state->need_update_pending_parents) {
187 for (OperationNode *
node :
state->graph->operations) {
188 calculate_pending_parents_for_node(
state,
node);
191 state->need_update_pending_parents =
false;
197 if (
state->do_stats) {
204 bool is_metaball_object_operation(
const OperationNode *operation_node)
206 const ComponentNode *component_node = operation_node->owner;
207 const IDNode *
id_node = component_node->owner;
215 bool need_evaluate_operation_at_stage(DepsgraphEvalState *
state,
216 const OperationNode *operation_node)
218 const ComponentNode *component_node = operation_node->owner;
219 switch (
state->stage) {
220 case EvaluationStage::COPY_ON_WRITE:
223 case EvaluationStage::DYNAMIC_VISIBILITY:
226 case EvaluationStage::THREADED_EVALUATION:
227 if (is_metaball_object_operation(operation_node)) {
228 state->need_single_thread_pass =
true;
233 case EvaluationStage::SINGLE_THREADED_WORKAROUND:
236 BLI_assert_msg(0,
"Unhandled evaluation stage, should never happen.");
244 template<
typename ScheduleFunction,
typename... ScheduleFunctionArgs>
245 void schedule_node(DepsgraphEvalState *
state,
248 ScheduleFunction *schedule_function,
249 ScheduleFunctionArgs... schedule_function_args)
252 if (!check_operation_node_visible(
state,
node)) {
272 if (!need_evaluate_operation_at_stage(
state,
node)) {
280 schedule_children(
state,
node, schedule_function, schedule_function_args...);
284 schedule_function(
node, 0, schedule_function_args...);
289 template<
typename ScheduleFunction,
typename... ScheduleFunctionArgs>
290 void schedule_graph(DepsgraphEvalState *
state,
291 ScheduleFunction *schedule_function,
292 ScheduleFunctionArgs... schedule_function_args)
294 for (OperationNode *
node :
state->graph->operations) {
295 schedule_node(
state,
node,
false, schedule_function, schedule_function_args...);
299 template<
typename ScheduleFunction,
typename... ScheduleFunctionArgs>
300 void schedule_children(DepsgraphEvalState *
state,
302 ScheduleFunction *schedule_function,
303 ScheduleFunctionArgs... schedule_function_args)
306 OperationNode *child = (OperationNode *)rel->to;
308 if (child->scheduled) {
316 schedule_function_args...);
320 void schedule_node_to_queue(OperationNode *
node,
330 void evaluate_graph_threaded_stage(DepsgraphEvalState *
state,
332 const EvaluationStage
stage)
336 calculate_pending_parents_if_needed(
state);
343 void evaluate_graph_single_threaded_if_needed(DepsgraphEvalState *
state)
345 if (!
state->need_single_thread_pass) {
351 state->stage = EvaluationStage::SINGLE_THREADED_WORKAROUND;
354 schedule_graph(
state, schedule_node_to_queue, evaluation_queue);
357 OperationNode *operation_node;
360 evaluate_node(
state, operation_node);
361 schedule_children(
state, operation_node, schedule_node_to_queue, evaluation_queue);
383 TaskPool *deg_evaluate_task_pool_create(DepsgraphEvalState *
state)
409 depsgraph_ensure_view_layer(
graph);
412 DepsgraphEvalState
state;
438 evaluate_graph_threaded_stage(&
state,
task_pool, EvaluationStage::COPY_ON_WRITE);
443 state.need_update_pending_parents =
true;
445 evaluate_graph_threaded_stage(&
state,
task_pool, EvaluationStage::DYNAMIC_VISIBILITY);
454 state.need_update_pending_parents =
true;
457 evaluate_graph_threaded_stage(&
state,
task_pool, EvaluationStage::THREADED_EVALUATION);
461 evaluate_graph_single_threaded_if_needed(&
state);
466 if (
state.do_stats) {
@ G_DEBUG_DEPSGRAPH_NO_THREADS
#define BLI_assert_msg(a, msg)
void BLI_gsqueue_free(GSQueue *queue)
GSQueue * BLI_gsqueue_new(size_t elem_size)
void BLI_gsqueue_push(GSQueue *queue, const void *item)
void BLI_gsqueue_pop(GSQueue *queue, void *r_item)
bool BLI_gsqueue_is_empty(const GSQueue *queue)
void * BLI_task_pool_user_data(TaskPool *pool)
void BLI_task_pool_work_and_wait(TaskPool *pool)
TaskPool * BLI_task_pool_create_suspended(void *userdata, eTaskPriority priority)
TaskPool * BLI_task_pool_create_no_threads(void *userdata)
void BLI_task_pool_free(TaskPool *pool)
void BLI_task_pool_push(TaskPool *pool, TaskRunFunction run, void *taskdata, bool free_taskdata, TaskFreeFunction freedata)
#define BPy_BEGIN_ALLOW_THREADS
#define BPy_END_ALLOW_THREADS
struct Depsgraph Depsgraph
@ ID_RECALC_COPY_ON_WRITE
Object is a sort of wrapper for general info.
Platform independent time functions.
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)
ID * deg_update_copy_on_write_datablock(const Depsgraph *depsgraph, const IDNode *id_node)
void deg_graph_clear_tags(Depsgraph *graph)
void deg_evaluate_on_refresh(Depsgraph *graph)
bool deg_copy_on_write_is_expanded(const ID *id_cow)
@ DEPSOP_FLAG_NEEDS_UPDATE
@ DEPSOP_FLAG_AFFECTS_VISIBILITY
@ DEPSOP_FLAG_DIRECTLY_MODIFIED
@ DEPSOP_FLAG_USER_MODIFIED
void deg_graph_flush_visibility_flags_if_needed(Depsgraph *graph)
thread_local int thread_id
IDNode * find_id_node(const ID *id) const
OperationNodes operations
bool has_animated_visibility
Set< OperationNode * > entry_tags
uint32_t num_links_pending
double PIL_check_seconds_timer(void)