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