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.
This commit is contained in:
Sergey Sharybin 2014-10-03 12:11:19 +02:00
parent 9ce645e7d9
commit 0fa7e4c853
4 changed files with 55 additions and 49 deletions

@ -1032,11 +1032,15 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
if(!need_update) if(!need_update)
return; return;
/* update normals */ /* update normals and flags */
foreach(Mesh *mesh, scene->meshes) { foreach(Mesh *mesh, scene->meshes) {
mesh->has_volume = false;
foreach(uint shader, mesh->used_shaders) { foreach(uint shader, mesh->used_shaders) {
if(scene->shaders[shader]->need_update_attributes) if(scene->shaders[shader]->need_update_attributes)
mesh->need_update = true; mesh->need_update = true;
if(scene->shaders[shader]->has_volume) {
mesh->has_volume = true;
}
} }
if(mesh->need_update) { if(mesh->need_update) {
@ -1105,37 +1109,10 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
bool motion_blur = false; bool motion_blur = false;
#endif #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 */ /* update obejcts */
vector<Object *> volume_objects; vector<Object *> volume_objects;
foreach(Object *object, scene->objects) { foreach(Object *object, scene->objects)
object->compute_bounds(motion_blur); 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; if(progress.get_cancel()) return;

@ -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+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)); 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 */ /* object flag */
if(ob->use_holdout) if(ob->use_holdout)
flag |= SD_HOLDOUT_MASK; flag |= SD_HOLDOUT_MASK;
if(ob->mesh->has_volume)
flag |= SD_OBJECT_HAS_VOLUME;
object_flag[i] = flag; object_flag[i] = flag;
/* have curves */ /* have curves */
@ -396,8 +378,6 @@ void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *sc
device_free(device, dscene); device_free(device, dscene);
need_update = false;
if(scene->objects.size() == 0) if(scene->objects.size() == 0)
return; 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) void ObjectManager::device_free(Device *device, DeviceScene *dscene)
{ {
device->tex_free(dscene->objects); device->tex_free(dscene->objects);

@ -76,6 +76,7 @@ public:
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); 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_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 device_free(Device *device, DeviceScene *dscene);
void tag_update(Scene *scene); void tag_update(Scene *scene);

@ -175,6 +175,11 @@ void Scene::device_update(Device *device_, Progress& progress)
if(progress.get_cancel()) return; 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"); progress.set_status("Updating Hair Systems");
curve_system_manager->device_update(device, &dscene, this, progress); curve_system_manager->device_update(device, &dscene, this, progress);