[Bf-blender-cvs] [97f1e4782a6] master: Cycles: Avoid unnecessary data updates in viewport

Sergey Sharybin noreply at git.blender.org
Tue May 18 10:13:37 CEST 2021


Commit: 97f1e4782a6fbc350f23a7f5c8520ffdf391f26c
Author: Sergey Sharybin
Date:   Mon May 17 18:23:44 2021 +0200
Branches: master
https://developer.blender.org/rB97f1e4782a6fbc350f23a7f5c8520ffdf391f26c

Cycles: Avoid unnecessary data updates in viewport

The BlenderSync will do quite a bit of work on every sync_data() call
even if there is nothing changed in the scene. There will be early
outputs done deeper in the call graph, but this is not really enough to
ensure best performance during viewport navigation.

This change makes it so sync_data() is only used when dependency graph
has any update tags: if something changed in the scene the dependency
graph will know it. If nothing changed there will be no IDs tagged for an
update in the dependency graph.

There are two weak parts in the current change:

- With the persistent data there is a special call to ignore the check
  of the dependency graph tags. This is more of a safety, because it is
  not immediately clear what the correct state of recalc flags is.

- Deletion of objects is detected indirectly, via tags of scene and
  collections.

It might not be bad for the first version of the change.

The test file used: {F10117322}

Simply open the file, start viewport render, and navigate the viewport.
On my computer this avoids 0.2sec spend on data_sync() on every
up[date of viewport navigation.

We can do way more granular updates in the future: for example, avoid
heavy objects sync when it is only camera object which changed. This
will need an extended support from the dependency graph API. Doing
nothing if nothing is changed is something we would want to do anyway.

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

===================================================================

M	intern/cycles/blender/blender_sync.cpp
M	intern/cycles/blender/blender_sync.h

===================================================================

diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index 4af8da402b1..9d0f9f29f94 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -69,7 +69,8 @@ BlenderSync::BlenderSync(BL::RenderEngine &b_engine,
       experimental(false),
       dicing_rate(1.0f),
       max_subdivisions(12),
-      progress(progress)
+      progress(progress),
+      has_updates_(true)
 {
   PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
   dicing_rate = preview ? RNA_float_get(&cscene, "preview_dicing_rate") :
@@ -84,7 +85,9 @@ BlenderSync::~BlenderSync()
 void BlenderSync::reset(BL::BlendData &b_data, BL::Scene &b_scene)
 {
   /* Update data and scene pointers in case they change in session reset,
-   * for example after undo. */
+   * for example after undo.
+   * Note that we do not modify the `has_updates_` flag here because the sync
+   * reset is also used during viewport navigation. */
   this->b_data = b_data;
   this->b_scene = b_scene;
 }
@@ -117,6 +120,8 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
     }
 
     if (dicing_prop_changed) {
+      has_updates_ = true;
+
       for (const pair<const GeometryKey, Geometry *> &iter : geometry_map.key_to_scene_data()) {
         Geometry *geom = iter.second;
         if (geom->is_mesh()) {
@@ -133,6 +138,12 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
 
   /* Iterate over all IDs in this depsgraph. */
   for (BL::DepsgraphUpdate &b_update : b_depsgraph.updates) {
+    /* TODO(sergey): Can do more selective filter here. For example, ignore changes made to
+     * screen datablock. Note that sync_data() needs to be called after object deletion, and
+     * currently this is ensured by the scene ID tagged for update, which sets the `has_updates_`
+     * flag. */
+    has_updates_ = true;
+
     BL::ID b_id(b_update.id());
 
     /* Material */
@@ -227,6 +238,10 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render,
                             int height,
                             void **python_thread_state)
 {
+  if (!has_updates_) {
+    return;
+  }
+
   scoped_timer timer;
 
   BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval();
@@ -254,6 +269,8 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render,
   free_data_after_sync(b_depsgraph);
 
   VLOG(1) << "Total time spent synchronizing data: " << timer.get_time();
+
+  has_updates_ = false;
 }
 
 /* Integrator */
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index a222c5e490e..15a10f2b46b 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -264,6 +264,12 @@ class BlenderSync {
   } view_layer;
 
   Progress &progress;
+
+ protected:
+  /* Indicates that `sync_recalc()` detected changes in the scene.
+   * If this flag is false then the data is considered to be up-to-date and will not be
+   * synchronized at all. */
+  bool has_updates_ = true;
 };
 
 CCL_NAMESPACE_END



More information about the Bf-blender-cvs mailing list