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