83fc756654f7452786812047eac0c73825ed56d5
[blender.git] / source / blender / depsgraph / intern / eval / deg_eval_flush.cc
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2013 Blender Foundation.
19  * All rights reserved.
20  *
21  * Original Author: Joshua Leung
22  * Contributor(s): None Yet
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/depsgraph/intern/eval/deg_eval_flush.cc
28  *  \ingroup depsgraph
29  *
30  * Core routines for how the Depsgraph works.
31  */
32
33 #include "intern/eval/deg_eval_flush.h"
34
35 // TODO(sergey): Use some sort of wrapper.
36 #include <deque>
37
38 #include "BLI_utildefines.h"
39 #include "BLI_task.h"
40 #include "BLI_ghash.h"
41
42 extern "C" {
43 #include "DNA_object_types.h"
44 } /* extern "C" */
45
46 #include "DEG_depsgraph.h"
47
48 #include "intern/nodes/deg_node.h"
49 #include "intern/nodes/deg_node_component.h"
50 #include "intern/nodes/deg_node_operation.h"
51
52 #include "intern/depsgraph_intern.h"
53 #include "util/deg_util_foreach.h"
54
55 namespace DEG {
56
57 enum {
58         COMPONENT_STATE_NONE      = 0,
59         COMPONENT_STATE_SCHEDULED = 1,
60         COMPONENT_STATE_DONE      = 2,
61 };
62
63 namespace {
64
65 // TODO(sergey): De-duplicate with depsgraph_tag,cc
66 void lib_id_recalc_tag(Main *bmain, ID *id)
67 {
68         id->tag |= LIB_TAG_ID_RECALC;
69         DEG_id_type_tag(bmain, GS(id->name));
70 }
71
72 void lib_id_recalc_data_tag(Main *bmain, ID *id)
73 {
74         id->tag |= LIB_TAG_ID_RECALC_DATA;
75         DEG_id_type_tag(bmain, GS(id->name));
76 }
77
78 }  /* namespace */
79
80 typedef std::deque<OperationDepsNode *> FlushQueue;
81
82 static void flush_init_func(void *data_v, int i)
83 {
84         /* ID node's done flag is used to avoid multiple editors update
85          * for the same ID.
86          */
87         Depsgraph *graph = (Depsgraph *)data_v;
88         OperationDepsNode *node = graph->operations[i];
89         ComponentDepsNode *comp_node = node->owner;
90         IDDepsNode *id_node = comp_node->owner;
91         id_node->done = 0;
92         comp_node->done = COMPONENT_STATE_NONE;
93         node->scheduled = false;
94 }
95
96 /* Flush updates from tagged nodes outwards until all affected nodes
97  * are tagged.
98  */
99 void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
100 {
101         /* Sanity check. */
102         if (graph == NULL) {
103                 return;
104         }
105
106         /* Nothing to update, early out. */
107         if (BLI_gset_size(graph->entry_tags) == 0) {
108                 return;
109         }
110
111         /* TODO(sergey): With a bit of flag magic we can get rid of this
112          * extra loop.
113          */
114         const int num_operations = graph->operations.size();
115         const bool do_threads = num_operations > 256;
116         BLI_task_parallel_range(0,
117                                 num_operations,
118                                 graph,
119                                 flush_init_func,
120                                 do_threads);
121
122         FlushQueue queue;
123         /* Starting from the tagged "entry" nodes, flush outwards... */
124         /* NOTE: Also need to ensure that for each of these, there is a path back to
125          *       root, or else they won't be done.
126          * NOTE: Count how many nodes we need to handle - entry nodes may be
127          *       component nodes which don't count for this purpose!
128          */
129         GSET_FOREACH_BEGIN(OperationDepsNode *, node, graph->entry_tags)
130         {
131                 queue.push_back(node);
132                 node->scheduled = true;
133         }
134         GSET_FOREACH_END();
135
136         int num_flushed_objects = 0;
137         while (!queue.empty()) {
138                 OperationDepsNode *node = queue.front();
139                 queue.pop_front();
140
141                 for (;;) {
142                         node->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
143
144                         ComponentDepsNode *comp_node = node->owner;
145                         IDDepsNode *id_node = comp_node->owner;
146
147                         ID *id = id_node->id;
148                         if (id_node->done == 0) {
149                                 deg_editors_id_update(bmain, id);
150                                 lib_id_recalc_tag(bmain, id);
151                                 /* TODO(sergey): For until we've got proper data nodes in the graph. */
152                                 lib_id_recalc_data_tag(bmain, id);
153                         }
154
155                         if (comp_node->done != COMPONENT_STATE_DONE) {
156                                 Object *object = NULL;
157                                 if (GS(id->name) == ID_OB) {
158                                         object = (Object *)id;
159                                         if (id_node->done == 0) {
160                                                 ++num_flushed_objects;
161                                         }
162                                 }
163                                 foreach (OperationDepsNode *op, comp_node->operations) {
164                                         op->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
165                                 }
166                                 if (object != NULL) {
167                                         /* This code is used to preserve those areas which does
168                                          * direct object update,
169                                          *
170                                          * Plus it ensures visibility changes and relations and
171                                          * layers visibility update has proper flags to work with.
172                                          */
173                                         switch (comp_node->type) {
174                                                 case DEG_NODE_TYPE_UNDEFINED:
175                                                 case DEG_NODE_TYPE_OPERATION:
176                                                 case DEG_NODE_TYPE_TIMESOURCE:
177                                                 case DEG_NODE_TYPE_ID_REF:
178                                                 case DEG_NODE_TYPE_PARAMETERS:
179                                                 case DEG_NODE_TYPE_SEQUENCER:
180                                                         /* Ignore, does not translate to object component. */
181                                                         BLI_assert(!"This should never happen!");
182                                                         break;
183                                                 case DEG_NODE_TYPE_ANIMATION:
184                                                         object->recalc |= OB_RECALC_TIME;
185                                                         break;
186                                                 case DEG_NODE_TYPE_TRANSFORM:
187                                                         object->recalc |= OB_RECALC_OB;
188                                                         break;
189                                                 case DEG_NODE_TYPE_GEOMETRY:
190                                                 case DEG_NODE_TYPE_EVAL_POSE:
191                                                 case DEG_NODE_TYPE_BONE:
192                                                 case DEG_NODE_TYPE_EVAL_PARTICLES:
193                                                 case DEG_NODE_TYPE_SHADING:
194                                                 case DEG_NODE_TYPE_CACHE:
195                                                 case DEG_NODE_TYPE_PROXY:
196                                                         object->recalc |= OB_RECALC_DATA;
197                                                         break;
198                                         }
199                                 }
200                                 /* When some target changes bone, we might need to re-run the
201                                  * whole IK solver, otherwise result might be unpredictable.
202                                  */
203                                 if (comp_node->type == DEG_NODE_TYPE_BONE) {
204                                         ComponentDepsNode *pose_comp =
205                                                 id_node->find_component(DEG_NODE_TYPE_EVAL_POSE);
206                                         BLI_assert(pose_comp != NULL);
207                                         if (pose_comp->done == COMPONENT_STATE_NONE) {
208                                                 queue.push_front(pose_comp->get_entry_operation());
209                                                 pose_comp->done = COMPONENT_STATE_SCHEDULED;
210                                         }
211                                 }
212                         }
213
214                         id_node->done = 1;
215                         comp_node->done = COMPONENT_STATE_DONE;
216
217                         /* Flush to nodes along links... */
218                         /* TODO(sergey): This is mainly giving speedup due ot less queue pushes, which
219                          * reduces number of memory allocations.
220                          *
221                          * We should try solve the allocation issue instead of doing crazy things here.
222                          */
223                         if (node->outlinks.size() == 1) {
224                                 OperationDepsNode *to_node = (OperationDepsNode *)node->outlinks[0]->to;
225                                 if (to_node->scheduled == false) {
226                                         to_node->scheduled = true;
227                                         node = to_node;
228                                 }
229                                 else {
230                                         break;
231                                 }
232                         }
233                         else {
234                                 foreach (DepsRelation *rel, node->outlinks) {
235                                         OperationDepsNode *to_node = (OperationDepsNode *)rel->to;
236                                         if (to_node->scheduled == false) {
237                                                 queue.push_front(to_node);
238                                                 to_node->scheduled = true;
239                                         }
240                                 }
241                                 break;
242                         }
243                 }
244         }
245         DEG_DEBUG_PRINTF("Update flushed to %d objects\n", num_flushed_objects);
246 }
247
248 static void graph_clear_func(void *data_v, int i)
249 {
250         Depsgraph *graph = (Depsgraph *)data_v;
251         OperationDepsNode *node = graph->operations[i];
252         /* Clear node's "pending update" settings. */
253         node->flag &= ~(DEPSOP_FLAG_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE);
254 }
255
256 /* Clear tags from all operation nodes. */
257 void deg_graph_clear_tags(Depsgraph *graph)
258 {
259         /* Go over all operation nodes, clearing tags. */
260         const int num_operations = graph->operations.size();
261         const bool do_threads = num_operations > 256;
262         BLI_task_parallel_range(0, num_operations, graph, graph_clear_func, do_threads);
263         /* Clear any entry tags which haven't been flushed. */
264         BLI_gset_clear(graph->entry_tags, NULL);
265 }
266
267 }  // namespace DEG