Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/depsgraph/intern/depsgraph_tag.cc')
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc498
1 files changed, 286 insertions, 212 deletions
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index 5adcb3a11b3..41724100b51 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -49,6 +49,7 @@ extern "C" {
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_node.h"
+#include "BKE_workspace.h"
#define new new_
#include "BKE_screen.h"
@@ -66,18 +67,17 @@ extern "C" {
#include "intern/depsgraph_intern.h"
#include "util/deg_util_foreach.h"
+/* Define this in order to have more strict sanitization of what tagging flags
+ * are used for ID databnlocks. Ideally, we would always want this, but there
+ * are cases in generic modules (like IR remapping) where we don't want to spent
+ * lots of time trying to guess which components are to be updated.
+ */
+// #define STRICT_COMPONENT_TAGGING
+
/* *********************** */
/* Update Tagging/Flushing */
-/* Legacy depsgraph did some special trickery for things like particle systems
- * when tagging ID for an update. Ideally that tagging needs to become obsolete
- * in favor of havng dedicated node for that which gets tagged, but for until
- * design of those areas is more clear we'll do the same legacy code here.
- * - sergey -
- */
-#define DEPSGRAPH_USE_LEGACY_TAGGING
-
-namespace {
+namespace DEG {
/* Data-Based Tagging ------------------------------- */
@@ -93,168 +93,329 @@ void lib_id_recalc_data_tag(Main *bmain, ID *id)
DEG_id_type_tag(bmain, GS(id->name));
}
+namespace {
+
+void deg_graph_id_tag_update(Main *bmain, Depsgraph *graph, ID *id, int flag);
+
void lib_id_recalc_tag_flag(Main *bmain, ID *id, int flag)
{
+ /* This bit of code ensures legacy object->recalc flags are still filled in
+ * the same way as it was expected with the old dependency graph.
+ *
+ * This is because some areas like motion paths and likely some other
+ * physics baking process are doing manual scene update on all the frames,
+ * trying to minimize number of updates.
+ *
+ * But this flag will also let us to re-construct entry nodes for update
+ * after relations update and after layer visibility changes.
+ */
if (flag) {
- /* This bit of code ensures legacy object->recalc flags
- * are still filled in the same way as it was expected
- * with the old dependency graph.
- *
- * This is because some areas like motion paths and likely
- * some other physics baking process are doing manual scene
- * update on all the frames, trying to minimize number of
- * updates.
- *
- * But this flag will also let us to re-construct entry
- * nodes for update after relations update and after layer
- * visibility changes.
- */
- ID_Type idtype = GS(id->name);
- if (idtype == ID_OB) {
+ ID_Type id_type = GS(id->name);
+ if (id_type == ID_OB) {
Object *object = (Object *)id;
object->recalc |= (flag & OB_RECALC_ALL);
}
-
- if (flag & OB_RECALC_OB)
+ if (flag & OB_RECALC_OB) {
lib_id_recalc_tag(bmain, id);
- if (flag & (OB_RECALC_DATA | PSYS_RECALC))
+ }
+ if (flag & (OB_RECALC_DATA | PSYS_RECALC)) {
lib_id_recalc_data_tag(bmain, id);
+ }
}
else {
lib_id_recalc_tag(bmain, id);
}
}
-#ifdef DEPSGRAPH_USE_LEGACY_TAGGING
-void depsgraph_legacy_handle_update_tag(Main *bmain, ID *id, short flag)
+/* Special tagging */
+void id_tag_update_special_zero_flag(Depsgraph *graph, IDDepsNode *id_node)
{
- if (flag) {
- Object *object;
- short idtype = GS(id->name);
- if (idtype == ID_PA) {
- ParticleSystem *psys;
- for (object = (Object *)bmain->object.first;
- object != NULL;
- object = (Object *)object->id.next)
- {
- for (psys = (ParticleSystem *)object->particlesystem.first;
- psys != NULL;
- psys = (ParticleSystem *)psys->next)
- {
- if (&psys->part->id == id) {
- DEG_id_tag_update_ex(bmain, &object->id, flag & OB_RECALC_ALL);
- psys->recalc |= (flag & PSYS_RECALC);
- }
- }
+ /* NOTE: Full ID node update for now, need to minimize that i9n the future. */
+ id_node->tag_update(graph);
+}
+
+/* Tag corresponding to OB_RECALC_OB. */
+void id_tag_update_object_transform(Depsgraph *graph, IDDepsNode *id_node)
+{
+ ComponentDepsNode *transform_comp =
+ id_node->find_component(DEG_NODE_TYPE_TRANSFORM);
+ if (transform_comp == NULL) {
+#ifdef STRICT_COMPONENT_TAGGING
+ DEG_ERROR_PRINTF("ERROR: Unable to find transform component for %s\n",
+ id_node->id_orig->name);
+ BLI_assert(!"This is not supposed to happen!");
+#endif
+ return;
+ }
+ transform_comp->tag_update(graph);
+}
+
+/* Tag corresponding to OB_RECALC_DATA. */
+void id_tag_update_object_data(Depsgraph *graph, IDDepsNode *id_node)
+{
+ const ID_Type id_type = GS(id_node->id_orig->name);
+ ComponentDepsNode *data_comp = NULL;
+ switch (id_type) {
+ case ID_OB:
+ {
+ const Object *object = (Object *)id_node->id_orig;
+ switch (object->type) {
+ case OB_MESH:
+ case OB_CURVE:
+ case OB_SURF:
+ case OB_FONT:
+ case OB_MBALL:
+ data_comp = id_node->find_component(DEG_NODE_TYPE_GEOMETRY);
+ break;
+ case OB_ARMATURE:
+ data_comp = id_node->find_component(DEG_NODE_TYPE_EVAL_POSE);
+ break;
+ /* TODO(sergey): More cases here? */
}
+ break;
}
+ case ID_ME:
+ data_comp = id_node->find_component(DEG_NODE_TYPE_GEOMETRY);
+ break;
+ case ID_PA:
+ return;
+ default:
+ break;
}
-}
+ if (data_comp == NULL) {
+#ifdef STRICT_COMPONENT_TAGGING
+ DEG_ERROR_PRINTF("ERROR: Unable to find data component for %s\n",
+ id_node->id_orig->name);
+ BLI_assert(!"This is not supposed to happen!");
#endif
+ return;
+ }
+ data_comp->tag_update(graph);
+ /* Special legacy compatibility code, tag data ID for update when object
+ * is tagged for data update.
+ */
+ if (id_type == ID_OB) {
+ Object *object = (Object *)id_node->id_orig;
+ ID *data_id = (ID *)object->data;
+ if (data_id != NULL) {
+ IDDepsNode *data_id_node = graph->find_id_node(data_id);
+ // BLI_assert(data_id_node != NULL);
+ /* TODO(sergey): Do we want more granular tags here? */
+ /* TODO(sergey): Hrm, during some operations it's possible to have
+ * object node existing but not it's data. For example, when making
+ * objects local. This is valid situation, but how can we distinguish
+ * that from someone trying to do stupid things with dependency
+ * graph?
+ */
+ if (data_id_node != NULL) {
+ data_id_node->tag_update(graph);
+ }
+ }
+ }
+}
-} /* namespace */
-
-/* Tag all nodes in ID-block for update.
- * This is a crude measure, but is most convenient for old code.
- */
-void DEG_graph_id_tag_update(Main *bmain, Depsgraph *graph, ID *id)
+/* Tag corresponding to OB_RECALC_TIME. */
+void id_tag_update_object_time(Depsgraph *graph, IDDepsNode *id_node)
{
- DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
- DEG::IDDepsNode *node = deg_graph->find_id_node(id);
- lib_id_recalc_tag(bmain, id);
- if (node != NULL) {
- node->tag_update(deg_graph);
+ ComponentDepsNode *animation_comp =
+ id_node->find_component(DEG_NODE_TYPE_ANIMATION);
+ if (animation_comp == NULL) {
+ /* It's not necessarily we've got animation component in cases when
+ * we are tagging for time updates.
+ */
+ return;
}
+ animation_comp->tag_update(graph);
+ /* TODO(sergey): More components to tag here? */
}
-/* Tag nodes related to a specific piece of data */
-void DEG_graph_data_tag_update(Depsgraph *graph, const PointerRNA *ptr)
+void id_tag_update_particle(Depsgraph *graph, IDDepsNode *id_node, int tag)
{
- DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
- DEG::DepsNode *node = deg_graph->find_node_from_pointer(ptr, NULL);
- if (node != NULL) {
- node->tag_update(deg_graph);
- }
- else {
- printf("Missing node in %s\n", __func__);
- BLI_assert(!"Shouldn't happens since it'll miss crucial update.");
+ ComponentDepsNode *particle_comp =
+ id_node->find_component(DEG_NODE_TYPE_PARAMETERS);
+ ParticleSettings *particle_settings = (ParticleSettings *)id_node->id_orig;
+ particle_settings->recalc |= (tag & PSYS_RECALC);
+ if (particle_comp == NULL) {
+#ifdef STRICT_COMPONENT_TAGGING
+ DEG_ERROR_PRINTF("ERROR: Unable to find particle component for %s\n",
+ id_node->id_orig->name);
+ BLI_assert(!"This is not supposed to happen!");
+#endif
+ return;
}
+ particle_comp->tag_update(graph);
}
-/* Tag nodes related to a specific property. */
-void DEG_graph_property_tag_update(Depsgraph *graph,
- const PointerRNA *ptr,
- const PropertyRNA *prop)
+void id_tag_update_shading(Depsgraph *graph, IDDepsNode *id_node)
{
- DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
- DEG::DepsNode *node = deg_graph->find_node_from_pointer(ptr, prop);
- if (node != NULL) {
- node->tag_update(deg_graph);
+ ComponentDepsNode *shading_comp;
+ if (GS(id_node->id_orig->name) == ID_NT) {
+ shading_comp = id_node->find_component(DEG_NODE_TYPE_SHADING_PARAMETERS);
}
else {
- printf("Missing node in %s\n", __func__);
- BLI_assert(!"Shouldn't happens since it'll miss crucial update.");
+ shading_comp = id_node->find_component(DEG_NODE_TYPE_SHADING);
}
+ if (shading_comp == NULL) {
+#ifdef STRICT_COMPONENT_TAGGING
+ DEG_ERROR_PRINTF("ERROR: Unable to find shading component for %s\n",
+ id_node->id_orig->name);
+ BLI_assert(!"This is not supposed to happen!");
+#endif
+ return;
+ }
+ shading_comp->tag_update(graph);
}
-/* Tag given ID for an update in all the dependency graphs. */
-void DEG_id_tag_update(ID *id, short flag)
+#ifdef WITH_COPY_ON_WRITE
+/* Tag corresponding to DEG_TAG_COPY_ON_WRITE. */
+void id_tag_update_copy_on_write(Depsgraph *graph, IDDepsNode *id_node)
{
- DEG_id_tag_update_ex(G.main, id, flag);
+ ComponentDepsNode *cow_comp =
+ id_node->find_component(DEG_NODE_TYPE_COPY_ON_WRITE);
+ OperationDepsNode *cow_node = cow_comp->get_entry_operation();
+ cow_node->tag_update(graph);
}
+#endif
-void DEG_id_tag_update_ex(Main *bmain, ID *id, short flag)
+void id_tag_update_ntree_special(Main *bmain, Depsgraph *graph, ID *id, int flag)
{
- if (id == NULL) {
- /* Ideally should not happen, but old depsgraph allowed this. */
+ bNodeTree *ntree = NULL;
+ switch (GS(id->name)) {
+ case ID_MA:
+ ntree = ((Material *)id)->nodetree;
+ break;
+ default:
+ break;
+ }
+ if (ntree == NULL) {
return;
}
- DEG_DEBUG_PRINTF("%s: id=%s flag=%d\n", __func__, id->name, flag);
+ IDDepsNode *id_node = graph->find_id_node(&ntree->id);
+ if (id_node != NULL) {
+ deg_graph_id_tag_update(bmain, graph, id_node->id_orig, flag);
+ }
+}
+
+void deg_graph_id_tag_update(Main *bmain, Depsgraph *graph, ID *id, int flag)
+{
+ Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
+ IDDepsNode *id_node = deg_graph->find_id_node(id);
+ /* Make sure legacy flags are all nicely update. */
+ lib_id_recalc_tag_flag(bmain, id, flag);
+ if (id_node == NULL) {
+ /* Shouldn't happen, but better be sure here. */
+ return;
+ }
+ /* Tag components based on flags. */
+ if (flag == 0) {
+ id_tag_update_special_zero_flag(graph, id_node);
+ id_tag_update_ntree_special(bmain, graph, id, flag);
+ return;
+ }
+ if (flag & OB_RECALC_OB) {
+ id_tag_update_object_transform(graph, id_node);
+ }
+ if (flag & OB_RECALC_DATA) {
+ id_tag_update_object_data(graph, id_node);
+#ifdef WITH_COPY_ON_WRITE
+ if (flag & DEG_TAG_COPY_ON_WRITE) {
+ const ID_Type id_type = GS(id_node->id_orig->name);
+ if (id_type == ID_OB) {
+ Object *object = (Object *)id_node->id_orig;
+ ID *ob_data = (ID *)object->data;
+ DEG_id_tag_update_ex(bmain, ob_data, flag);
+ }
+ }
+#endif
+ }
+ if (flag & OB_RECALC_TIME) {
+ id_tag_update_object_time(graph, id_node);
+ }
+ if (flag & PSYS_RECALC) {
+ id_tag_update_particle(graph, id_node, flag);
+ }
+ if (flag & DEG_TAG_SHADING_UPDATE) {
+ id_tag_update_shading(graph, id_node);
+ }
+#ifdef WITH_COPY_ON_WRITE
+ if (flag & DEG_TAG_COPY_ON_WRITE) {
+ id_tag_update_copy_on_write(graph, id_node);
+ }
+#endif
+ id_tag_update_ntree_special(bmain, graph, id, flag);
+}
+
+void deg_id_tag_update(Main *bmain, ID *id, int flag)
+{
lib_id_recalc_tag_flag(bmain, id, flag);
for (Scene *scene = (Scene *)bmain->scene.first;
scene != NULL;
scene = (Scene *)scene->id.next)
{
- if (scene->depsgraph) {
- Depsgraph *graph = scene->depsgraph;
- if (flag == 0) {
- /* TODO(sergey): Currently blender is still tagging IDs
- * for recalc just using flag=0. This isn't totally correct
- * but we'd better deal with such cases and don't fail.
- */
- DEG_graph_id_tag_update(bmain, graph, id);
- continue;
- }
- if (flag & OB_RECALC_DATA && GS(id->name) == ID_OB) {
- Object *object = (Object *)id;
- if (object->data != NULL) {
- DEG_graph_id_tag_update(bmain,
- graph,
- (ID *)object->data);
- }
- }
- if (flag & (OB_RECALC_OB | OB_RECALC_DATA)) {
- DEG_graph_id_tag_update(bmain, graph, id);
- }
- else if (flag & OB_RECALC_TIME) {
- DEG_graph_id_tag_update(bmain, graph, id);
- }
+ if (scene->depsgraph_legacy != NULL) {
+ Depsgraph *graph = (Depsgraph *)scene->depsgraph_legacy;
+ deg_graph_id_tag_update(bmain, graph, id, flag);
}
}
+}
-#ifdef DEPSGRAPH_USE_LEGACY_TAGGING
- /* Special handling from the legacy depsgraph.
- * TODO(sergey): Need to get rid of those once all the areas
- * are re-formulated in terms of franular nodes.
- */
- depsgraph_legacy_handle_update_tag(bmain, id, flag);
-#endif
+void deg_graph_on_visible_update(Main *bmain, Scene *scene, Depsgraph *graph)
+{
+ /* Make sure objects are up to date. */
+ GHASH_FOREACH_BEGIN(DEG::IDDepsNode *, id_node, graph->id_hash)
+ {
+ const ID_Type id_type = GS(id_node->id_orig->name);
+ /* TODO(sergey): Special exception for now. */
+ if (id_type == ID_MSK) {
+ deg_graph_id_tag_update(bmain, graph, id_node->id_orig, 0);
+ }
+ if (id_type != ID_OB) {
+ /* Ignore non-object nodes on visibility changes. */
+ continue;
+ }
+ int flag = 0;
+ /* We only tag components which needs an update. Tagging everything is
+ * not a good idea because that might reset particles cache (or any
+ * other type of cache).
+ *
+ * TODO(sergey): Need to generalize this somehow.
+ */
+ if (id_type == ID_OB) {
+ flag |= OB_RECALC_OB | OB_RECALC_DATA | DEG_TAG_COPY_ON_WRITE;
+ }
+ deg_graph_id_tag_update(bmain, graph, id_node->id_orig, flag);
+ }
+ GHASH_FOREACH_END();
+ /* Make sure collection properties are up to date. */
+ IDDepsNode *scene_id_node = graph->find_id_node(&scene->id);
+ BLI_assert(scene_id_node != NULL);
+ scene_id_node->tag_update(graph);
+}
+
+} /* namespace */
+
+} // namespace DEG
+
+/* Tag given ID for an update in all the dependency graphs. */
+void DEG_id_tag_update(ID *id, int flag)
+{
+ DEG_id_tag_update_ex(G.main, id, flag);
+}
+
+void DEG_id_tag_update_ex(Main *bmain, ID *id, int flag)
+{
+ if (id == NULL) {
+ /* Ideally should not happen, but old depsgraph allowed this. */
+ return;
+ }
+ DEG_DEBUG_PRINTF("%s: id=%s flag=%d\n", __func__, id->name, flag);
+ DEG::deg_id_tag_update(bmain, id, flag);
}
/* Tag given ID type for update. */
-void DEG_id_type_tag(Main *bmain, short idtype)
+void DEG_id_type_tag(Main *bmain, short id_type)
{
- if (idtype == ID_NT) {
+ if (id_type == ID_NT) {
/* Stupid workaround so parent datablocks of nested nodetree get looped
* over when we loop over tagged datablock types.
*/
@@ -265,7 +426,7 @@ void DEG_id_type_tag(Main *bmain, short idtype)
DEG_id_type_tag(bmain, ID_SCE);
}
- bmain->id_tag_update[BKE_idcode_to_index(idtype)] = 1;
+ bmain->id_tag_update[BKE_idcode_to_index(id_type)] = 1;
}
/* Recursively push updates out to all nodes dependent on this,
@@ -283,106 +444,19 @@ void DEG_ids_flush_tagged(Main *bmain)
void DEG_scene_flush_update(Main *bmain, Scene *scene)
{
- if (scene->depsgraph == NULL) {
+ if (scene->depsgraph_legacy == NULL) {
return;
}
DEG::deg_graph_flush_updates(
bmain,
- reinterpret_cast<DEG::Depsgraph *>(scene->depsgraph));
+ reinterpret_cast<DEG::Depsgraph *>(scene->depsgraph_legacy));
}
/* Update dependency graph when visible scenes/layers changes. */
void DEG_graph_on_visible_update(Main *bmain, Scene *scene)
{
- DEG::Depsgraph *graph = reinterpret_cast<DEG::Depsgraph *>(scene->depsgraph);
- wmWindowManager *wm = (wmWindowManager *)bmain->wm.first;
- int old_layers = graph->layers;
- if (wm != NULL) {
- BKE_main_id_tag_listbase(&bmain->scene, LIB_TAG_DOIT, true);
- graph->layers = 0;
- for (wmWindow *win = (wmWindow *)wm->windows.first;
- win != NULL;
- win = (wmWindow *)win->next)
- {
- Scene *scene = win->screen->scene;
- if (scene->id.tag & LIB_TAG_DOIT) {
- graph->layers |= BKE_screen_visible_layers(win->screen, scene);
- scene->id.tag &= ~LIB_TAG_DOIT;
- }
- }
- }
- else {
- /* All the layers for background render for now. */
- graph->layers = (1 << 20) - 1;
- }
- if (old_layers != graph->layers) {
- /* Tag all objects which becomes visible (or which becomes needed for dependencies)
- * for recalc.
- *
- * This is mainly needed on file load only, after that updates of invisible objects
- * will be stored in the pending list.
- */
- GHASH_FOREACH_BEGIN(DEG::IDDepsNode *, id_node, graph->id_hash)
- {
- ID *id = id_node->id;
- if ((id->tag & LIB_TAG_ID_RECALC_ALL) != 0 ||
- (id_node->layers & scene->lay_updated) == 0)
- {
- id_node->tag_update(graph);
- }
- /* A bit of magic: if object->recalc is set it means somebody tagged
- * it for update. If corresponding ID recalc flags are zero it means
- * graph has been evaluated after that and the recalc was skipped
- * because of visibility check.
- */
- if (GS(id->name) == ID_OB) {
- Object *object = (Object *)id;
- if ((id->tag & LIB_TAG_ID_RECALC_ALL) == 0 &&
- (object->recalc & OB_RECALC_ALL) != 0)
- {
- id_node->tag_update(graph);
- DEG::ComponentDepsNode *anim_comp =
- id_node->find_component(DEG::DEG_NODE_TYPE_ANIMATION);
- if (anim_comp != NULL && object->recalc & OB_RECALC_TIME) {
- anim_comp->tag_update(graph);
- }
- }
- }
- }
- GHASH_FOREACH_END();
- }
- scene->lay_updated |= graph->layers;
- /* If graph is tagged for update, we don't need to bother with updates here,
- * nodes will be re-created.
- */
- if (graph->need_update) {
- return;
- }
- /* Special trick to get local view to work. */
- LINKLIST_FOREACH (Base *, base, &scene->base) {
- Object *object = base->object;
- DEG::IDDepsNode *id_node = graph->find_id_node(&object->id);
- id_node->layers = 0;
- }
- LINKLIST_FOREACH (Base *, base, &scene->base) {
- Object *object = base->object;
- DEG::IDDepsNode *id_node = graph->find_id_node(&object->id);
- id_node->layers |= base->lay;
- if (object == scene->camera) {
- /* Camera should always be updated, it used directly by viewport. */
- id_node->layers |= (unsigned int)(-1);
- }
- }
- DEG::deg_graph_build_flush_layers(graph);
- LINKLIST_FOREACH (Base *, base, &scene->base) {
- Object *object = base->object;
- DEG::IDDepsNode *id_node = graph->find_id_node(&object->id);
- GHASH_FOREACH_BEGIN(DEG::ComponentDepsNode *, comp, id_node->components)
- {
- id_node->layers |= comp->layers;
- }
- GHASH_FOREACH_END();
- }
+ DEG::Depsgraph *graph = (DEG::Depsgraph *)scene->depsgraph_legacy;
+ DEG::deg_graph_on_visible_update(bmain, scene, graph);
}
void DEG_on_visible_update(Main *bmain, const bool UNUSED(do_time))
@@ -391,7 +465,7 @@ void DEG_on_visible_update(Main *bmain, const bool UNUSED(do_time))
scene != NULL;
scene = (Scene *)scene->id.next)
{
- if (scene->depsgraph != NULL) {
+ if (scene->depsgraph_legacy != NULL) {
DEG_graph_on_visible_update(bmain, scene);
}
}