Cycles: fix inefficient attribute map storage, saves 615MB in victor scene.

This commit is contained in:
Brecht Van Lommel 2017-11-05 17:40:36 +01:00
parent 5801ef71e4
commit cac3d4d166
8 changed files with 43 additions and 34 deletions

View File

@ -51,14 +51,21 @@ ccl_device_inline AttributeDescriptor attribute_not_found()
/* Find attribute based on ID */
ccl_device_inline uint object_attribute_map_offset(KernelGlobals *kg, int object)
{
int offset = object*OBJECT_SIZE + 11;
float4 f = kernel_tex_fetch(__objects, offset);
return __float_as_uint(f.y);
}
ccl_device_inline AttributeDescriptor find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id)
{
if(sd->object == PRIM_NONE) {
if(sd->object == OBJECT_NONE) {
return attribute_not_found();
}
/* for SVM, find attribute by unique id */
uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
uint attr_offset = object_attribute_map_offset(kg, sd->object);
attr_offset += attribute_primitive_type(kg, sd);
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);

View File

@ -33,7 +33,7 @@ ccl_device_inline int find_attribute_curve_motion(KernelGlobals *kg, int object,
* zero iterations and rendering is really slow with motion curves. For until other
* areas are speed up it's probably not so crucial to optimize this out.
*/
uint attr_offset = object*kernel_data.bvh.attributes_map_stride + ATTR_PRIM_CURVE;
uint attr_offset = object_attribute_map_offset(kg, object) + ATTR_PRIM_CURVE;
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
while(attr_map.x != id) {

View File

@ -32,7 +32,7 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline int find_attribute_motion(KernelGlobals *kg, int object, uint id, AttributeElement *elem)
{
/* todo: find a better (faster) solution for this, maybe store offset per object */
uint attr_offset = object*kernel_data.bvh.attributes_map_stride;
uint attr_offset = object_attribute_map_offset(kg, object);
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
while(attr_map.x != id) {

View File

@ -1295,13 +1295,12 @@ static_assert_align(KernelIntegrator, 16);
typedef struct KernelBVH {
/* root node */
int root;
int attributes_map_stride;
int have_motion;
int have_curves;
int have_instancing;
int use_qbvh;
int use_bvh_steps;
int pad1;
int pad1, pad2;
} KernelBVH;
static_assert_align(KernelBVH, 16);

View File

@ -436,6 +436,8 @@ Mesh::Mesh()
face_offset = 0;
corner_offset = 0;
attr_map_offset = 0;
num_subd_verts = 0;
attributes.triangle_mesh = this;
@ -1258,33 +1260,27 @@ void MeshManager::update_svm_attributes(Device *, DeviceScene *dscene, Scene *sc
* attribute, based on a unique shader attribute id. */
/* compute array stride */
int attr_map_stride = 0;
int attr_map_size = 0;
for(size_t i = 0; i < scene->meshes.size(); i++)
attr_map_stride = max(attr_map_stride, (mesh_attributes[i].size() + 1)*ATTR_PRIM_TYPES);
for(size_t i = 0; i < scene->meshes.size(); i++) {
Mesh *mesh = scene->meshes[i];
mesh->attr_map_offset = attr_map_size;
attr_map_size += (mesh_attributes[i].size() + 1)*ATTR_PRIM_TYPES;
}
if(attr_map_stride == 0)
if(attr_map_size == 0)
return;
/* create attribute map */
uint4 *attr_map = dscene->attributes_map.alloc(attr_map_stride*scene->objects.size());
uint4 *attr_map = dscene->attributes_map.alloc(attr_map_size*scene->meshes.size());
memset(attr_map, 0, dscene->attributes_map.size()*sizeof(uint));
for(size_t i = 0; i < scene->objects.size(); i++) {
Object *object = scene->objects[i];
Mesh *mesh = object->mesh;
/* find mesh attributes */
size_t j;
for(j = 0; j < scene->meshes.size(); j++)
if(scene->meshes[j] == mesh)
break;
AttributeRequestSet& attributes = mesh_attributes[j];
for(size_t i = 0; i < scene->meshes.size(); i++) {
Mesh *mesh = scene->meshes[i];
AttributeRequestSet& attributes = mesh_attributes[i];
/* set object attributes */
int index = i*attr_map_stride;
int index = mesh->attr_map_offset;
foreach(AttributeRequest& req, attributes.requests) {
uint id;
@ -1358,7 +1354,6 @@ void MeshManager::update_svm_attributes(Device *, DeviceScene *dscene, Scene *sc
}
/* copy to device */
dscene->data.bvh.attributes_map_stride = attr_map_stride;
dscene->attributes_map.copy_to_device();
}
@ -1625,6 +1620,12 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
if(dscene->attributes_uchar4.size()) {
dscene->attributes_uchar4.copy_to_device();
}
if(progress.get_cancel()) return;
/* After mesh attributes and patch tables have been copied to device memory,
* we need to update offsets in the objects. */
scene->object_manager->device_update_mesh_offsets(device, dscene, scene);
}
void MeshManager::mesh_calc_offset(Scene *scene)
@ -2042,10 +2043,6 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
}
if(progress.get_cancel()) return;
/* after mesh data has been copied to device memory we need to update
* offsets for patch tables as this can't be known before hand */
scene->object_manager->device_update_patch_map_offsets(device, dscene, scene);
device_update_attributes(device, dscene, scene, progress);
if(progress.get_cancel()) return;

View File

@ -250,6 +250,8 @@ public:
size_t face_offset;
size_t corner_offset;
size_t attr_map_offset;
size_t num_subd_verts;
/* Functions */

View File

@ -641,7 +641,7 @@ void ObjectManager::device_update_flags(Device *,
dscene->object_flag.copy_to_device();
}
void ObjectManager::device_update_patch_map_offsets(Device *, DeviceScene *dscene, Scene *scene)
void ObjectManager::device_update_mesh_offsets(Device *, DeviceScene *dscene, Scene *scene)
{
if(scene->objects.size() == 0) {
return;
@ -650,12 +650,11 @@ void ObjectManager::device_update_patch_map_offsets(Device *, DeviceScene *dscen
uint4* objects = (uint4*)dscene->objects.data();
bool update = false;
int object_index = 0;
foreach(Object *object, scene->objects) {
int offset = object_index*OBJECT_SIZE + 11;
foreach(Object *object, scene->objects) {
Mesh* mesh = object->mesh;
int offset = object_index*OBJECT_SIZE + 11;
if(mesh->patch_table) {
uint patch_map_offset = 2*(mesh->patch_table_offset + mesh->patch_table->total_size() -
@ -667,6 +666,11 @@ void ObjectManager::device_update_patch_map_offsets(Device *, DeviceScene *dscen
}
}
if(objects[offset].y != mesh->attr_map_offset) {
objects[offset].y = mesh->attr_map_offset;
update = true;
}
object_index++;
}

View File

@ -104,7 +104,7 @@ public:
Scene *scene,
Progress& progress,
bool bounds_valid = true);
void device_update_patch_map_offsets(Device *device, DeviceScene *dscene, Scene *scene);
void device_update_mesh_offsets(Device *device, DeviceScene *dscene, Scene *scene);
void device_free(Device *device, DeviceScene *dscene);