Merge branch 'master' into blender2.8
[blender.git] / source / blender / depsgraph / intern / depsgraph_tag.cc
index 8f91a82676007ac7f2a9e3c4473c8f42a7ddb029..ee406acb4900fbd9d14e901513267f892d9fc591 100644 (file)
@@ -49,6 +49,8 @@ extern "C" {
 #include "BKE_library.h"
 #include "BKE_main.h"
 #include "BKE_node.h"
+#include "BKE_scene.h"
+#include "BKE_workspace.h"
 
 #define new new_
 #include "BKE_screen.h"
@@ -66,18 +68,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,138 +94,421 @@ 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) {
-                       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;
+               case ID_LP:
+                       data_comp = id_node->find_component(DEG_NODE_TYPE_PARAMETERS);
+                       break;
+               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);
                        }
                }
        }
 }
+
+/* Tag corresponding to OB_RECALC_TIME. */
+void id_tag_update_object_time(Depsgraph *graph, IDDepsNode *id_node)
+{
+       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? */
+}
+
+void id_tag_update_particle(Depsgraph *graph, IDDepsNode *id_node, int tag)
+{
+       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);
+}
 
-}  /* namespace */
+void id_tag_update_shading(Depsgraph *graph, IDDepsNode *id_node)
+{
+       ComponentDepsNode *shading_comp;
+       if (GS(id_node->id_orig->name) == ID_NT) {
+               shading_comp = id_node->find_component(DEG_NODE_TYPE_SHADING_PARAMETERS);
+       }
+       else {
+               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 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 DEG_TAG_COPY_ON_WRITE. */
+void id_tag_update_copy_on_write(Depsgraph *graph, IDDepsNode *id_node)
+{
+       if (!DEG_depsgraph_use_copy_on_write()) {
+               return;
+       }
+       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);
+}
+
+void id_tag_update_select_update(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);
+       ComponentDepsNode *component;
+       OperationDepsNode *node = NULL;
+       const ID_Type id_type = GS(id_node->id_orig->name);
+       if (id_type == ID_SCE) {
+               /* We need to flush base flags to all objects in a scene since we
+                * don't know which ones changed. However, we don't want to update
+                * the whole scene, so pick up some operation which will do as less
+                * as possible.
+                *
+                * TODO(sergey): We can introduce explicit exit operation which
+                * does nothing and which is only used to cascade flush down the
+                * road.
+                */
+               component = id_node->find_component(DEG_NODE_TYPE_LAYER_COLLECTIONS);
+               BLI_assert(component != NULL);
+               if (component != NULL) {
+                       node = component->find_operation(DEG_OPCODE_VIEW_LAYER_DONE);
+               }
+       }
+       else if (id_type == ID_OB) {
+               component = id_node->find_component(DEG_NODE_TYPE_LAYER_COLLECTIONS);
+               /* NOTE: This component might be missing for indirectly linked
+                * objects.
+                */
+               if (component != NULL) {
+                       node = component->find_operation(DEG_OPCODE_OBJECT_BASE_FLAGS);
+               }
+       }
+       else {
+               component = id_node->find_component(DEG_NODE_TYPE_BATCH_CACHE);
+               BLI_assert(component != NULL);
+               if (component != NULL) {
+                       node = component->find_operation(DEG_OPCODE_GEOMETRY_SELECT_UPDATE,
+                                                        "", -1);
+               }
+       }
        if (node != NULL) {
-               node->tag_update(deg_graph);
+               node->tag_update(graph);
        }
 }
 
-/* Tag given ID for an update in all the dependency graphs. */
-void DEG_id_tag_update(ID *id, short flag)
+void id_tag_update_base_flags(Depsgraph *graph, IDDepsNode *id_node)
 {
-       DEG_id_tag_update_ex(G.main, id, flag);
+       ComponentDepsNode *component;
+       OperationDepsNode *node = NULL;
+       const ID_Type id_type = GS(id_node->id_orig->name);
+       if (id_type == ID_SCE) {
+               component = id_node->find_component(DEG_NODE_TYPE_LAYER_COLLECTIONS);
+               if (component == NULL) {
+                       return;
+               }
+               node = component->find_operation(DEG_OPCODE_VIEW_LAYER_INIT);
+       }
+       else if (id_type == ID_OB) {
+               component = id_node->find_component(DEG_NODE_TYPE_LAYER_COLLECTIONS);
+               if (component == NULL) {
+                       return;
+               }
+               node = component->find_operation(DEG_OPCODE_OBJECT_BASE_FLAGS);
+               if (node == NULL) {
+                       return;
+               }
+       }
+       if (node != NULL) {
+               node->tag_update(graph);
+       }
 }
 
-void DEG_id_tag_update_ex(Main *bmain, ID *id, short flag)
+void id_tag_update_editors_update(Main *bmain, Depsgraph *graph, ID *id)
 {
-       if (id == NULL) {
-               /* Ideally should not happen, but old depsgraph allowed this. */
+       /* NOTE: We handle this immediately, without delaying anything, to be
+        * sure we don't cause threading issues with OpenGL.
+        */
+       /* TODO(sergey): Make sure this works for CoW-ed datablocks as well. */
+       DEGEditorUpdateContext update_ctx = {NULL};
+       update_ctx.bmain = bmain;
+       update_ctx.scene = graph->scene;
+       update_ctx.view_layer = graph->view_layer;
+       deg_editors_id_update(&update_ctx, id);
+}
+
+void id_tag_update_ntree_special(Main *bmain, Depsgraph *graph, ID *id, int flag)
+{
+       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);
-       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 (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);
+               if (DEG_depsgraph_use_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);
                                }
                        }
-                       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 (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);
+       }
+       if (flag & DEG_TAG_COPY_ON_WRITE) {
+               id_tag_update_copy_on_write(graph, id_node);
+       }
+       if (flag & DEG_TAG_SELECT_UPDATE) {
+               id_tag_update_select_update(graph, id_node);
+       }
+       if (flag & DEG_TAG_BASE_FLAGS_UPDATE) {
+               id_tag_update_base_flags(graph, id_node);
+       }
+       if (flag & DEG_TAG_EDITORS_UPDATE) {
+               id_tag_update_editors_update(bmain, graph, id);
+       }
+       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);
+       LINKLIST_FOREACH(Scene *, scene, &bmain->scene) {
+               LINKLIST_FOREACH(ViewLayer *, view_layer, &scene->view_layers) {
+                       Depsgraph *depsgraph =
+                               (Depsgraph *)BKE_scene_get_depsgraph(scene,
+                                                                    view_layer,
+                                                                    false);
+                       if (depsgraph != NULL) {
+                               deg_graph_id_tag_update(bmain, depsgraph, 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, Depsgraph *graph)
+{
+       /* Make sure objects are up to date. */
+       foreach (DEG::IDDepsNode *id_node, graph->id_nodes) {
+               const ID_Type id_type = GS(id_node->id_orig->name);
+               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);
+       }
+       /* Make sure collection properties are up to date. */
+       for (Scene *scene_iter = graph->scene; scene_iter != NULL; scene_iter = scene_iter->set) {
+               IDDepsNode *scene_id_node = graph->find_id_node(&scene_iter->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);
+}
+
+void DEG_graph_id_tag_update(struct Main *bmain,
+                             struct Depsgraph *depsgraph,
+                             struct ID *id,
+                             int flag)
+{
+       DEG::Depsgraph *graph = (DEG::Depsgraph *)depsgraph;
+       DEG::deg_graph_id_tag_update(bmain, graph, id, flag);
 }
 
 /* Mark a particular datablock type as having changing. */
-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.
                 */
@@ -235,134 +519,35 @@ 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,
- * until all affected are tagged and/or scheduled up for eval
- */
-void DEG_ids_flush_tagged(Main *bmain)
+void DEG_graph_flush_update(Main *bmain, Depsgraph *depsgraph)
 {
-       for (Scene *scene = (Scene *)bmain->scene.first;
-            scene != NULL;
-            scene = (Scene *)scene->id.next)
-       {
-               DEG_scene_flush_update(bmain, scene);
-       }
-}
-
-void DEG_scene_flush_update(Main *bmain, Scene *scene)
-{
-       if (scene->depsgraph == NULL) {
+       if (depsgraph == NULL) {
                return;
        }
-       DEG::deg_graph_flush_updates(
-               bmain,
-               reinterpret_cast<DEG::Depsgraph *>(scene->depsgraph));
+       DEG::deg_graph_flush_updates(bmain, (DEG::Depsgraph *)depsgraph);
 }
 
 /* Update dependency graph when visible scenes/layers changes. */
-void DEG_graph_on_visible_update(Main *bmain, Scene *scene)
+void DEG_graph_on_visible_update(Main *bmain, Depsgraph *depsgraph)
 {
-       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 *)depsgraph;
+       DEG::deg_graph_on_visible_update(bmain, graph);
 }
 
 void DEG_on_visible_update(Main *bmain, const bool UNUSED(do_time))
 {
-       for (Scene *scene = (Scene *)bmain->scene.first;
-            scene != NULL;
-            scene = (Scene *)scene->id.next)
-       {
-               if (scene->depsgraph != NULL) {
-                       DEG_graph_on_visible_update(bmain, scene);
+       LINKLIST_FOREACH(Scene *, scene, &bmain->scene) {
+               LINKLIST_FOREACH(ViewLayer *, view_layer, &scene->view_layers) {
+                       Depsgraph *depsgraph =
+                               (Depsgraph *)BKE_scene_get_depsgraph(scene,
+                                                                    view_layer,
+                                                                    false);
+                       if (depsgraph != NULL) {
+                               DEG_graph_on_visible_update(bmain, depsgraph);
+                       }
                }
        }
 }
@@ -370,7 +555,10 @@ void DEG_on_visible_update(Main *bmain, const bool UNUSED(do_time))
 /* Check if something was changed in the database and inform
  * editors about this.
  */
-void DEG_ids_check_recalc(Main *bmain, Scene *scene, bool time)
+void DEG_ids_check_recalc(Main *bmain,
+                          Scene *scene,
+                          ViewLayer *view_layer,
+                          bool time)
 {
        ListBase *lbarray[MAX_LIBARRAY];
        int a;
@@ -388,7 +576,11 @@ void DEG_ids_check_recalc(Main *bmain, Scene *scene, bool time)
                }
        }
 
-       DEG::deg_editors_scene_update(bmain, scene, (updated || time));
+       DEGEditorUpdateContext update_ctx = {NULL};
+       update_ctx.bmain = bmain;
+       update_ctx.scene = scene;
+       update_ctx.view_layer = view_layer;
+       DEG::deg_editors_scene_update(&update_ctx, (updated || time));
 }
 
 void DEG_ids_clear_recalc(Main *bmain)