Cycles: Decouple object flags update to a separate update step
authorSergey Sharybin <sergey.vfx@gmail.com>
Fri, 3 Oct 2014 10:11:19 +0000 (12:11 +0200)
committerSergey Sharybin <sergey.vfx@gmail.com>
Fri, 3 Oct 2014 10:13:41 +0000 (12:13 +0200)
This way there's much less cross-references between objects and meshes
device update functions.

The only thing remained s the object bounds calculation which is needed
by bvh update. This could also be decoupled, but it's not that crucial
yet because its's how it used to be for ages now.

intern/cycles/render/mesh.cpp
intern/cycles/render/object.cpp
intern/cycles/render/object.h
intern/cycles/render/scene.cpp

index db6311c3d9791d7d694b651db95a207edb415ad9..42103396b53b2e5f1b712864fd767ae4f47de828 100644 (file)
@@ -1032,11 +1032,15 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
        if(!need_update)
                return;
 
-       /* update normals */
+       /* update normals and flags */
        foreach(Mesh *mesh, scene->meshes) {
+               mesh->has_volume = false;
                foreach(uint shader, mesh->used_shaders) {
                        if(scene->shaders[shader]->need_update_attributes)
                                mesh->need_update = true;
+                       if(scene->shaders[shader]->has_volume) {
+                               mesh->has_volume = true;
+                       }
                }
 
                if(mesh->need_update) {
@@ -1105,37 +1109,10 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
        bool motion_blur = false;
 #endif
 
-       /* TODO(sergey): There's an ongoing fake cyclic dependency between objects
-        * and meshes here -- needs to make update functions a bit more granular in
-        * order to keep all the updates in a logical way.
-        */
-
        /* update obejcts */
        vector<Object *> volume_objects;
-       foreach(Object *object, scene->objects) {
+       foreach(Object *object, scene->objects)
                object->compute_bounds(motion_blur);
-               if(object->mesh->has_volume) {
-                       volume_objects.push_back(object);
-               }
-       }
-
-       int object_index = 0;
-       uint *object_flags = dscene->object_flag.get_data();
-       foreach(Object *object, scene->objects) {
-               foreach(Object *volume_object, volume_objects) {
-                       if(object == volume_object) {
-                               continue;
-                       }
-                       if(object->bounds.intersects(volume_object->bounds)) {
-                               object_flags[object_index] |= SD_OBJECT_INTERSECTS_VOLUME;
-                               break;
-                       }
-               }
-               ++object_index;
-       }
-
-       /* allocate object flag */
-       device->tex_alloc("__object_flag", dscene->object_flag);
 
        if(progress.get_cancel()) return;
 
index 986a36ba120002b1e53faee7c31b6cd5dd3c1cc0..46ddab235d98ba3df319d0cb9708fa4408c22638 100644 (file)
@@ -348,27 +348,9 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
                objects[offset+9] = make_float4(ob->dupli_generated[0], ob->dupli_generated[1], ob->dupli_generated[2], __int_as_float(numkeys));
                objects[offset+10] = make_float4(ob->dupli_uv[0], ob->dupli_uv[1], __int_as_float(numsteps), __int_as_float(numverts));
 
-               /* That's a bit weird place to update mesh flags, but we do it here
-                * because  object needs to know if it's a volume or not and mesh needs
-                * to have the updated.
-                *
-                * TODO(sergey): Check on whether we can reshuffle update order in scene.
-                */
-               if(ob->mesh->need_update) {
-                       ob->mesh->has_volume = false;
-                       foreach(uint shader, ob->mesh->used_shaders) {
-                               if(scene->shaders[shader]->has_volume) {
-                                       ob->mesh->has_volume = true;
-                                       break;
-                               }
-                       }
-               }
-
                /* object flag */
                if(ob->use_holdout)
                        flag |= SD_HOLDOUT_MASK;
-               if(ob->mesh->has_volume)
-                       flag |= SD_OBJECT_HAS_VOLUME;
                object_flag[i] = flag;
 
                /* have curves */
@@ -396,8 +378,6 @@ void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *sc
        
        device_free(device, dscene);
 
-       need_update = false;
-
        if(scene->objects.size() == 0)
                return;
 
@@ -418,6 +398,49 @@ void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *sc
        }
 }
 
+void ObjectManager::device_update_flags(Device *device, DeviceScene *dscene,
+                                        Scene *scene, Progress& progress)
+{
+       if(!need_update)
+               return;
+
+       need_update = false;
+
+       if(scene->objects.size() == 0)
+               return;
+
+       /* object info flag */
+       uint *object_flag = dscene->object_flag.get_data();
+
+       vector<Object *> volume_objects;
+       foreach(Object *object, scene->objects) {
+               if(object->mesh->has_volume) {
+                       volume_objects.push_back(object);
+               }
+       }
+
+       int object_index = 0;
+       foreach(Object *object, scene->objects) {
+               if(object->mesh->has_volume) {
+                       object_flag[object_index] |= SD_OBJECT_HAS_VOLUME;
+               }
+
+               foreach(Object *volume_object, volume_objects) {
+                       if(object == volume_object) {
+                               continue;
+                       }
+                       if(object->bounds.intersects(volume_object->bounds)) {
+                               object_flag[object_index] |= SD_OBJECT_INTERSECTS_VOLUME;
+                               break;
+                       }
+               }
+               ++object_index;
+       }
+
+       /* allocate object flag */
+       device->tex_alloc("__object_flag", dscene->object_flag);
+}
+
 void ObjectManager::device_free(Device *device, DeviceScene *dscene)
 {
        device->tex_free(dscene->objects);
index 677526b715f2256b2865e5920dd7560a08f77bbc..2c69b83a2e97636e88e0b0527f411f7e3c1fb516 100644 (file)
@@ -76,6 +76,7 @@ public:
 
        void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
        void device_update_transforms(Device *device, DeviceScene *dscene, Scene *scene, uint *object_flag, Progress& progress);
+       void device_update_flags(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
        void device_free(Device *device, DeviceScene *dscene);
 
        void tag_update(Scene *scene);
index d0de8c51300b9a12ae95579ddbf4474c29b61a9c..6c3f98bc9b012b43f5b80fdab618662f91f3bec2 100644 (file)
@@ -175,6 +175,11 @@ void Scene::device_update(Device *device_, Progress& progress)
 
        if(progress.get_cancel()) return;
 
+       progress.set_status("Updating Objects Flags");
+       object_manager->device_update_flags(device, &dscene, this, progress);
+
+       if(progress.get_cancel()) return;
+
        progress.set_status("Updating Hair Systems");
        curve_system_manager->device_update(device, &dscene, this, progress);