Blender V4.3
depsgraph.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2013 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11#include "intern/depsgraph.hh" /* own include */
12
13#include <algorithm>
14#include <cstring>
15
16#include "MEM_guardedalloc.h"
17
18#include "BLI_console.h"
19#include "BLI_hash.h"
20#include "BLI_utildefines.h"
21
22#include "BKE_global.hh"
23#include "BKE_idtype.hh"
24#include "BKE_scene.hh"
25
26#include "DEG_depsgraph.hh"
28
33
35
42
43namespace deg = blender::deg;
44
45namespace blender::deg {
46
47Depsgraph::Depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluationMode mode)
48 : time_source(nullptr),
49 has_animated_visibility(false),
50 need_update_relations(true),
51 need_update_nodes_visibility(true),
52 need_tag_id_on_graph_visibility_update(true),
53 need_tag_id_on_graph_visibility_time_update(false),
54 bmain(bmain),
55 scene(scene),
56 view_layer(view_layer),
57 mode(mode),
58 frame(BKE_scene_frame_get(scene)),
59 ctime(BKE_scene_ctime_get(scene)),
60 scene_cow(nullptr),
61 is_active(false),
62 use_visibility_optimization(true),
63 is_evaluating(false),
64 is_render_pipeline_depsgraph(false),
65 use_editors_update(false),
66 update_count(0)
67{
69 memset(id_type_updated, 0, sizeof(id_type_updated));
71 memset(id_type_exist, 0, sizeof(id_type_exist));
72 memset(physics_relations, 0, sizeof(physics_relations));
73
75}
76
83
84/* Node Management ---------------------------- */
85
87{
88 if (time_source == nullptr) {
90 time_source = (TimeSourceNode *)factory->create_node(nullptr, "", "Time Source");
91 }
92 return time_source;
93}
94
99
104
106{
107 return id_hash.lookup_default(id, nullptr);
108}
109
111{
112 BLI_assert((id->tag & ID_TAG_COPIED_ON_EVAL) == 0);
114 if (!id_node) {
116 id_node = (IDNode *)factory->create_node(id, "", id->name);
117 id_node->init_copy_on_write(*this, id_cow_hint);
118 /* Register node in ID hash.
119 *
120 * NOTE: We address ID nodes by the original ID pointer they are
121 * referencing to. */
122 id_hash.add_new(id, id_node);
124
126 }
127 return id_node;
128}
129
130template<typename FilterFunc>
131static void clear_id_nodes_conditional(Depsgraph::IDDepsNodes *id_nodes, const FilterFunc &filter)
132{
133 for (IDNode *id_node : *id_nodes) {
134 if (id_node->id_cow == nullptr) {
135 /* This means builder "stole" ownership of the evaluated
136 * datablock for its own dirty needs. */
137 continue;
138 }
139 if (id_node->id_cow == id_node->id_orig) {
140 /* Evaluated copy is not needed for this ID type.
141 *
142 * NOTE: Is important to not de-reference the original datablock here because it might be
143 * freed already (happens during main database free when some IDs are freed prior to a
144 * scene). */
145 continue;
146 }
148 continue;
149 }
150 const ID_Type id_type = GS(id_node->id_cow->name);
151 if (filter(id_type)) {
152 id_node->destroy();
153 }
154 }
155}
156
158{
159 /* Free memory used by ID nodes. */
160
161 /* Stupid workaround to ensure we free IDs in a proper order. */
162 clear_id_nodes_conditional(&id_nodes, [](ID_Type id_type) { return id_type == ID_SCE; });
163 clear_id_nodes_conditional(&id_nodes, [](ID_Type id_type) { return id_type != ID_PA; });
164
165 for (IDNode *id_node : id_nodes) {
166 delete id_node;
167 }
168 /* Clear containers. */
169 id_hash.clear();
170 id_nodes.clear();
171 /* Clear physics relation caches. */
173
175}
176
177Relation *Depsgraph::add_new_relation(Node *from, Node *to, const char *description, int flags)
178{
179 Relation *rel = nullptr;
180 if (flags & RELATION_CHECK_BEFORE_ADD) {
181 rel = check_nodes_connected(from, to, description);
182 }
183 if (rel != nullptr) {
184 rel->flag |= flags;
185 return rel;
186 }
187
188#ifndef NDEBUG
189 if (from->type == NodeType::OPERATION && to->type == NodeType::OPERATION) {
190 OperationNode *operation_from = static_cast<OperationNode *>(from);
191 OperationNode *operation_to = static_cast<OperationNode *>(to);
192 BLI_assert(operation_to->owner->type != NodeType::COPY_ON_EVAL ||
193 operation_from->owner->type == NodeType::COPY_ON_EVAL);
194 }
195#endif
196
197 /* Create new relation, and add it to the graph. */
198 rel = new Relation(from, to, description);
199 rel->flag |= flags;
200 return rel;
201}
202
204 const Node *to,
205 const char *description)
206{
207 for (Relation *rel : from->outlinks) {
208 BLI_assert(rel->from == from);
209 if (rel->to != to) {
210 continue;
211 }
212 if (description != nullptr && !STREQ(rel->name, description)) {
213 continue;
214 }
215 return rel;
216 }
217 return nullptr;
218}
219
220/* Low level tagging -------------------------------------- */
221
223{
224 /* Sanity check. */
225 if (node == nullptr) {
226 return;
227 }
228 /* Add to graph-level set of directly modified nodes to start searching
229 * from.
230 * NOTE: this is necessary since we have several thousand nodes to play
231 * with. */
232 entry_tags.add(node);
233}
234
236{
238 delete time_source;
239 time_source = nullptr;
240}
241
242ID *Depsgraph::get_cow_id(const ID *id_orig) const
243{
244 IDNode *id_node = find_id_node(id_orig);
245 if (id_node == nullptr) {
246 /* This function is used from places where we expect ID to be either
247 * already a copy-on-evaluation version or have a corresponding copy-on-evaluation
248 * version.
249 *
250 * We try to enforce that in debug builds, for release we play a bit
251 * safer game here. */
252 if ((id_orig->tag & ID_TAG_COPIED_ON_EVAL) == 0) {
253 /* TODO(sergey): This is nice sanity check to have, but it fails
254 * in following situations:
255 *
256 * - Material has link to texture, which is not needed by new
257 * shading system and hence can be ignored at construction.
258 * - Object or mesh has material at a slot which is not used (for
259 * example, object has material slot by materials are set to
260 * object data). */
261 // BLI_assert_msg(0, "Request for non-existing copy-on-evaluation ID");
262 }
263 return (ID *)id_orig;
264 }
265 return id_node->id_cow;
266}
267
268} // namespace blender::deg
269
270/* **************** */
271/* Public Graph API */
272
273Depsgraph *DEG_graph_new(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluationMode mode)
274{
275 deg::Depsgraph *deg_depsgraph = new deg::Depsgraph(bmain, scene, view_layer, mode);
276 deg::register_graph(deg_depsgraph);
277 return reinterpret_cast<Depsgraph *>(deg_depsgraph);
278}
279
281 Main *bmain,
282 Scene *scene,
283 ViewLayer *view_layer)
284{
285 deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(depsgraph);
286
287 const bool do_update_register = deg_graph->bmain != bmain;
288 if (do_update_register && deg_graph->bmain != nullptr) {
289 deg::unregister_graph(deg_graph);
290 }
291
292 deg_graph->bmain = bmain;
293 deg_graph->scene = scene;
294 deg_graph->view_layer = view_layer;
295
296 if (do_update_register) {
297 deg::register_graph(deg_graph);
298 }
299}
300
301void DEG_graph_free(Depsgraph *graph)
302{
303 if (graph == nullptr) {
304 return;
305 }
306 using deg::Depsgraph;
307 deg::Depsgraph *deg_depsgraph = reinterpret_cast<deg::Depsgraph *>(graph);
308 deg::unregister_graph(deg_depsgraph);
309 delete deg_depsgraph;
310}
311
312bool DEG_is_evaluating(const Depsgraph *depsgraph)
313{
314 const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(depsgraph);
315 return deg_graph->is_evaluating;
316}
317
318bool DEG_is_active(const Depsgraph *depsgraph)
319{
320 if (depsgraph == nullptr) {
321 /* Happens for such cases as work object in what_does_obaction(),
322 * and sine render pipeline parts. Shouldn't really be accepting
323 * nullptr depsgraph, but is quite hard to get proper one in those
324 * cases. */
325 return false;
326 }
327 const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(depsgraph);
328 return deg_graph->is_active;
329}
330
332{
333 deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(depsgraph);
334 deg_graph->is_active = true;
335 /* TODO(sergey): Copy data from evaluated state to original. */
336}
337
339{
340 deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(depsgraph);
341 deg_graph->is_active = false;
342}
343
345{
346 deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(depsgraph);
347 deg_graph->use_visibility_optimization = false;
348}
349
351{
352 const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(depsgraph);
353 return deg_graph->update_count;
354}
int BKE_idtype_idcode_to_index(short idcode)
Definition idtype.cc:232
float BKE_scene_ctime_get(const Scene *scene)
Definition scene.cc:2317
float BKE_scene_frame_get(const Scene *scene)
Definition scene.cc:2331
#define BLI_assert(a)
Definition BLI_assert.h:50
Set of utility functions and constants to work with consoles.
void BLI_spin_init(SpinLock *spin)
Definition threads.cc:391
void BLI_spin_end(SpinLock *spin)
Definition threads.cc:445
#define STREQ(a, b)
bool DEG_is_evaluating(const Depsgraph *depsgraph)
Definition depsgraph.cc:312
uint64_t DEG_get_update_count(const Depsgraph *depsgraph)
Definition depsgraph.cc:350
void DEG_disable_visibility_optimization(Depsgraph *depsgraph)
Definition depsgraph.cc:344
eEvaluationMode
Depsgraph * DEG_graph_new(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluationMode mode)
Definition depsgraph.cc:273
bool DEG_is_active(const Depsgraph *depsgraph)
Definition depsgraph.cc:318
void DEG_graph_replace_owners(Depsgraph *depsgraph, Main *bmain, Scene *scene, ViewLayer *view_layer)
Definition depsgraph.cc:280
void DEG_graph_free(Depsgraph *graph)
Definition depsgraph.cc:301
void DEG_make_inactive(Depsgraph *depsgraph)
Definition depsgraph.cc:338
void DEG_make_active(Depsgraph *depsgraph)
Definition depsgraph.cc:331
@ ID_TAG_COPIED_ON_EVAL
Definition DNA_ID.h:964
ID_Type
@ ID_SCE
@ ID_PA
Read Guarded memory(de)allocation.
void append(const T &value)
Depsgraph * graph
StackEntry * from
const IDNode * id_node
const Depsgraph * depsgraph
DO_INLINE void filter(lfVector *V, fmatrix3x3 *S)
#define GS(x)
Definition iris.cc:202
bool deg_eval_copy_is_expanded(const ID *id_cow)
static void clear_id_nodes_conditional(Depsgraph::IDDepsNodes *id_nodes, const FilterFunc &filter)
Definition depsgraph.cc:131
void clear_physics_relations(Depsgraph *graph)
DepsNodeFactory * type_get_factory(const NodeType type)
void unregister_graph(Depsgraph *depsgraph)
void register_graph(Depsgraph *depsgraph)
unsigned __int64 uint64_t
Definition stdint.h:90
Definition DNA_ID.h:413
int tag
Definition DNA_ID.h:434
char name[66]
Definition DNA_ID.h:425
virtual Node * create_node(const ID *id, const char *subdata, const char *name) const =0
ID * get_cow_id(const ID *id_orig) const
Definition depsgraph.cc:242
Map< const ID *, ListBase * > * physics_relations[DEG_PHYSICS_RELATIONS_NUM]
Definition depsgraph.hh:174
IDNode * find_id_node(const ID *id) const
Definition depsgraph.cc:105
char id_type_updated[INDEX_ID_MAX]
Definition depsgraph.hh:110
light_linking::Cache light_linking_cache
Definition depsgraph.hh:176
TimeSourceNode * find_time_source() const
Definition depsgraph.cc:95
IDNode * add_id_node(ID *id, ID *id_cow_hint=nullptr)
Definition depsgraph.cc:110
char id_type_updated_backup[INDEX_ID_MAX]
Definition depsgraph.hh:112
Depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluationMode mode)
Definition depsgraph.cc:47
Relation * add_new_relation(Node *from, Node *to, const char *description, int flags=0)
Definition depsgraph.cc:177
char id_type_exist[INDEX_ID_MAX]
Definition depsgraph.hh:115
Map< const ID *, IDNode * > id_hash
Definition depsgraph.hh:85
Relation * check_nodes_connected(const Node *from, const Node *to, const char *description)
Definition depsgraph.cc:203
TimeSourceNode * add_time_source()
Definition depsgraph.cc:86
Set< OperationNode * > entry_tags
Definition depsgraph.hh:120
TimeSourceNode * time_source
Definition depsgraph.hh:93
void add_entry_tag(OperationNode *node)
Definition depsgraph.cc:222
virtual void tag_update(Depsgraph *graph, eUpdateSource source) override