Blender V4.3
deg_builder_remove_noop.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2020 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include "MEM_guardedalloc.h"
12
15
17#include "intern/depsgraph.hh"
20
21namespace blender::deg {
22
23static inline bool is_unused_noop(OperationNode *op_node)
24{
25 if (op_node == nullptr) {
26 return false;
27 }
29 return false;
30 }
31 return op_node->is_noop() && op_node->outlinks.is_empty();
32}
33
34static inline bool is_removable_relation(const Relation *relation)
35{
36 if (relation->from->type != NodeType::OPERATION || relation->to->type != NodeType::OPERATION) {
37 return true;
38 }
39
40 const OperationNode *operation_from = static_cast<OperationNode *>(relation->from);
41 const OperationNode *operation_to = static_cast<OperationNode *>(relation->to);
42
43 /* If the relation connects two different IDs there is a high risk that the removal of the
44 * relation will make it so visibility flushing is not possible at runtime. This happens with
45 * relations like the DoF on camera of custom shape on bones: such relation do not lead to an
46 * actual depsgraph evaluation operation as they are handled on render engine level.
47 *
48 * The indirectly linked objects could have some of their components invisible as well, so
49 * also keep relations which connect different components of the same object so that visibility
50 * tracking happens correct in those cases as well. */
51 return operation_from->owner == operation_to->owner;
52}
53
55{
56 deque<OperationNode *> queue;
57
58 for (OperationNode *node : graph->operations) {
59 if (is_unused_noop(node)) {
60 queue.push_back(node);
61 }
62 }
63
64 Vector<Relation *> relations_to_remove;
65
66 while (!queue.empty()) {
67 OperationNode *to_remove = queue.front();
68 queue.pop_front();
69
70 for (Relation *rel_in : to_remove->inlinks) {
71 if (!is_removable_relation(rel_in)) {
72 continue;
73 }
74
75 Node *dependency = rel_in->from;
76 relations_to_remove.append(rel_in);
77
78 /* Queue parent no-op node that has now become unused. */
79 OperationNode *operation = dependency->get_exit_operation();
80 if (is_unused_noop(operation)) {
81 queue.push_back(operation);
82 }
83 }
84
85 /* TODO(Sybren): Remove the node itself. */
86 }
87
88 /* Remove the relations. */
89 for (Relation *relation : relations_to_remove) {
90 relation->unlink();
91 delete relation;
92 }
93
94 DEG_DEBUG_PRINTF((::Depsgraph *)graph,
95 BUILD,
96 "Removed %d relations to no-op nodes\n",
97 int(relations_to_remove.size()));
98}
99
100} // namespace blender::deg
Read Guarded memory(de)allocation.
int64_t size() const
void append(const T &value)
bool is_empty() const
#define DEG_DEBUG_PRINTF(depsgraph, type,...)
Definition deg_debug.h:45
void deg_graph_remove_unused_noops(Depsgraph *graph)
static bool is_removable_relation(const Relation *relation)
static bool is_unused_noop(OperationNode *op_node)
Relations inlinks
Definition deg_node.hh:180
Relations outlinks
Definition deg_node.hh:181
virtual OperationNode * get_exit_operation()
Definition deg_node.hh:205