[Bf-blender-cvs] [bb49aa0d697] master: Cycles: multithreaded export of geometry

Jagannadhan Ravi noreply at git.blender.org
Wed Oct 21 18:55:44 CEST 2020


Commit: bb49aa0d6978c2194de7835a0531f2cecd849372
Author: Jagannadhan Ravi
Date:   Wed Oct 21 16:38:36 2020 +0200
Branches: master
https://developer.blender.org/rBbb49aa0d6978c2194de7835a0531f2cecd849372

Cycles: multithreaded export of geometry

This improves performance in scene synchronization when there are many
mesh, hair and volume objects. Sync time speedups in benchmarks:

barbershop   5.2x
bmw          1.3x
fishycat     1.5x
koro         1.0x
sponza       3.0x
victor       1.4x
wdas_cloud   0.9x

Implementation by Nicolas Lelong, and Jagannadhan Ravi (AMD).

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

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

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

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

diff --git a/intern/cycles/blender/blender_geometry.cpp b/intern/cycles/blender/blender_geometry.cpp
index 002f5e0fdb7..14da8075903 100644
--- a/intern/cycles/blender/blender_geometry.cpp
+++ b/intern/cycles/blender/blender_geometry.cpp
@@ -25,6 +25,7 @@
 #include "blender/blender_util.h"
 
 #include "util/util_foreach.h"
+#include "util/util_task.h"
 
 CCL_NAMESPACE_BEGIN
 
@@ -45,7 +46,8 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
                                      BL::Object &b_ob,
                                      BL::Object &b_ob_instance,
                                      bool object_updated,
-                                     bool use_particle_hair)
+                                     bool use_particle_hair,
+                                     TaskPool *task_pool)
 {
   /* Test if we can instance or if the object is modified. */
   BL::ID b_ob_data = b_ob.data();
@@ -77,8 +79,15 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
       used_shaders.push_back(default_shader);
   }
 
-  /* Test if we need to sync. */
+  /* Ensure we only sync instanced geometry once. */
   Geometry *geom = geometry_map.find(key);
+  if (geom) {
+    if (geometry_synced.find(geom) != geometry_synced.end()) {
+      return geom;
+    }
+  }
+
+  /* Test if we need to sync. */
   bool sync = true;
   if (geom == NULL) {
     /* Add new geometry if it did not exist yet. */
@@ -125,28 +134,36 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
     }
   }
 
-  /* Ensure we only sync instanced geometry once. */
-  if (geometry_synced.find(geom) != geometry_synced.end()) {
-    return geom;
-  }
-
-  progress.set_sync_status("Synchronizing object", b_ob.name());
-
   geometry_synced.insert(geom);
 
   geom->name = ustring(b_ob_data.name().c_str());
 
-  if (geom_type == Geometry::HAIR) {
-    Hair *hair = static_cast<Hair *>(geom);
-    sync_hair(b_depsgraph, b_ob, hair, used_shaders);
-  }
-  else if (geom_type == Geometry::VOLUME) {
-    Volume *volume = static_cast<Volume *>(geom);
-    sync_volume(b_ob, volume, used_shaders);
+  auto sync_func = [=]() mutable {
+    if (progress.get_cancel())
+      return;
+
+    progress.set_sync_status("Synchronizing object", b_ob.name());
+
+    if (geom_type == Geometry::HAIR) {
+      Hair *hair = static_cast<Hair *>(geom);
+      sync_hair(b_depsgraph, b_ob, hair, used_shaders);
+    }
+    else if (geom_type == Geometry::VOLUME) {
+      Volume *volume = static_cast<Volume *>(geom);
+      sync_volume(b_ob, volume, used_shaders);
+    }
+    else {
+      Mesh *mesh = static_cast<Mesh *>(geom);
+      sync_mesh(b_depsgraph, b_ob, mesh, used_shaders);
+    }
+  };
+
+  /* Defer the actual geometry sync to the task_pool for multithreading */
+  if (task_pool) {
+    task_pool->push(sync_func);
   }
   else {
-    Mesh *mesh = static_cast<Mesh *>(geom);
-    sync_mesh(b_depsgraph, b_ob, mesh, used_shaders);
+    sync_func();
   }
 
   return geom;
@@ -156,7 +173,8 @@ void BlenderSync::sync_geometry_motion(BL::Depsgraph &b_depsgraph,
                                        BL::Object &b_ob,
                                        Object *object,
                                        float motion_time,
-                                       bool use_particle_hair)
+                                       bool use_particle_hair,
+                                       TaskPool *task_pool)
 {
   /* Ensure we only sync instanced geometry once. */
   Geometry *geom = object->geometry;
@@ -177,16 +195,29 @@ void BlenderSync::sync_geometry_motion(BL::Depsgraph &b_depsgraph,
     return;
   }
 
-  if (b_ob.type() == BL::Object::type_HAIR || use_particle_hair) {
-    Hair *hair = static_cast<Hair *>(geom);
-    sync_hair_motion(b_depsgraph, b_ob, hair, motion_step);
-  }
-  else if (b_ob.type() == BL::Object::type_VOLUME || object_fluid_gas_domain_find(b_ob)) {
-    /* No volume motion blur support yet. */
+  auto sync_func = [=]() mutable {
+    if (progress.get_cancel())
+      return;
+
+    if (b_ob.type() == BL::Object::type_HAIR || use_particle_hair) {
+      Hair *hair = static_cast<Hair *>(geom);
+      sync_hair_motion(b_depsgraph, b_ob, hair, motion_step);
+    }
+    else if (b_ob.type() == BL::Object::type_VOLUME || object_fluid_gas_domain_find(b_ob)) {
+      /* No volume motion blur support yet. */
+    }
+    else {
+      Mesh *mesh = static_cast<Mesh *>(geom);
+      sync_mesh_motion(b_depsgraph, b_ob, mesh, motion_step);
+    }
+  };
+
+  /* Defer the actual geometry sync to the task_pool for multithreading */
+  if (task_pool) {
+    task_pool->push(sync_func);
   }
   else {
-    Mesh *mesh = static_cast<Mesh *>(geom);
-    sync_mesh_motion(b_depsgraph, b_ob, mesh, motion_step);
+    sync_func();
   }
 }
 
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index 212b9cbe103..c3420c24469 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -32,6 +32,7 @@
 #include "util/util_foreach.h"
 #include "util/util_hash.h"
 #include "util/util_logging.h"
+#include "util/util_task.h"
 
 CCL_NAMESPACE_BEGIN
 
@@ -103,7 +104,8 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
                                  bool use_particle_hair,
                                  bool show_lights,
                                  BlenderObjectCulling &culling,
-                                 bool *use_portal)
+                                 bool *use_portal,
+                                 TaskPool *geom_task_pool)
 {
   const bool is_instance = b_instance.is_instance();
   BL::Object b_ob = b_instance.object();
@@ -181,6 +183,10 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
     return NULL;
   }
 
+  /* Use task pool only for non-instances, since sync_dupli_particle accesses
+   * geometry. This restriction should be removed for better performance. */
+  TaskPool *object_geom_task_pool = (is_instance) ? NULL : geom_task_pool;
+
   /* key to lookup object */
   ObjectKey key(b_parent, persistent_id, b_ob_instance, use_particle_hair);
   Object *object;
@@ -198,7 +204,12 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
 
       /* mesh deformation */
       if (object->geometry)
-        sync_geometry_motion(b_depsgraph, b_ob, object, motion_time, use_particle_hair);
+        sync_geometry_motion(b_depsgraph,
+                             b_ob_instance,
+                             object,
+                             motion_time,
+                             use_particle_hair,
+                             object_geom_task_pool);
     }
 
     return object;
@@ -211,8 +222,15 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
     object_updated = true;
 
   /* mesh sync */
-  object->geometry = sync_geometry(
-      b_depsgraph, b_ob, b_ob_instance, object_updated, use_particle_hair);
+  /* b_ob is owned by the iterator and will go out of scope at the end of the block.
+   * b_ob_instance is the original object and will remain valid for deferred geometry
+   * sync. */
+  object->geometry = sync_geometry(b_depsgraph,
+                                   b_ob_instance,
+                                   b_ob_instance,
+                                   object_updated,
+                                   use_particle_hair,
+                                   object_geom_task_pool);
 
   /* special case not tracked by object update flags */
 
@@ -331,6 +349,9 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
                                BL::SpaceView3D &b_v3d,
                                float motion_time)
 {
+  /* Task pool for multithreaded geometry sync. */
+  TaskPool geom_task_pool;
+
   /* layer data */
   bool motion = motion_time != 0.0f;
 
@@ -355,8 +376,8 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
   const bool show_lights = BlenderViewportParameters(b_v3d).use_scene_lights;
 
   BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval();
-
   BL::Depsgraph::object_instances_iterator b_instance_iter;
+
   for (b_depsgraph.object_instances.begin(b_instance_iter);
        b_instance_iter != b_depsgraph.object_instances.end() && !cancel;
        ++b_instance_iter) {
@@ -381,7 +402,8 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
                   false,
                   show_lights,
                   culling,
-                  &use_portal);
+                  &use_portal,
+                  &geom_task_pool);
     }
 
     /* Particle hair as separate object. */
@@ -393,12 +415,15 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
                   true,
                   show_lights,
                   culling,
-                  &use_portal);
+                  &use_portal,
+                  &geom_task_pool);
     }
 
     cancel = progress.get_cancel();
   }
 
+  geom_task_pool.wait_work();
+
   progress.set_sync_status("");
 
   if (!cancel && !motion) {
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index 62fd1ac2351..a17db128957 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -50,6 +50,7 @@ class ViewLayer;
 class Shader;
 class ShaderGraph;
 class ShaderNode;
+class TaskPool;
 
 class BlenderSync {
  public:
@@ -145,7 +146,8 @@ class BlenderSync {
                       bool use_particle_hair,
                       bool show_lights,
                       BlenderObjectCulling &culling,
-                      bool *use_portal);
+                      bool *use_portal,
+                      TaskPool *geom_task_pool);
 
   /* Volume */
   void sync_volume(BL::Object &b_ob, Volume *volume, const vector<Shader *> &used_shaders);
@@ -177,12 +179,15 @@ class BlenderSync {
                           BL::Object &b_ob,
                           BL::Object &b_ob_instance,
                           bool object_updated,
-                          bool use_particle_hair);
+                          bool use_particle_hair,
+                          TaskPool *task_pool);
+
   void sync_geometry_motion(BL::Depsgraph &b_depsgraph,
        

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list