Blender  V3.3
deg_eval_flush.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2013 Blender Foundation. All rights reserved. */
3 
11 
12 #include <cmath>
13 
14 #include "BLI_listbase.h"
15 #include "BLI_math_vector.h"
16 #include "BLI_task.h"
17 #include "BLI_utildefines.h"
18 
19 #include "BKE_key.h"
20 #include "BKE_object.h"
21 #include "BKE_scene.h"
22 
23 #include "DNA_key_types.h"
24 #include "DNA_object_types.h"
25 #include "DNA_scene_types.h"
26 
27 #include "DRW_engine.h"
28 
29 #include "DEG_depsgraph.h"
30 
31 #include "intern/debug/deg_debug.h"
32 #include "intern/depsgraph.h"
34 #include "intern/depsgraph_type.h"
36 #include "intern/node/deg_node.h"
42 
44 
45 /* Invalidate data-block data when update is flushed on it.
46  *
47  * The idea of this is to help catching cases when area is accessing data which
48  * is not yet evaluated, which could happen due to missing relations. The issue
49  * is that usually that data will be kept from previous frame, and it looks to
50  * be plausible.
51  *
52  * This ensures that data does not look plausible, making it much easier to
53  * catch usage of invalid state. */
54 #undef INVALIDATE_ON_FLUSH
55 
56 namespace blender::deg {
57 
58 enum {
61 };
62 
63 enum {
67 };
68 
69 using FlushQueue = deque<OperationNode *>;
70 
71 namespace {
72 
73 void flush_init_id_node_func(void *__restrict data_v,
74  const int i,
75  const TaskParallelTLS *__restrict /*tls*/)
76 {
77  Depsgraph *graph = (Depsgraph *)data_v;
80  for (ComponentNode *comp_node : id_node->components.values()) {
81  comp_node->custom_flags = COMPONENT_STATE_NONE;
82  }
83 }
84 
85 inline void flush_prepare(Depsgraph *graph)
86 {
88  node->scheduled = false;
89  }
90 
91  {
92  const int num_id_nodes = graph->id_nodes.size();
93  TaskParallelSettings settings;
95  settings.min_iter_per_thread = 1024;
96  BLI_task_parallel_range(0, num_id_nodes, graph, flush_init_id_node_func, &settings);
97  }
98 }
99 
100 inline void flush_schedule_entrypoints(Depsgraph *graph, FlushQueue *queue)
101 {
102  for (OperationNode *op_node : graph->entry_tags) {
103  queue->push_back(op_node);
104  op_node->scheduled = true;
106  EVAL,
107  "Operation is entry point for update: %s\n",
108  op_node->identifier().c_str());
109  }
110 }
111 
112 inline void flush_handle_id_node(IDNode *id_node)
113 {
115 }
116 
117 /* TODO(sergey): We can reduce number of arguments here. */
118 inline void flush_handle_component_node(IDNode *id_node,
119  ComponentNode *comp_node,
120  FlushQueue *queue)
121 {
122  /* We only handle component once. */
123  if (comp_node->custom_flags == COMPONENT_STATE_DONE) {
124  return;
125  }
126  comp_node->custom_flags = COMPONENT_STATE_DONE;
127  /* Tag all required operations in component for update, unless this is a
128  * special component where we don't want all operations to be tagged.
129  *
130  * TODO(sergey): Make this a more generic solution. */
132  for (OperationNode *op : comp_node->operations) {
134  }
135  }
136  /* when some target changes bone, we might need to re-run the
137  * whole IK solver, otherwise result might be unpredictable. */
138  if (comp_node->type == NodeType::BONE) {
140  BLI_assert(pose_comp != nullptr);
141  if (pose_comp->custom_flags == COMPONENT_STATE_NONE) {
142  queue->push_front(pose_comp->get_entry_operation());
144  }
145  }
146 }
147 
148 /* Schedule children of the given operation node for traversal.
149  *
150  * One of the children will by-pass the queue and will be returned as a function
151  * return value, so it can start being handled right away, without building too
152  * much of a queue.
153  */
154 inline OperationNode *flush_schedule_children(OperationNode *op_node, FlushQueue *queue)
155 {
156  if (op_node->flag & DEPSOP_FLAG_USER_MODIFIED) {
157  IDNode *id_node = op_node->owner->owner;
158  id_node->is_user_modified = true;
159  }
160 
161  OperationNode *result = nullptr;
162  for (Relation *rel : op_node->outlinks) {
163  /* Flush is forbidden, completely. */
164  if (rel->flag & RELATION_FLAG_NO_FLUSH) {
165  continue;
166  }
167  /* Relation only allows flushes on user changes, but the node was not
168  * affected by user. */
170  (op_node->flag & DEPSOP_FLAG_USER_MODIFIED) == 0) {
171  continue;
172  }
173  OperationNode *to_node = (OperationNode *)rel->to;
174  /* Always flush flushable flags, so children always know what happened
175  * to their parents. */
176  to_node->flag |= (op_node->flag & DEPSOP_FLAG_FLUSH);
177  /* Flush update over the relation, if it was not flushed yet. */
178  if (to_node->scheduled) {
179  continue;
180  }
181  if (result != nullptr) {
182  queue->push_front(to_node);
183  }
184  else {
185  result = to_node;
186  }
187  to_node->scheduled = true;
188  }
189  return result;
190 }
191 
192 void flush_engine_data_update(ID *id)
193 {
194  DrawDataList *draw_data_list = DRW_drawdatalist_from_id(id);
195  if (draw_data_list == nullptr) {
196  return;
197  }
198  LISTBASE_FOREACH (DrawData *, draw_data, draw_data_list) {
199  draw_data->recalc |= id->recalc;
200  }
201 }
202 
203 /* NOTE: It will also accumulate flags from changed components. */
204 void flush_editors_id_update(Depsgraph *graph, const DEGEditorUpdateContext *update_ctx)
205 {
206  for (IDNode *id_node : graph->id_nodes) {
208  continue;
209  }
210  DEG_graph_id_type_tag(reinterpret_cast<::Depsgraph *>(graph), GS(id_node->id_orig->name));
211  /* TODO(sergey): Do we need to pass original or evaluated ID here? */
212  ID *id_orig = id_node->id_orig;
213  ID *id_cow = id_node->id_cow;
214  /* Gather recalc flags from all changed components. */
215  for (ComponentNode *comp_node : id_node->components.values()) {
216  if (comp_node->custom_flags != COMPONENT_STATE_DONE) {
217  continue;
218  }
219  DepsNodeFactory *factory = type_get_factory(comp_node->type);
220  BLI_assert(factory != nullptr);
221  id_cow->recalc |= factory->id_recalc_tag();
222  }
224  EVAL,
225  "Accumulated recalc bits for %s: %u\n",
226  id_orig->name,
227  (unsigned int)id_cow->recalc);
228 
229  /* Inform editors. Only if the data-block is being evaluated a second
230  * time, to distinguish between user edits and initial evaluation when
231  * the data-block becomes visible.
232  *
233  * TODO: image data-blocks do not use COW, so might not be detected
234  * correctly. */
235  if (deg_copy_on_write_is_expanded(id_cow)) {
237  deg_editors_id_update(update_ctx, id_orig);
238 
239  /* We only want to tag an ID for lib-override auto-refresh if it was actually tagged as
240  * changed. CoW IDs indirectly modified because of changes in other IDs should never
241  * require a lib-override diffing. */
242  if (ID_IS_OVERRIDE_LIBRARY_REAL(id_orig)) {
244  }
245  else if (ID_IS_OVERRIDE_LIBRARY_VIRTUAL(id_orig)) {
246  switch (GS(id_orig->name)) {
247  case ID_KE:
248  ((Key *)id_orig)->from->tag |= LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH;
249  break;
250  case ID_GR:
251  BLI_assert(id_orig->flag & LIB_EMBEDDED_DATA);
252  /* TODO. */
253  break;
254  case ID_NT:
255  BLI_assert(id_orig->flag & LIB_EMBEDDED_DATA);
256  /* TODO. */
257  break;
258  default:
259  BLI_assert(0);
260  }
261  }
262  }
263  /* Inform draw engines that something was changed. */
264  flush_engine_data_update(id_cow);
265  }
266  }
267 }
268 
269 #ifdef INVALIDATE_ON_FLUSH
270 void invalidate_tagged_evaluated_transform(ID *id)
271 {
272  const ID_Type id_type = GS(id->name);
273  switch (id_type) {
274  case ID_OB: {
275  Object *object = (Object *)id;
276  copy_vn_fl((float *)object->obmat, 16, NAN);
277  break;
278  }
279  default:
280  break;
281  }
282 }
283 
284 void invalidate_tagged_evaluated_geometry(ID *id)
285 {
286  const ID_Type id_type = GS(id->name);
287  switch (id_type) {
288  case ID_OB: {
289  Object *object = (Object *)id;
291  break;
292  }
293  default:
294  break;
295  }
296 }
297 #endif
298 
299 void invalidate_tagged_evaluated_data(Depsgraph *graph)
300 {
301 #ifdef INVALIDATE_ON_FLUSH
302  for (IDNode *id_node : graph->id_nodes) {
304  continue;
305  }
306  ID *id_cow = id_node->id_cow;
307  if (!deg_copy_on_write_is_expanded(id_cow)) {
308  continue;
309  }
310  for (ComponentNode *comp_node : id_node->components.values()) {
311  if (comp_node->custom_flags != COMPONENT_STATE_DONE) {
312  continue;
313  }
314  switch (comp_node->type) {
315  case ID_RECALC_TRANSFORM:
316  invalidate_tagged_evaluated_transform(id_cow);
317  break;
318  case ID_RECALC_GEOMETRY:
319  invalidate_tagged_evaluated_geometry(id_cow);
320  break;
321  default:
322  break;
323  }
324  }
325  }
326 #else
327  (void)graph;
328 #endif
329 }
330 
331 } // namespace
332 
334 {
335  /* Sanity checks. */
336  BLI_assert(graph != nullptr);
337  Main *bmain = graph->bmain;
338 
340 
341  /* Nothing to update, early out. */
342  if (graph->entry_tags.is_empty()) {
343  return;
344  }
345  /* Reset all flags, get ready for the flush. */
346  flush_prepare(graph);
347  /* Starting from the tagged "entry" nodes, flush outwards. */
349  flush_schedule_entrypoints(graph, &queue);
350  /* Prepare update context for editors. */
351  DEGEditorUpdateContext update_ctx;
352  update_ctx.bmain = bmain;
353  update_ctx.depsgraph = (::Depsgraph *)graph;
354  update_ctx.scene = graph->scene;
355  update_ctx.view_layer = graph->view_layer;
356  /* Do actual flush. */
357  while (!queue.empty()) {
358  OperationNode *op_node = queue.front();
359  queue.pop_front();
360  while (op_node != nullptr) {
361  /* Tag operation as required for update. */
362  op_node->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
363  /* Inform corresponding ID and component nodes about the change. */
364  ComponentNode *comp_node = op_node->owner;
365  IDNode *id_node = comp_node->owner;
366  flush_handle_id_node(id_node);
367  flush_handle_component_node(id_node, comp_node, &queue);
368  /* Flush to nodes along links. */
369  op_node = flush_schedule_children(op_node, &queue);
370  }
371  }
372  /* Inform editors about all changes. */
373  flush_editors_id_update(graph, &update_ctx);
374  /* Reset evaluation result tagged which is tagged for update to some state
375  * which is obvious to catch. */
376  invalidate_tagged_evaluated_data(graph);
377 }
378 
380 {
381  /* Clear any entry tags which haven't been flushed. */
382  graph->entry_tags.clear();
383 
385 }
386 
387 } // namespace blender::deg
General operations, lookup, etc. for blender objects.
void BKE_object_free_derived_caches(struct Object *ob)
Definition: object.cc:1774
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void copy_vn_fl(float *array_tar, int size, float val)
Definition: math_vector.c:1259
void BLI_task_parallel_range(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:94
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition: BLI_task.h:293
#define ELEM(...)
void DEG_graph_id_type_tag(struct Depsgraph *depsgraph, short id_type)
#define ID_IS_OVERRIDE_LIBRARY_VIRTUAL(_id)
Definition: DNA_ID.h:585
@ ID_RECALC_TRANSFORM
Definition: DNA_ID.h:771
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:791
#define ID_IS_OVERRIDE_LIBRARY_REAL(_id)
Definition: DNA_ID.h:581
@ LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH
Definition: DNA_ID.h:695
@ LIB_EMBEDDED_DATA
Definition: DNA_ID.h:635
ID_Type
Definition: DNA_ID_enums.h:44
@ ID_NT
Definition: DNA_ID_enums.h:68
@ ID_KE
Definition: DNA_ID_enums.h:58
@ ID_GR
Definition: DNA_ID_enums.h:65
@ ID_OB
Definition: DNA_ID_enums.h:47
Object is a sort of wrapper for general info.
struct DrawDataList * DRW_drawdatalist_from_id(struct ID *id)
Definition: draw_manager.c:836
int64_t size() const
Definition: BLI_vector.hh:694
OperationNode * node
Depsgraph * graph
#define DEG_DEBUG_PRINTF(depsgraph, type,...)
Definition: deg_debug.h:51
const IDNode * id_node
SyclQueue * queue
SyclQueue void void size_t num_bytes void
#define GS(x)
Definition: iris.c:225
@ RELATION_FLAG_FLUSH_USER_EDIT_ONLY
void deg_editors_id_update(const DEGEditorUpdateContext *update_ctx, ID *id)
void deg_graph_clear_tags(Depsgraph *graph)
DepsNodeFactory * type_get_factory(const NodeType type)
void deg_graph_flush_updates(Depsgraph *graph)
bool deg_copy_on_write_is_expanded(const ID *id_cow)
deque< OperationNode * > FlushQueue
struct Depsgraph * depsgraph
struct ViewLayer * view_layer
struct Scene * scene
Definition: DNA_ID.h:368
int tag
Definition: DNA_ID.h:387
int recalc
Definition: DNA_ID.h:390
short flag
Definition: DNA_ID.h:383
char name[66]
Definition: DNA_ID.h:378
Definition: BKE_main.h:121
float obmat[4][4]
virtual OperationNode * get_entry_operation() override
Vector< OperationNode * > operations
virtual int id_recalc_tag() const =0
OperationNodes operations
Definition: depsgraph.h:120
ViewLayer * view_layer
Definition: depsgraph.h:129
Set< OperationNode * > entry_tags
Definition: depsgraph.h:114
TimeSourceNode * time_source
Definition: depsgraph.h:89
IDDepsNodes id_nodes
Definition: depsgraph.h:86
Map< ComponentIDKey, ComponentNode * > components
Definition: deg_node_id.h:80
ComponentNode * find_component(NodeType type, const char *name="") const
Definition: deg_node_id.cc:146
Relations outlinks
Definition: deg_node.h:174
virtual string identifier() const override
void flush_update_tag(Depsgraph *graph)