Blender V4.3
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
11#include "BLI_utildefines.h"
12
13#include "DNA_scene_types.h"
14
15#include "DNA_object_types.h"
16
17#include "DEG_depsgraph.hh"
21
23#include "intern/depsgraph.hh"
29
30namespace deg = blender::deg;
31
32void DEG_debug_flags_set(Depsgraph *depsgraph, int flags)
33{
34 deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(depsgraph);
35 deg_graph->debug.flags = flags;
36}
37
38int DEG_debug_flags_get(const Depsgraph *depsgraph)
39{
40 const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(depsgraph);
41 return deg_graph->debug.flags;
42}
43
44void DEG_debug_name_set(Depsgraph *depsgraph, const char *name)
45{
46 deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(depsgraph);
47 deg_graph->debug.name = name;
48}
49
50const char *DEG_debug_name_get(Depsgraph *depsgraph)
51{
52 const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(depsgraph);
53 return deg_graph->debug.name.c_str();
54}
55
56bool DEG_debug_compare(const Depsgraph *graph1, const Depsgraph *graph2)
57{
58 BLI_assert(graph1 != nullptr);
59 BLI_assert(graph2 != nullptr);
60 const deg::Depsgraph *deg_graph1 = reinterpret_cast<const deg::Depsgraph *>(graph1);
61 const deg::Depsgraph *deg_graph2 = reinterpret_cast<const deg::Depsgraph *>(graph2);
62 if (deg_graph1->operations.size() != deg_graph2->operations.size()) {
63 return false;
64 }
65 /* TODO(sergey): Currently we only do real stupid check,
66 * which is fast but which isn't 100% reliable.
67 *
68 * Would be cool to make it more robust, but it's good enough
69 * for now. Also, proper graph check is actually NP-complex
70 * problem. */
71 return true;
72}
73
75 Main *bmain,
76 Scene *scene,
77 ViewLayer *view_layer)
78{
79 Depsgraph *temp_depsgraph = DEG_graph_new(bmain, scene, view_layer, DEG_get_mode(graph));
80 bool valid = true;
81 DEG_graph_build_from_view_layer(temp_depsgraph);
82 if (!DEG_debug_compare(temp_depsgraph, graph)) {
83 fprintf(stderr, "ERROR! Depsgraph wasn't tagged for update when it should have!\n");
84 BLI_assert_msg(0, "This should not happen!");
85 valid = false;
86 }
87 DEG_graph_free(temp_depsgraph);
88 return valid;
89}
90
91bool DEG_debug_consistency_check(Depsgraph *graph)
92{
93 const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(graph);
94 /* Validate links exists in both directions. */
95 for (deg::OperationNode *node : deg_graph->operations) {
96 for (deg::Relation *rel : node->outlinks) {
97 int counter1 = 0;
98 for (deg::Relation *tmp_rel : node->outlinks) {
99 if (tmp_rel == rel) {
100 counter1++;
101 }
102 }
103 int counter2 = 0;
104 for (deg::Relation *tmp_rel : rel->to->inlinks) {
105 if (tmp_rel == rel) {
106 counter2++;
107 }
108 }
109 if (counter1 != counter2) {
110 printf(
111 "Relation exists in outgoing direction but not in "
112 "incoming (%d vs. %d).\n",
113 counter1,
114 counter2);
115 return false;
116 }
117 }
118 }
119
120 for (deg::OperationNode *node : deg_graph->operations) {
121 for (deg::Relation *rel : node->inlinks) {
122 int counter1 = 0;
123 for (deg::Relation *tmp_rel : node->inlinks) {
124 if (tmp_rel == rel) {
125 counter1++;
126 }
127 }
128 int counter2 = 0;
129 for (deg::Relation *tmp_rel : rel->from->outlinks) {
130 if (tmp_rel == rel) {
131 counter2++;
132 }
133 }
134 if (counter1 != counter2) {
135 printf("Relation exists in incoming direction but not in outcoming (%d vs. %d).\n",
136 counter1,
137 counter2);
138 }
139 }
140 }
141
142 /* Validate node valency calculated in both directions. */
143 for (deg::OperationNode *node : deg_graph->operations) {
144 node->num_links_pending = 0;
145 node->custom_flags = 0;
146 }
147
148 for (deg::OperationNode *node : deg_graph->operations) {
149 if (node->custom_flags) {
150 printf("Node %s is twice in the operations!\n", node->identifier().c_str());
151 return false;
152 }
153 for (deg::Relation *rel : node->outlinks) {
154 if (rel->to->type == deg::NodeType::OPERATION) {
155 deg::OperationNode *to = (deg::OperationNode *)rel->to;
156 BLI_assert(to->num_links_pending < to->inlinks.size());
157 ++to->num_links_pending;
158 }
159 }
160 node->custom_flags = 1;
161 }
162
163 for (deg::OperationNode *node : deg_graph->operations) {
164 int num_links_pending = 0;
165 for (deg::Relation *rel : node->inlinks) {
166 if (rel->from->type == deg::NodeType::OPERATION) {
167 num_links_pending++;
168 }
169 }
170 if (node->num_links_pending != num_links_pending) {
171 printf("Valency mismatch: %s, %u != %d\n",
172 node->identifier().c_str(),
173 node->num_links_pending,
174 num_links_pending);
175 printf("Number of inlinks: %d\n", int(node->inlinks.size()));
176 return false;
177 }
178 }
179 return true;
180}
181
182/* ------------------------------------------------ */
183
184void DEG_stats_simple(const Depsgraph *graph,
185 size_t *r_outer,
186 size_t *r_operations,
187 size_t *r_relations)
188{
189 const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(graph);
190
191 /* number of operations */
192 if (r_operations) {
193 /* All operations should be in this list, allowing us to count the total
194 * number of nodes. */
195 *r_operations = deg_graph->operations.size();
196 }
197
198 /* Count number of outer nodes and/or relations between these. */
199 if (r_outer || r_relations) {
200 size_t tot_outer = 0;
201 size_t tot_rels = 0;
202
203 for (deg::IDNode *id_node : deg_graph->id_nodes) {
204 tot_outer++;
205 for (deg::ComponentNode *comp_node : id_node->components.values()) {
206 tot_outer++;
207 for (deg::OperationNode *op_node : comp_node->operations) {
208 tot_rels += op_node->inlinks.size();
209 }
210 }
211 }
212
213 deg::TimeSourceNode *time_source = deg_graph->find_time_source();
214 if (time_source != nullptr) {
215 tot_rels += time_source->inlinks.size();
216 }
217
218 if (r_relations) {
219 *r_relations = tot_rels;
220 }
221 if (r_outer) {
222 *r_outer = tot_outer;
223 }
224 }
225}
226
227static deg::string depsgraph_name_for_logging(Depsgraph *depsgraph)
228{
229 const char *name = DEG_debug_name_get(depsgraph);
230 if (name[0] == '\0') {
231 return "";
232 }
233 return "[" + deg::string(name) + "]: ";
234}
235
237{
238 fprintf(stdout, "%s", depsgraph_name_for_logging(depsgraph).c_str());
239}
240
242 const char *function_name,
243 const char *object_name,
244 const void *object_address)
245{
247 return;
248 }
249 fprintf(stdout,
250 "%s%s on %s %s(%p)%s\n",
252 function_name,
253 object_name,
254 deg::color_for_pointer(object_address).c_str(),
255 object_address,
256 deg::color_end().c_str());
257 fflush(stdout);
258}
259
261 const char *function_name,
262 const char *object_name,
263 const void *object_address,
264 const char *subdata_comment,
265 const char *subdata_name,
266 const void *subdata_address)
267{
269 return;
270 }
271 fprintf(stdout,
272 "%s%s on %s %s(%p)%s %s %s %s(%p)%s\n",
274 function_name,
275 object_name,
276 deg::color_for_pointer(object_address).c_str(),
277 object_address,
278 deg::color_end().c_str(),
279 subdata_comment,
280 subdata_name,
281 deg::color_for_pointer(subdata_address).c_str(),
282 subdata_address,
283 deg::color_end().c_str());
284 fflush(stdout);
285}
286
288 const char *function_name,
289 const char *object_name,
290 const void *object_address,
291 const char *subdata_comment,
292 const char *subdata_name,
293 const void *subdata_address,
294 const int subdata_index)
295{
297 return;
298 }
299 fprintf(stdout,
300 "%s%s on %s %s(%p)%s %s %s[%d] %s(%p)%s\n",
302 function_name,
303 object_name,
304 deg::color_for_pointer(object_address).c_str(),
305 object_address,
306 deg::color_end().c_str(),
307 subdata_comment,
308 subdata_name,
309 subdata_index,
310 deg::color_for_pointer(subdata_address).c_str(),
311 subdata_address,
312 deg::color_end().c_str());
313 fflush(stdout);
314}
315
317 const char *function_name,
318 const char *object_name,
319 const void *object_address,
320 const char *parent_comment,
321 const char *parent_name,
322 const void *parent_address)
323{
325 return;
326 }
327 fprintf(stdout,
328 "%s%s on %s %s(%p) [%s] %s %s %s(%p)%s\n",
330 function_name,
331 object_name,
332 deg::color_for_pointer(object_address).c_str(),
333 object_address,
334 deg::color_end().c_str(),
335 parent_comment,
336 parent_name,
337 deg::color_for_pointer(parent_address).c_str(),
338 parent_address,
339 deg::color_end().c_str());
340 fflush(stdout);
341}
342
344 const char *function_name,
345 const char *object_name,
346 const void *object_address,
347 float time)
348{
350 return;
351 }
352 fprintf(stdout,
353 "%s%s on %s %s(%p)%s at time %f\n",
355 function_name,
356 object_name,
357 deg::color_for_pointer(object_address).c_str(),
358 object_address,
359 deg::color_end().c_str(),
360 time);
361 fflush(stdout);
362}
@ G_DEBUG_DEPSGRAPH_EVAL
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
Depsgraph * DEG_graph_new(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluationMode mode)
Definition depsgraph.cc:273
void DEG_graph_free(Depsgraph *graph)
Definition depsgraph.cc:301
void DEG_graph_build_from_view_layer(Depsgraph *graph)
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
Object is a sort of wrapper for general info.
int64_t size() const
#define printf
Depsgraph * graph
const IDNode * id_node
const Depsgraph * depsgraph
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)
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)
void DEG_stats_simple(const Depsgraph *graph, size_t *r_outer, size_t *r_operations, size_t *r_relations)
static deg::string depsgraph_name_for_logging(Depsgraph *depsgraph)
string color_for_pointer(const void *pointer)
Definition deg_debug.cc:63
string color_end()
Definition deg_debug.cc:75
TimeSourceNode * find_time_source() const
Definition depsgraph.cc:95
OperationNodes operations
Definition depsgraph.hh:126
DepsgraphDebug debug
Definition depsgraph.hh:159
Relations inlinks
Definition deg_node.hh:180