Depsgraph: Fix bug introduced by wrong merge conflict resolution
[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 "intern/eval/deg_eval_copy_on_write.h"
54 #include "util/deg_util_foreach.h"
55
56 namespace DEG {
57
58 enum {
59         COMPONENT_STATE_NONE      = 0,
60         COMPONENT_STATE_SCHEDULED = 1,
61         COMPONENT_STATE_DONE      = 2,
62 };
63
64 typedef std::deque<OperationDepsNode *> FlushQueue;
65
66 static void flush_init_func(void *data_v, int i)
67 {
68         /* ID node's done flag is used to avoid multiple editors update
69          * for the same ID.
70          */
71         Depsgraph *graph = (Depsgraph *)data_v;
72         OperationDepsNode *node = graph->operations[i];
73         ComponentDepsNode *comp_node = node->owner;
74         IDDepsNode *id_node = comp_node->owner;
75         id_node->done = 0;
76         comp_node->done = COMPONENT_STATE_NONE;
77         node->scheduled = false;
78 }
79
80 /* Flush updates from tagged nodes outwards until all affected nodes
81  * are tagged.
82  */
83 void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
84 {
85         /* Sanity check. */
86         if (graph == NULL) {
87                 return;
88         }
89
90         /* Nothing to update, early out. */
91         if (BLI_gset_size(graph->entry_tags) == 0) {
92                 return;
93         }
94
95         /* TODO(sergey): With a bit of flag magic we can get rid of this
96          * extra loop.
97          */
98         const int num_operations = graph->operations.size();
99         const bool do_threads = num_operations > 256;
100         BLI_task_parallel_range(0,
101                                 num_operations,
102                                 graph,
103                                 flush_init_func,
104                                 do_threads);
105
106         FlushQueue queue;
107         /* Starting from the tagged "entry" nodes, flush outwards... */
108         /* NOTE: Also need to ensure that for each of these, there is a path back to
109          *       root, or else they won't be done.
110          * NOTE: Count how many nodes we need to handle - entry nodes may be
111          *       component nodes which don't count for this purpose!
112          */
113         GSET_FOREACH_BEGIN(OperationDepsNode *, op_node, graph->entry_tags)
114         {
115                 queue.push_back(op_node);
116                 op_node->scheduled = true;
117         }
118         GSET_FOREACH_END();
119
120         int num_flushed_objects = 0;
121         while (!queue.empty()) {
122                 OperationDepsNode *node = queue.front();
123                 queue.pop_front();
124
125                 for (;;) {
126                         node->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
127
128                         ComponentDepsNode *comp_node = node->owner;
129                         IDDepsNode *id_node = comp_node->owner;
130
131                         /* TODO(sergey): Do we need to pass original or evaluated ID here? */
132                         ID *id_orig = id_node->id_orig;
133                         ID *id_cow = id_node->id_cow;
134                         if (id_node->done == 0) {
135                                 /* Copy tag from original data to CoW storage.
136                                  * This is because DEG_id_tag_update() sets tags on original
137                                  * data.
138                                  */
139                                 id_cow->tag |= (id_orig->tag & LIB_TAG_ID_RECALC_ALL);
140                                 if (deg_copy_on_write_is_expanded(id_cow)) {
141                                         deg_editors_id_update(bmain, id_cow);
142                                 }
143                                 lib_id_recalc_tag(bmain, id_orig);
144                                 /* TODO(sergey): For until we've got proper data nodes in the graph. */
145                                 lib_id_recalc_data_tag(bmain, id_orig);
146                         }
147
148                         if (comp_node->done != COMPONENT_STATE_DONE) {
149 #ifdef WITH_COPY_ON_WRITE
150                                 /* Currently this is needed to get ob->mesh to be replaced with
151                                  * original mesh (rather than being evaluated_mesh).
152                                  *
153                                  * TODO(sergey): This is something we need to avoid.
154                                  */
155                                 if (comp_node->depends_on_cow()) {
156                                         ComponentDepsNode *cow_comp =
157                                                 id_node->find_component(DEG_NODE_TYPE_COPY_ON_WRITE);
158                                         cow_comp->tag_update(graph);
159                                 }
160 #endif
161                                 Object *object = NULL;
162                                 if (GS(id_orig->name) == ID_OB) {
163                                         object = (Object *)id_orig;
164                                         if (id_node->done == 0) {
165                                                 ++num_flushed_objects;
166                                         }
167                                 }
168                                 foreach (OperationDepsNode *op, comp_node->operations) {
169                                         /* We don't want to flush tags in "upstream" direction for
170                                          * certain types of operations.
171                                          *
172                                          * TODO(sergey): Need a more generic solution for this.
173                                          */
174                                         if (op->opcode == DEG_OPCODE_PARTICLE_SETTINGS_EVAL) {
175                                                 continue;
176                                         }
177                                         op->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
178                                 }
179                                 if (object != NULL) {
180                                         /* This code is used to preserve those areas which does
181                                          * direct object update,
182                                          *
183                                          * Plus it ensures visibility changes and relations and
184                                          * layers visibility update has proper flags to work with.
185                                          */
186                                         switch (comp_node->type) {
187                                                 case DEG_NODE_TYPE_UNDEFINED:
188                                                 case DEG_NODE_TYPE_OPERATION:
189                                                 case DEG_NODE_TYPE_TIMESOURCE:
190                                                 case DEG_NODE_TYPE_ID_REF:
191                                                 case DEG_NODE_TYPE_PARAMETERS:
192                                                 case DEG_NODE_TYPE_SEQUENCER:
193                                                 case DEG_NODE_TYPE_LAYER_COLLECTIONS:
194                                                 case DEG_NODE_TYPE_COPY_ON_WRITE:
195                                                         /* Ignore, does not translate to object component. */
196                                                         break;
197                                                 case DEG_NODE_TYPE_ANIMATION:
198                                                         object->recalc |= OB_RECALC_TIME;
199                                                         break;
200                                                 case DEG_NODE_TYPE_TRANSFORM:
201                                                         object->recalc |= OB_RECALC_OB;
202                                                         break;
203                                                 case DEG_NODE_TYPE_GEOMETRY:
204                                                 case DEG_NODE_TYPE_EVAL_POSE:
205                                                 case DEG_NODE_TYPE_BONE:
206                                                 case DEG_NODE_TYPE_EVAL_PARTICLES:
207                                                 case DEG_NODE_TYPE_SHADING:
208                                                 case DEG_NODE_TYPE_CACHE:
209                                                 case DEG_NODE_TYPE_PROXY:
210                                                         object->recalc |= OB_RECALC_DATA;
211                                                         break;
212                                                 case DEG_NODE_TYPE_SHADING_PARAMETERS:
213                                                         break;
214                                         }
215
216                                         /* TODO : replace with more granular flags */
217                                         object->deg_update_flag |= DEG_RUNTIME_DATA_UPDATE;
218                                 }
219                                 /* When some target changes bone, we might need to re-run the
220                                  * whole IK solver, otherwise result might be unpredictable.
221                                  */
222                                 if (comp_node->type == DEG_NODE_TYPE_BONE) {
223                                         ComponentDepsNode *pose_comp =
224                                                 id_node->find_component(DEG_NODE_TYPE_EVAL_POSE);
225                                         BLI_assert(pose_comp != NULL);
226                                         if (pose_comp->done == COMPONENT_STATE_NONE) {
227                                                 queue.push_front(pose_comp->get_entry_operation());
228                                                 pose_comp->done = COMPONENT_STATE_SCHEDULED;
229                                         }
230                                 }
231                         }
232
233                         id_node->done = 1;
234                         comp_node->done = COMPONENT_STATE_DONE;
235
236                         /* Flush to nodes along links... */
237                         /* TODO(sergey): This is mainly giving speedup due ot less queue pushes, which
238                          * reduces number of memory allocations.
239                          *
240                          * We should try solve the allocation issue instead of doing crazy things here.
241                          */
242                         if (node->outlinks.size() == 1) {
243                                 OperationDepsNode *to_node = (OperationDepsNode *)node->outlinks[0]->to;
244                                 if (to_node->scheduled == false) {
245                                         to_node->scheduled = true;
246                                         node = to_node;
247                                 }
248                                 else {
249                                         break;
250                                 }
251                         }
252                         else {
253                                 foreach (DepsRelation *rel, node->outlinks) {
254                                         OperationDepsNode *to_node = (OperationDepsNode *)rel->to;
255                                         if (to_node->scheduled == false) {
256                                                 queue.push_front(to_node);
257                                                 to_node->scheduled = true;
258                                         }
259                                 }
260                                 break;
261                         }
262                 }
263         }
264         DEG_DEBUG_PRINTF("Update flushed to %d objects\n", num_flushed_objects);
265 }
266
267 static void graph_clear_func(void *data_v, int i)
268 {
269         Depsgraph *graph = (Depsgraph *)data_v;
270         OperationDepsNode *node = graph->operations[i];
271         /* Clear node's "pending update" settings. */
272         node->flag &= ~(DEPSOP_FLAG_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE);
273 }
274
275 /* Clear tags from all operation nodes. */
276 void deg_graph_clear_tags(Depsgraph *graph)
277 {
278         /* Go over all operation nodes, clearing tags. */
279         const int num_operations = graph->operations.size();
280         const bool do_threads = num_operations > 256;
281         BLI_task_parallel_range(0, num_operations, graph, graph_clear_func, do_threads);
282         /* Clear any entry tags which haven't been flushed. */
283         BLI_gset_clear(graph->entry_tags, NULL);
284 }
285
286 }  // namespace DEG