From 0fa7e4c853e07cfc6bd898c85cd0aa3119f97aa8 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 3 Oct 2014 12:11:19 +0200 Subject: [PATCH] Cycles: Decouple object flags update to a separate update step 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 | 35 ++++-------------- intern/cycles/render/object.cpp | 63 ++++++++++++++++++++++----------- intern/cycles/render/object.h | 1 + intern/cycles/render/scene.cpp | 5 +++ 4 files changed, 55 insertions(+), 49 deletions(-) diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index db6311c3d97..42103396b53 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -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 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; diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 986a36ba120..46ddab235d9 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -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 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); diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h index 677526b715f..2c69b83a2e9 100644 --- a/intern/cycles/render/object.h +++ b/intern/cycles/render/object.h @@ -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); diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index d0de8c51300..6c3f98bc9b0 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -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);