Blender V5.0
depsgraph_debug.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2014 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include "DNA_scene_types.h"
12
13#include "BKE_global.hh"
14
15#include "DEG_depsgraph.hh"
19
21#include "intern/depsgraph.hh"
26
27#include "BLI_math_bits.h"
28
29namespace deg = blender::deg;
30
31void DEG_debug_flags_set(Depsgraph *depsgraph, int flags)
32{
33 deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(depsgraph);
34 deg_graph->debug.flags = flags;
35}
36
37int DEG_debug_flags_get(const Depsgraph *depsgraph)
38{
39 const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(depsgraph);
40 return deg_graph->debug.flags;
41}
42
43void DEG_debug_name_set(Depsgraph *depsgraph, const char *name)
44{
45 deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(depsgraph);
46 deg_graph->debug.name = name;
47}
48
49const char *DEG_debug_name_get(Depsgraph *depsgraph)
50{
51 const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(depsgraph);
52 return deg_graph->debug.name.c_str();
53}
54
55bool DEG_debug_compare(const Depsgraph *graph1, const Depsgraph *graph2)
56{
57 BLI_assert(graph1 != nullptr);
58 BLI_assert(graph2 != nullptr);
59 const deg::Depsgraph *deg_graph1 = reinterpret_cast<const deg::Depsgraph *>(graph1);
60 const deg::Depsgraph *deg_graph2 = reinterpret_cast<const deg::Depsgraph *>(graph2);
61 if (deg_graph1->operations.size() != deg_graph2->operations.size()) {
62 return false;
63 }
64 /* TODO(sergey): Currently we only do real stupid check,
65 * which is fast but which isn't 100% reliable.
66 *
67 * Would be cool to make it more robust, but it's good enough
68 * for now. Also, proper graph check is actually NP-complex
69 * problem. */
70 return true;
71}
72
74 Main *bmain,
75 Scene *scene,
76 ViewLayer *view_layer)
77{
78 Depsgraph *temp_depsgraph = DEG_graph_new(bmain, scene, view_layer, DEG_get_mode(graph));
79 bool valid = true;
80 DEG_graph_build_from_view_layer(temp_depsgraph);
81 if (!DEG_debug_compare(temp_depsgraph, graph)) {
82 fprintf(stderr, "ERROR! Depsgraph wasn't tagged for update when it should have!\n");
83 BLI_assert_msg(0, "This should not happen!");
84 valid = false;
85 }
86 DEG_graph_free(temp_depsgraph);
87 return valid;
88}
89
90bool DEG_debug_consistency_check(Depsgraph *graph)
91{
92 const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(graph);
93 /* Validate links exists in both directions. */
94 for (deg::OperationNode *node : deg_graph->operations) {
95 for (deg::Relation *rel : node->outlinks) {
96 int counter1 = 0;
97 for (deg::Relation *tmp_rel : node->outlinks) {
98 if (tmp_rel == rel) {
99 counter1++;
100 }
101 }
102 int counter2 = 0;
103 for (deg::Relation *tmp_rel : rel->to->inlinks) {
104 if (tmp_rel == rel) {
105 counter2++;
106 }
107 }
108 if (counter1 != counter2) {
109 printf(
110 "Relation exists in outgoing direction but not in "
111 "incoming (%d vs. %d).\n",
112 counter1,
113 counter2);
114 return false;
115 }
116 }
117 }
118
119 for (deg::OperationNode *node : deg_graph->operations) {
120 for (deg::Relation *rel : node->inlinks) {
121 int counter1 = 0;
122 for (deg::Relation *tmp_rel : node->inlinks) {
123 if (tmp_rel == rel) {
124 counter1++;
125 }
126 }
127 int counter2 = 0;
128 for (deg::Relation *tmp_rel : rel->from->outlinks) {
129 if (tmp_rel == rel) {
130 counter2++;
131 }
132 }
133 if (counter1 != counter2) {
134 printf("Relation exists in incoming direction but not in outcoming (%d vs. %d).\n",
135 counter1,
136 counter2);
137 }
138 }
139 }
140
141 /* Validate node valency calculated in both directions. */
142 for (deg::OperationNode *node : deg_graph->operations) {
143 node->num_links_pending = 0;
144 node->custom_flags = 0;
145 }
146
147 for (deg::OperationNode *node : deg_graph->operations) {
148 if (node->custom_flags) {
149 printf("Node %s is twice in the operations!\n", node->identifier().c_str());
150 return false;
151 }
152 for (deg::Relation *rel : node->outlinks) {
153 if (rel->to->type == deg::NodeType::OPERATION) {
156 ++to->num_links_pending;
157 }
158 }
159 node->custom_flags = 1;
160 }
161
162 for (deg::OperationNode *node : deg_graph->operations) {
163 int num_links_pending = 0;
164 for (deg::Relation *rel : node->inlinks) {
165 if (rel->from->type == deg::NodeType::OPERATION) {
166 num_links_pending++;
167 }
168 }
169 if (node->num_links_pending != num_links_pending) {
170 printf("Valency mismatch: %s, %u != %d\n",
171 node->identifier().c_str(),
172 node->num_links_pending,
173 num_links_pending);
174 printf("Number of inlinks: %d\n", int(node->inlinks.size()));
175 return false;
176 }
177 }
178 return true;
179}
180
181/* ------------------------------------------------ */
182
183void DEG_stats_simple(const Depsgraph *graph,
184 size_t *r_outer,
185 size_t *r_operations,
186 size_t *r_relations)
187{
188 const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(graph);
189
190 /* number of operations */
191 if (r_operations) {
192 /* All operations should be in this list, allowing us to count the total
193 * number of nodes. */
194 *r_operations = deg_graph->operations.size();
195 }
196
197 /* Count number of outer nodes and/or relations between these. */
198 if (r_outer || r_relations) {
199 size_t tot_outer = 0;
200 size_t tot_rels = 0;
201
202 for (deg::IDNode *id_node : deg_graph->id_nodes) {
203 tot_outer++;
204 for (deg::ComponentNode *comp_node : id_node->components.values()) {
205 tot_outer++;
206 for (deg::OperationNode *op_node : comp_node->operations) {
207 tot_rels += op_node->inlinks.size();
208 }
209 }
210 }
211
212 deg::TimeSourceNode *time_source = deg_graph->find_time_source();
213 if (time_source != nullptr) {
214 tot_rels += time_source->inlinks.size();
215 }
216
217 if (r_relations) {
218 *r_relations = tot_rels;
219 }
220 if (r_outer) {
221 *r_outer = tot_outer;
222 }
223 }
224}
225
226static std::string depsgraph_name_for_logging(Depsgraph *depsgraph)
227{
228 const char *name = DEG_debug_name_get(depsgraph);
229 if (name[0] == '\0') {
230 return "";
231 }
232 return "[" + std::string(name) + "]: ";
233}
234
236{
237 fprintf(stdout, "%s", depsgraph_name_for_logging(depsgraph).c_str());
238}
239
241 const char *function_name,
242 const char *object_name,
243 const void *object_address)
244{
246 return;
247 }
248 fprintf(stdout,
249 "%s%s on %s %s(%p)%s\n",
251 function_name,
252 object_name,
253 deg::color_for_pointer(object_address).c_str(),
254 object_address,
255 deg::color_end().c_str());
256 fflush(stdout);
257}
258
260 const char *function_name,
261 const char *object_name,
262 const void *object_address,
263 const char *subdata_comment,
264 const char *subdata_name,
265 const void *subdata_address)
266{
268 return;
269 }
270 fprintf(stdout,
271 "%s%s on %s %s(%p)%s %s %s %s(%p)%s\n",
273 function_name,
274 object_name,
275 deg::color_for_pointer(object_address).c_str(),
276 object_address,
277 deg::color_end().c_str(),
278 subdata_comment,
279 subdata_name,
280 deg::color_for_pointer(subdata_address).c_str(),
281 subdata_address,
282 deg::color_end().c_str());
283 fflush(stdout);
284}
285
287 const char *function_name,
288 const char *object_name,
289 const void *object_address,
290 const char *subdata_comment,
291 const char *subdata_name,
292 const void *subdata_address,
293 const int subdata_index)
294{
296 return;
297 }
298 fprintf(stdout,
299 "%s%s on %s %s(%p)%s %s %s[%d] %s(%p)%s\n",
301 function_name,
302 object_name,
303 deg::color_for_pointer(object_address).c_str(),
304 object_address,
305 deg::color_end().c_str(),
306 subdata_comment,
307 subdata_name,
308 subdata_index,
309 deg::color_for_pointer(subdata_address).c_str(),
310 subdata_address,
311 deg::color_end().c_str());
312 fflush(stdout);
313}
314
316 const char *function_name,
317 const char *object_name,
318 const void *object_address,
319 const char *parent_comment,
320 const char *parent_name,
321 const void *parent_address)
322{
324 return;
325 }
326 fprintf(stdout,
327 "%s%s on %s %s(%p) [%s] %s %s %s(%p)%s\n",
329 function_name,
330 object_name,
331 deg::color_for_pointer(object_address).c_str(),
332 object_address,
333 deg::color_end().c_str(),
334 parent_comment,
335 parent_name,
336 deg::color_for_pointer(parent_address).c_str(),
337 parent_address,
338 deg::color_end().c_str());
339 fflush(stdout);
340}
341
343 const char *function_name,
344 const char *object_name,
345 const void *object_address,
346 float time)
347{
349 return;
350 }
351 fprintf(stdout,
352 "%s%s on %s %s(%p)%s at time %f\n",
354 function_name,
355 object_name,
356 deg::color_for_pointer(object_address).c_str(),
357 object_address,
358 deg::color_end().c_str(),
359 time);
360 fflush(stdout);
361}
362
363static std::string stringify_append_bit(const std::string &str, IDRecalcFlag tag)
364{
365 const char *tag_name = DEG_update_tag_as_string(tag);
366 if (tag_name == nullptr) {
367 return str;
368 }
369 std::string result = str;
370 if (!result.empty()) {
371 result += ", ";
372 }
373 result += tag_name;
374 return result;
375}
376
378{
379 if (flags == 0) {
380 return "NONE";
381 }
382 std::string result;
383 uint current_flag = flags;
384 /* Special cases to avoid ALL flags from being split into individual bits. */
385 if ((current_flag & ID_RECALC_PSYS_ALL) == ID_RECALC_PSYS_ALL) {
387 }
388 /* Handle all the rest of the flags. */
389 while (current_flag != 0) {
390 IDRecalcFlag tag = (IDRecalcFlag)(1 << bitscan_forward_clear_uint(&current_flag));
392 }
393 return result;
394}
@ G_DEBUG_DEPSGRAPH_EVAL
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
MINLINE unsigned int bitscan_forward_clear_uint(unsigned int *a)
unsigned int uint
Depsgraph * DEG_graph_new(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluationMode mode)
Definition depsgraph.cc:278
void DEG_graph_free(Depsgraph *graph)
Definition depsgraph.cc:306
const char * DEG_update_tag_as_string(IDRecalcFlag flag)
void DEG_graph_build_from_view_layer(Depsgraph *graph)
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
IDRecalcFlag
Definition DNA_ID.h:1049
@ ID_RECALC_PSYS_ALL
Definition DNA_ID.h:1191
BPy_StructRNA * depsgraph
int64_t size() const
void DEG_debug_print_eval_parent_typed(Depsgraph *depsgraph, const char *function_name, const char *object_name, const void *object_address, const char *parent_comment, const char *parent_name, const void *parent_address)
void DEG_debug_flags_set(Depsgraph *depsgraph, int flags)
void DEG_debug_print_eval_time(Depsgraph *depsgraph, const char *function_name, const char *object_name, const void *object_address, float time)
static std::string stringify_append_bit(const std::string &str, IDRecalcFlag tag)
void DEG_debug_print_eval_subdata(Depsgraph *depsgraph, const char *function_name, const char *object_name, const void *object_address, const char *subdata_comment, const char *subdata_name, const void *subdata_address)
int DEG_debug_flags_get(const Depsgraph *depsgraph)
bool DEG_debug_compare(const Depsgraph *graph1, const Depsgraph *graph2)
bool DEG_debug_consistency_check(Depsgraph *graph)
void DEG_debug_print_begin(Depsgraph *depsgraph)
bool DEG_debug_graph_relations_validate(Depsgraph *graph, Main *bmain, Scene *scene, ViewLayer *view_layer)
void DEG_debug_print_eval(Depsgraph *depsgraph, const char *function_name, const char *object_name, const void *object_address)
void DEG_debug_print_eval_subdata_index(Depsgraph *depsgraph, const char *function_name, const char *object_name, const void *object_address, const char *subdata_comment, const char *subdata_name, const void *subdata_address, const int subdata_index)
const char * DEG_debug_name_get(Depsgraph *depsgraph)
void DEG_debug_name_set(Depsgraph *depsgraph, const char *name)
std::string DEG_stringify_recalc_flags(uint flags)
static std::string depsgraph_name_for_logging(Depsgraph *depsgraph)
void DEG_stats_simple(const Depsgraph *graph, size_t *r_outer, size_t *r_operations, size_t *r_relations)
#define str(s)
#define printf(...)
std::string color_end()
Definition deg_debug.cc:72
std::string color_for_pointer(const void *pointer)
Definition deg_debug.cc:60
const char * name
TimeSourceNode * find_time_source() const
Definition depsgraph.cc:91
OperationNodes operations
Definition depsgraph.hh:133
DepsgraphDebug debug
Definition depsgraph.hh:166
Map< ComponentIDKey, ComponentNode * > components
Relations inlinks
Definition deg_node.hh:182
Relations outlinks
Definition deg_node.hh:183
std::string identifier() const override