Cycles: fix inefficient attribute map storage, saves 615MB in victor scene.
This commit is contained in:
parent
5801ef71e4
commit
cac3d4d166
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -250,6 +250,8 @@ public:
|
|||
size_t face_offset;
|
||||
size_t corner_offset;
|
||||
|
||||
size_t attr_map_offset;
|
||||
|
||||
size_t num_subd_verts;
|
||||
|
||||
/* Functions */
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue