Render: Use dependency graph for compositor/sequencer
authorSergey Sharybin <sergey.vfx@gmail.com>
Mon, 20 May 2019 13:14:10 +0000 (15:14 +0200)
committerSergey Sharybin <sergey.vfx@gmail.com>
Thu, 23 May 2019 14:22:25 +0000 (16:22 +0200)
This change makes it so a minimal dependency graph which only includes
compositor and sequencer is built for the render pipeline purposes.

Tricky part here is that it's only compositor itself and sequencer who
to use this dependency graph and IDs from it. Render engines are still
to be provided original IDs because:

- They will create dependency graph for the given scene, and currently
  it is not possible to create dependency graph from CoW scene.

- IDs from the compositor/sequencer dependency graph are "stripped",
  as in, they wouldn't have all view layers, collections or objects
required for proper final render.

This creates annoying mess of mixing evaluated and original scene
access in various parts of the pipeline.

Fixes T63927: Compositing nodes - drivers don't really work

Reviewers: brecht

Maniphest Tasks: T63927

Differential Revision: https://developer.blender.org/D4911

16 files changed:
source/blender/depsgraph/DEG_depsgraph_build.h
source/blender/depsgraph/intern/builder/deg_builder_map.h
source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
source/blender/depsgraph/intern/builder/deg_builder_nodes.h
source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc
source/blender/depsgraph/intern/builder/deg_builder_relations.cc
source/blender/depsgraph/intern/builder/deg_builder_relations.h
source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc
source/blender/depsgraph/intern/depsgraph.cc
source/blender/depsgraph/intern/depsgraph.h
source/blender/depsgraph/intern/depsgraph_build.cc
source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
source/blender/render/intern/include/render_types.h
source/blender/render/intern/source/pipeline.c

index 2d0bc6ff15bc1ccf086e1e70215a9e965509a95e..15abc0c0a641795cc9cf60194e1b454c075a9820 100644 (file)
@@ -52,14 +52,19 @@ extern "C" {
 
 /* Graph Building -------------------------------- */
 
-/* Build depsgraph for the given scene, and dump results in given
- * graph container.
- */
+/* Build depsgraph for the given scene, and dump results in given graph container. */
 void DEG_graph_build_from_view_layer(struct Depsgraph *graph,
                                      struct Main *bmain,
                                      struct Scene *scene,
                                      struct ViewLayer *view_layer);
 
+/* Special version of builder which produces dependency graph suitable for the render pipeline.
+ * It will contain sequencer and compositor (if needed) and all their dependencies. */
+void DEG_graph_build_for_render_pipeline(struct Depsgraph *graph,
+                                         struct Main *bmain,
+                                         struct Scene *scene,
+                                         struct ViewLayer *view_layer);
+
 /* Tag relations from the given graph for update. */
 void DEG_graph_tag_relations_update(struct Depsgraph *graph);
 
index 1199b517f0cb8d6ee04a7cec3c0a31d45e1d459e..dd124e07a009f0c5673cf85bcb2942bee0b0cc38 100644 (file)
@@ -38,8 +38,12 @@ class BuilderMap {
     TAG_TRANSFORM = (1 << 2),
     TAG_GEOMETRY = (1 << 3),
 
+    TAG_SCENE_COMPOSITOR = (1 << 4),
+    TAG_SCENE_SEQUENCER = (1 << 5),
+
     /* All ID components has been built. */
-    TAG_COMPLETE = (TAG_ANIMATION | TAG_PARAMETERS | TAG_TRANSFORM | TAG_GEOMETRY),
+    TAG_COMPLETE = (TAG_ANIMATION | TAG_PARAMETERS | TAG_TRANSFORM | TAG_GEOMETRY |
+                    TAG_SCENE_COMPOSITOR | TAG_SCENE_SEQUENCER),
   };
 
   BuilderMap();
index 10bcfcf04d78f36c4dbb738a30dc592484c37304..cc9e1d2a9da66a33676ad05c1c05384fb2750cf9 100644 (file)
@@ -543,7 +543,10 @@ void DepsgraphNodeBuilder::build_object(int base_index,
   IDNode *id_node = add_id_node(&object->id);
   Object *object_cow = get_cow_datablock(object);
   id_node->linked_state = linked_state;
-  if (object == scene_->camera) {
+  /* NOTE: Scene is NULL when building dependency graph for render pipeline.
+   * Probably need to assign that to something non-NULL, but then the logic here will still be
+   * somewhat weird. */
+  if (scene_ != NULL && object == scene_->camera) {
     id_node->is_directly_visible = true;
   }
   else {
@@ -1366,8 +1369,16 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree)
       build_object(-1, (Object *)id, DEG_ID_LINKED_INDIRECTLY, true);
     }
     else if (id_type == ID_SCE) {
-      /* Scenes are used by compositor trees, and handled by render
-       * pipeline. No need to build dependencies for them here. */
+      Scene *node_scene = (Scene *)id;
+      build_scene_parameters(node_scene);
+      /* Camera is used by defocus node.
+       *
+       * On the one hand it's annoying to always pull it in, but on another hand it's also annoying
+       * to have hardcoded node-type exception here. */
+      if (node_scene->camera != NULL) {
+        /* TODO(sergey): Use visibility of owner of the node tree. */
+        build_object(-1, node_scene->camera, DEG_ID_LINKED_INDIRECTLY, true);
+      }
     }
     else if (id_type == ID_TXT) {
       /* Ignore script nodes. */
@@ -1442,19 +1453,6 @@ void DepsgraphNodeBuilder::build_image(Image *image)
       &image->id, NodeType::GENERIC_DATABLOCK, OperationCode::GENERIC_DATABLOCK_UPDATE);
 }
 
-void DepsgraphNodeBuilder::build_compositor(Scene *scene)
-{
-  /* For now, just a plain wrapper? */
-  // TODO: create compositing component?
-  // XXX: component type undefined!
-  // graph->get_node(&scene->id, NULL, NodeType::COMPOSITING, NULL);
-
-  /* for now, nodetrees are just parameters; compositing occurs in internals
-   * of renderer... */
-  add_component_node(&scene->id, NodeType::PARAMETERS);
-  build_nodetree(scene->nodetree);
-}
-
 void DepsgraphNodeBuilder::build_gpencil(bGPdata *gpd)
 {
   if (built_map_.checkIsBuiltAndTag(gpd)) {
index 8b9578915a196fd143efe81cc4c63bde6485a276..c3a04a9ad8819614a30638424ec4db3b72108dfa 100644 (file)
@@ -153,7 +153,9 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
 
   void build_id(ID *id);
 
+  void build_scene_render(Scene *scene);
   void build_scene_parameters(Scene *scene);
+  void build_scene_compositor(Scene *scene);
 
   void build_layer_collections(ListBase *lb);
   void build_view_layer(Scene *scene,
@@ -203,7 +205,6 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
   void build_texture(Tex *tex);
   void build_image(Image *image);
   void build_world(World *world);
-  void build_compositor(Scene *scene);
   void build_gpencil(bGPdata *gpd);
   void build_cachefile(CacheFile *cache_file);
   void build_mask(Mask *mask);
index 5fd1b4e833201d53a8ff1f98d905cc6a85c8df3f..4d2fe48e974486c59a35dbec74d0eef8ecaf3f84 100644 (file)
 
 namespace DEG {
 
+void DepsgraphNodeBuilder::build_scene_render(Scene *scene)
+{
+  const bool build_compositor = (scene->r.scemode & R_DOCOMP);
+  IDNode *id_node = add_id_node(&scene->id);
+  id_node->linked_state = DEG_ID_LINKED_DIRECTLY;
+  add_time_source();
+  build_scene_parameters(scene);
+  if (build_compositor) {
+    build_scene_compositor(scene);
+  }
+}
+
 void DepsgraphNodeBuilder::build_scene_parameters(Scene *scene)
 {
   if (built_map_.checkIsBuiltAndTag(scene, BuilderMap::TAG_PARAMETERS)) {
@@ -36,4 +48,15 @@ void DepsgraphNodeBuilder::build_scene_parameters(Scene *scene)
   add_operation_node(&scene->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL);
 }
 
+void DepsgraphNodeBuilder::build_scene_compositor(Scene *scene)
+{
+  if (built_map_.checkIsBuiltAndTag(scene, BuilderMap::TAG_SCENE_COMPOSITOR)) {
+    return;
+  }
+  if (scene->nodetree == NULL) {
+    return;
+  }
+  build_nodetree(scene->nodetree);
+}
+
 }  // namespace DEG
index 675933a38e3643972e46214ff245739617ad4b83..baebd682f3ff3fe04d2a81821cdf9b6c0f5a10d4 100644 (file)
@@ -125,9 +125,7 @@ void DepsgraphNodeBuilder::build_view_layer(Scene *scene,
     build_world(scene->world);
   }
   /* Compositor nodes */
-  if (scene->nodetree != NULL) {
-    build_compositor(scene);
-  }
+  build_scene_compositor(scene);
   /* Cache file. */
   LISTBASE_FOREACH (CacheFile *, cachefile, &bmain_->cachefiles) {
     build_cachefile(cachefile);
index 10e81faf333af278b6a7f3ca79404725d6e90bec..79f28973dc37471ef2000aec5ac0f0c90ece8323 100644 (file)
@@ -2131,8 +2131,15 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
       build_object(NULL, (Object *)id);
     }
     else if (id_type == ID_SCE) {
-      /* Scenes are used by compositor trees, and handled by render
-       * pipeline. No need to build dependencies for them here. */
+      Scene *node_scene = (Scene *)id;
+      build_scene_parameters(node_scene);
+      /* Camera is used by defocus node.
+       *
+       * On the one hand it's annoying to always pull it in, but on another hand it's also annoying
+       * to have hardcoded node-type exception here. */
+      if (node_scene->camera != NULL) {
+        build_object(NULL, node_scene->camera);
+      }
     }
     else if (id_type == ID_TXT) {
       /* Ignore script nodes. */
@@ -2220,12 +2227,6 @@ void DepsgraphRelationBuilder::build_image(Image *image)
   build_parameters(&image->id);
 }
 
-void DepsgraphRelationBuilder::build_compositor(Scene *scene)
-{
-  /* For now, just a plain wrapper? */
-  build_nodetree(scene->nodetree);
-}
-
 void DepsgraphRelationBuilder::build_gpencil(bGPdata *gpd)
 {
   if (built_map_.checkIsBuiltAndTag(gpd)) {
index c97c8a4b375dda6f8abe622977ad702094c2f1e7..7d3020921196519801e4a11187a4e1c674e81f00 100644 (file)
@@ -195,7 +195,9 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
 
   void build_id(ID *id);
 
+  void build_scene_render(Scene *scene);
   void build_scene_parameters(Scene *scene);
+  void build_scene_compositor(Scene *scene);
 
   void build_layer_collections(ListBase *lb);
   void build_view_layer(Scene *scene, ViewLayer *view_layer);
@@ -261,7 +263,6 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
   void build_material(Material *ma);
   void build_texture(Tex *tex);
   void build_image(Image *image);
-  void build_compositor(Scene *scene);
   void build_gpencil(bGPdata *gpd);
   void build_cachefile(CacheFile *cache_file);
   void build_mask(Mask *mask);
index d8672d35ddbc2fe2fc4b2e83872937efc8634078..beada644f71748a1fca5fc1c62c2f4227ca0fd47 100644 (file)
 
 namespace DEG {
 
+void DepsgraphRelationBuilder::build_scene_render(Scene *scene)
+{
+  const bool build_compositor = (scene->r.scemode & R_DOCOMP);
+  build_scene_parameters(scene);
+  if (build_compositor) {
+    build_scene_compositor(scene);
+  }
+}
+
 void DepsgraphRelationBuilder::build_scene_parameters(Scene *scene)
 {
   if (built_map_.checkIsBuiltAndTag(scene, BuilderMap::TAG_PARAMETERS)) {
@@ -38,4 +47,15 @@ void DepsgraphRelationBuilder::build_scene_parameters(Scene *scene)
   add_relation(parameters_eval_key, scene_eval_key, "Parameters -> Scene Eval");
 }
 
+void DepsgraphRelationBuilder::build_scene_compositor(Scene *scene)
+{
+  if (built_map_.checkIsBuiltAndTag(scene, BuilderMap::TAG_SCENE_COMPOSITOR)) {
+    return;
+  }
+  if (scene->nodetree == NULL) {
+    return;
+  }
+  build_nodetree(scene->nodetree);
+}
+
 }  // namespace DEG
index a744ecc0f5019f89a01a00068969def5c0e93330..8f705fcaae59b2389f83ac76effa77c9f86e5e3b 100644 (file)
@@ -106,10 +106,6 @@ void DepsgraphRelationBuilder::build_view_layer(Scene *scene, ViewLayer *view_la
   if (scene->world != NULL) {
     build_world(scene->world);
   }
-  /* Compositor nodes. */
-  if (scene->nodetree != NULL) {
-    build_compositor(scene);
-  }
   /* Masks. */
   LISTBASE_FOREACH (Mask *, mask, &bmain_->masks) {
     build_mask(mask);
@@ -128,7 +124,8 @@ void DepsgraphRelationBuilder::build_view_layer(Scene *scene, ViewLayer *view_la
       build_collection(NULL, NULL, fls->group);
     }
   }
-  /* Scene parameters. */
+  /* Scene parameters, compositor and such. */
+  build_scene_compositor(scene);
   build_scene_parameters(scene);
   /* Build all set scenes. */
   if (scene->set != NULL) {
index e2a9dde1eea22f6f2adcd7d76dd7a0bcdc7321cf..5d96bfad95eaf919733ea5036ba9e619e3ffedac 100644 (file)
@@ -73,7 +73,8 @@ Depsgraph::Depsgraph(Scene *scene, ViewLayer *view_layer, eEvaluationMode mode)
       ctime(BKE_scene_frame_get(scene)),
       scene_cow(NULL),
       is_active(false),
-      debug_is_evaluating(false)
+      debug_is_evaluating(false),
+      is_render_pipeline_depsgraph(false)
 {
   BLI_spin_init(&lock);
   id_hash = BLI_ghash_ptr_new("Depsgraph id hash");
index 2dcbb6b5574d591be59794692093d9f63acb8ef5..073ec99b3aa05f1d86269297186a18def0375730 100644 (file)
@@ -194,6 +194,12 @@ struct Depsgraph {
 
   bool debug_is_evaluating;
 
+  /* Is set to truth for dependency graph which are used for post-processing (compositor and
+   * sequencer).
+   * Such dependency graph needs all view layers (so render pipeline can access names), but it
+   * does not need any bases. */
+  bool is_render_pipeline_depsgraph;
+
   /* Cached list of colliders/effectors for collections and the scene
    * created along with relations, for fast lookup during evaluation. */
   GHash *physics_relations[DEG_PHYSICS_RELATIONS_NUM];
index dd2979160cd6ae0177a887290603555ede3f534b..138b23888b4d41e825b440dfd5443155daff44c4 100644 (file)
@@ -222,9 +222,33 @@ struct Depsgraph *DEG_get_graph_from_handle(struct DepsNodeHandle *node_handle)
 /* ******************** */
 /* Graph Building API's */
 
-/* Build depsgraph for the given scene layer, and dump results in given
- * graph container.
- */
+static void graph_build_finalize_common(DEG::Depsgraph *deg_graph, Main *bmain)
+{
+  /* Detect and solve cycles. */
+  DEG::deg_graph_detect_cycles(deg_graph);
+  /* Simplify the graph by removing redundant relations (to optimize
+   * traversal later). */
+  /* TODO: it would be useful to have an option to disable this in cases where
+   *       it is causing trouble. */
+  if (G.debug_value == 799) {
+    DEG::deg_graph_transitive_reduction(deg_graph);
+  }
+  /* Store pointers to commonly used valuated datablocks. */
+  deg_graph->scene_cow = (Scene *)deg_graph->get_cow_id(&deg_graph->scene->id);
+  /* Flush visibility layer and re-schedule nodes for update. */
+  DEG::deg_graph_build_finalize(bmain, deg_graph);
+  DEG_graph_on_visible_update(bmain, reinterpret_cast<::Depsgraph *>(deg_graph));
+#if 0
+  if (!DEG_debug_consistency_check(deg_graph)) {
+    printf("Consistency validation failed, ABORTING!\n");
+    abort();
+  }
+#endif
+  /* Relations are up to date. */
+  deg_graph->need_update = false;
+}
+
+/* Build depsgraph for the given scene layer, and dump results in given graph container. */
 void DEG_graph_build_from_view_layer(Depsgraph *graph,
                                      Main *bmain,
                                      Scene *scene,
@@ -245,34 +269,46 @@ void DEG_graph_build_from_view_layer(Depsgraph *graph,
   node_builder.begin_build();
   node_builder.build_view_layer(scene, view_layer, DEG::DEG_ID_LINKED_DIRECTLY);
   node_builder.end_build();
-  /* Hook up relationships between operations - to determine evaluation
-   * order. */
+  /* Hook up relationships between operations - to determine evaluation order. */
   DEG::DepsgraphRelationBuilder relation_builder(bmain, deg_graph, &builder_cache);
   relation_builder.begin_build();
   relation_builder.build_view_layer(scene, view_layer);
   relation_builder.build_copy_on_write_relations();
-  /* Detect and solve cycles. */
-  DEG::deg_graph_detect_cycles(deg_graph);
-  /* Simplify the graph by removing redundant relations (to optimize
-   * traversal later). */
-  /* TODO: it would be useful to have an option to disable this in cases where
-   *       it is causing trouble. */
-  if (G.debug_value == 799) {
-    DEG::deg_graph_transitive_reduction(deg_graph);
+  /* Finalize building. */
+  graph_build_finalize_common(deg_graph, bmain);
+  /* Finish statistics. */
+  if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) {
+    printf("Depsgraph built in %f seconds.\n", PIL_check_seconds_timer() - start_time);
   }
-  /* Store pointers to commonly used valuated datablocks. */
-  deg_graph->scene_cow = (Scene *)deg_graph->get_cow_id(&deg_graph->scene->id);
-  /* Flush visibility layer and re-schedule nodes for update. */
-  DEG::deg_graph_build_finalize(bmain, deg_graph);
-  DEG_graph_on_visible_update(bmain, graph);
-#if 0
-  if (!DEG_debug_consistency_check(deg_graph)) {
-    printf("Consistency validation failed, ABORTING!\n");
-    abort();
+}
+
+void DEG_graph_build_for_render_pipeline(Depsgraph *graph,
+                                         Main *bmain,
+                                         Scene *scene,
+                                         ViewLayer * /*view_layer*/)
+{
+  double start_time = 0.0;
+  if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) {
+    start_time = PIL_check_seconds_timer();
   }
-#endif
-  /* Relations are up to date. */
-  deg_graph->need_update = false;
+  DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
+  /* Perform sanity checks. */
+  BLI_assert(deg_graph->scene == scene);
+  deg_graph->is_render_pipeline_depsgraph = true;
+  DEG::DepsgraphBuilderCache builder_cache;
+  /* Generate all the nodes in the graph first */
+  DEG::DepsgraphNodeBuilder node_builder(bmain, deg_graph, &builder_cache);
+  node_builder.begin_build();
+  node_builder.build_scene_render(scene);
+  node_builder.end_build();
+  /* Hook up relationships between operations - to determine evaluation
+   * order. */
+  DEG::DepsgraphRelationBuilder relation_builder(bmain, deg_graph, &builder_cache);
+  relation_builder.begin_build();
+  relation_builder.build_scene_render(scene);
+  relation_builder.build_copy_on_write_relations();
+  /* Finalize building. */
+  graph_build_finalize_common(deg_graph, bmain);
   /* Finish statistics. */
   if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) {
     printf("Depsgraph built in %f seconds.\n", PIL_check_seconds_timer() - start_time);
index 98c50bf6fdf4f610558d9b05288755ac4ca42913..d714a913b96ecb96099c128b6fe800b22d0cbe8a 100644 (file)
@@ -327,7 +327,7 @@ ViewLayer *get_original_view_layer(const Depsgraph *depsgraph, const IDNode *id_
     return BKE_view_layer_default_render(scene_orig);
   }
   /* Is possible to have scene linked indirectly (i.e. via the driver) which
-   * we need to support. Currently there aer issues somewhere else, which
+   * we need to support. Currently there are issues somewhere else, which
    * makes testing hard. This is a reported problem, so will eventually be
    * properly fixed.
    *
@@ -341,11 +341,17 @@ void scene_remove_unused_view_layers(const Depsgraph *depsgraph,
                                      Scene *scene_cow)
 {
   const ViewLayer *view_layer_input;
-  /* Indirectly linked scenes means it's not an input scene and not a set scene, and is pulled via
-   * some driver. Such scenes should not have view layers after copy. */
   if (id_node->linked_state == DEG_ID_LINKED_INDIRECTLY) {
+    /* Indirectly linked scenes means it's not an input scene and not a set scene, and is pulled
+     * via some driver. Such scenes should not have view layers after copy. */
     view_layer_input = NULL;
   }
+  else if (depsgraph->is_render_pipeline_depsgraph) {
+    /* If the dependency graph is used for post-processing (such as compositor) we do need to
+     * have access to its view layer names so can not remove any view layers.
+     * On a more positive side we can remove all the bases from all the view layers. */
+    return;
+  }
   else {
     view_layer_input = get_original_view_layer(depsgraph, id_node);
   }
@@ -372,6 +378,13 @@ void scene_remove_unused_view_layers(const Depsgraph *depsgraph,
   scene_cow->view_layers.last = view_layer_eval;
 }
 
+void scene_remove_all_bases(Scene *scene_cow)
+{
+  LISTBASE_FOREACH (ViewLayer *, view_layer, &scene_cow->view_layers) {
+    BLI_freelistN(&view_layer->object_bases);
+  }
+}
+
 /* Makes it so given view layer only has bases corresponding to enabled
  * objects. */
 void view_layer_remove_disabled_bases(const Depsgraph *depsgraph, ViewLayer *view_layer)
@@ -425,6 +438,11 @@ void scene_setup_view_layers_before_remap(const Depsgraph *depsgraph,
                                           Scene *scene_cow)
 {
   scene_remove_unused_view_layers(depsgraph, id_node, scene_cow);
+  /* If dependency graph is used for post-processing we don't need any bases and can free of them.
+   * Do it before re-mapping to make that process faster. */
+  if (depsgraph->is_render_pipeline_depsgraph) {
+    scene_remove_all_bases(scene_cow);
+  }
 }
 
 void scene_setup_view_layers_after_remap(const Depsgraph *depsgraph,
index e4a2afa4349e3e034b2cd148f36e5fd22c3b5b53..efa328cf14d8b9231d55b37592c9744482d626e5 100644 (file)
@@ -118,6 +118,11 @@ struct Render {
   /* render engine */
   struct RenderEngine *engine;
 
+  /* NOTE: This is a minimal dependency graph and evaluated scene which is enough to access view
+   * layer visibility and use for post-precessing (compositor and sequencer). */
+  Depsgraph *pipeline_depsgraph;
+  Scene *pipeline_scene_eval;
+
 #ifdef WITH_FREESTYLE
   struct Main *freestyle_bmain;
   ListBase freestyle_renders;
index 9c1c713ab9450f8e1692edcd4cc4b9ca499cd411..76767d0d1d8d1e6e9127431f3cacb2f42b7a9628 100644 (file)
@@ -74,6 +74,7 @@
 
 #include "DEG_depsgraph.h"
 #include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_debug.h"
 #include "DEG_depsgraph_query.h"
 
 #include "PIL_time.h"
@@ -1430,10 +1431,10 @@ static void free_all_freestyle_renders(void)
 /* returns fully composited render-result on given time step (in RenderData) */
 static void do_render_composite(Render *re)
 {
-  bNodeTree *ntree = re->scene->nodetree;
+  bNodeTree *ntree = re->pipeline_scene_eval->nodetree;
   int update_newframe = 0;
 
-  if (composite_needs_render(re->scene, 1)) {
+  if (composite_needs_render(re->pipeline_scene_eval, 1)) {
     /* save memory... free all cached images */
     ntreeFreeCache(ntree);
 
@@ -1471,7 +1472,7 @@ static void do_render_composite(Render *re)
   if (!re->test_break(re->tbh)) {
 
     if (ntree) {
-      ntreeCompositTagRender(re->scene);
+      ntreeCompositTagRender(re->pipeline_scene_eval);
     }
 
     if (ntree && re->scene->use_nodes && re->r.scemode & R_DOCOMP) {
@@ -1494,7 +1495,7 @@ static void do_render_composite(Render *re)
 
         RenderView *rv;
         for (rv = re->result->views.first; rv; rv = rv->next) {
-          ntreeCompositExecTree(re->scene,
+          ntreeCompositExecTree(re->pipeline_scene_eval,
                                 ntree,
                                 &re->r,
                                 true,
@@ -1595,12 +1596,8 @@ static void do_render_seq(Render *re)
   tot_views = BKE_scene_multiview_num_views_get(&re->r);
   ibuf_arr = MEM_mallocN(sizeof(ImBuf *) * tot_views, "Sequencer Views ImBufs");
 
-  /* TODO(sergey): Currently depsgraph is only used to check whether it is an active
-   * edit window or not to deal with unkeyed changes. We don't have depsgraph here yet,
-   * but we also dont' deal with unkeyed changes. But still nice to get proper depsgraph
-   * within tjhe render pipeline, somehow.
-   */
-  BKE_sequencer_new_render_data(re->main, NULL, re->scene, re_x, re_y, 100, true, &context);
+  BKE_sequencer_new_render_data(
+      re->main, re->pipeline_depsgraph, re->scene, re_x, re_y, 100, true, &context);
 
   /* the renderresult gets destroyed during the rendering, so we first collect all ibufs
    * and then we populate the final renderesult */
@@ -1613,7 +1610,7 @@ static void do_render_seq(Render *re)
       ibuf_arr[view_id] = IMB_dupImBuf(out);
       IMB_metadata_copy(ibuf_arr[view_id], out);
       IMB_freeImBuf(out);
-      BKE_sequencer_imbuf_from_sequencer_space(re->scene, ibuf_arr[view_id]);
+      BKE_sequencer_imbuf_from_sequencer_space(re->pipeline_scene_eval, ibuf_arr[view_id]);
     }
     else {
       ibuf_arr[view_id] = NULL;
@@ -1641,9 +1638,9 @@ static void do_render_seq(Render *re)
       }
 
       if (recurs_depth == 0) { /* with nested scenes, only free on toplevel... */
-        Editing *ed = re->scene->ed;
+        Editing *ed = re->pipeline_scene_eval->ed;
         if (ed) {
-          BKE_sequencer_free_imbuf(re->scene, &ed->seqbase, true);
+          BKE_sequencer_free_imbuf(re->pipeline_scene_eval, &ed->seqbase, true);
         }
       }
       IMB_freeImBuf(ibuf_arr[view_id]);
@@ -2071,6 +2068,32 @@ void RE_SetReports(Render *re, ReportList *reports)
   re->reports = reports;
 }
 
+static void render_update_depsgraph(Render *re)
+{
+  Scene *scene = re->scene;
+  /* TODO(sergey): This doesn't run any callbacks and doesn't do sound update. But we can not use
+   * BKE_scene_graph_update_for_newframe() because that one builds dependency graph for view layer
+   * and not for the render pipeline. */
+  DEG_evaluate_on_framechange(re->main, re->pipeline_depsgraph, CFRA);
+}
+
+static void render_init_depsgraph(Render *re)
+{
+  Scene *scene = re->scene;
+  ViewLayer *view_layer = BKE_view_layer_default_render(re->scene);
+
+  re->pipeline_depsgraph = DEG_graph_new(scene, view_layer, DAG_EVAL_RENDER);
+  DEG_debug_name_set(re->pipeline_depsgraph, "RENDER PIPELINE");
+
+  /* Make sure there is a correct evaluated scene pointer. */
+  DEG_graph_build_for_render_pipeline(re->pipeline_depsgraph, re->main, scene, view_layer);
+
+  /* Update immediately so we have proper evaluated scene. */
+  render_update_depsgraph(re);
+
+  re->pipeline_scene_eval = DEG_get_evaluated_scene(re->pipeline_depsgraph);
+}
+
 /* general Blender frame render call */
 void RE_RenderFrame(Render *re,
                     Main *bmain,
@@ -2093,6 +2116,8 @@ void RE_RenderFrame(Render *re,
     const RenderData rd = scene->r;
     MEM_reset_peak_memory();
 
+    render_init_depsgraph(re);
+
     BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_PRE);
 
     do_render_all_options(re);
@@ -2490,6 +2515,8 @@ void RE_RenderAnim(Render *re,
     return;
   }
 
+  render_init_depsgraph(re);
+
   if (is_movie) {
     size_t width, height;
     int i;
@@ -2556,6 +2583,8 @@ void RE_RenderAnim(Render *re,
         BKE_animsys_evaluate_animdata(NULL, scene, &scene->id, adt, ctime, ADT_RECALC_ALL);
       }
 
+      render_update_depsgraph(re);
+
       /* only border now, todo: camera lens. (ton) */
       render_initialize_from_main(re, &rd, bmain, scene, single_layer, camera_override, 1, 0);
 
@@ -2746,6 +2775,11 @@ void RE_CleanAfterRender(Render *re)
 {
   /* Destroy the opengl context in the correct thread. */
   RE_gl_context_destroy(re);
+  if (re->pipeline_depsgraph != NULL) {
+    DEG_graph_free(re->pipeline_depsgraph);
+  }
+  re->pipeline_depsgraph = NULL;
+  re->pipeline_scene_eval = NULL;
 }
 
 /* note; repeated win/disprect calc... solve that nicer, also in compo */