[Bf-blender-cvs] [cac3d4d1669] master: Cycles: fix inefficient attribute map storage, saves 615MB in victor scene.

Brecht Van Lommel noreply at git.blender.org
Sun Nov 5 20:49:05 CET 2017


Commit: cac3d4d16691d77e8e01f158be07d182e56e9755
Author: Brecht Van Lommel
Date:   Sun Nov 5 17:40:36 2017 +0100
Branches: master
https://developer.blender.org/rBcac3d4d16691d77e8e01f158be07d182e56e9755

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

===================================================================

M	intern/cycles/kernel/geom/geom_attribute.h
M	intern/cycles/kernel/geom/geom_motion_curve.h
M	intern/cycles/kernel/geom/geom_motion_triangle.h
M	intern/cycles/kernel/kernel_types.h
M	intern/cycles/render/mesh.cpp
M	intern/cycles/render/mesh.h
M	intern/cycles/render/object.cpp
M	intern/cycles/render/object.h

===================================================================

diff --git a/intern/cycles/kernel/geom/geom_attribute.h b/intern/cycles/kernel/geom/geom_attribute.h
index cc62192ef21..18f5c813cc8 100644
--- a/intern/cycles/kernel/geom/geom_attribute.h
+++ b/intern/cycles/kernel/geom/geom_attribute.h
@@ -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);
 	
diff --git a/intern/cycles/kernel/geom/geom_motion_curve.h b/intern/cycles/kernel/geom/geom_motion_curve.h
index 119bdb2f15c..fad29e431ec 100644
--- a/intern/cycles/kernel/geom/geom_motion_curve.h
+++ b/intern/cycles/kernel/geom/geom_motion_curve.h
@@ -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) {
diff --git a/intern/cycles/kernel/geom/geom_motion_triangle.h b/intern/cycles/kernel/geom/geom_motion_triangle.h
index 4e84aa97776..cd28b75c22c 100644
--- a/intern/cycles/kernel/geom/geom_motion_triangle.h
+++ b/intern/cycles/kernel/geom/geom_motion_triangle.h
@@ -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) {
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 49ec6d97f28..d1733d8a6e7 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -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);
 
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index 75bdf71616f..189ba80ad2a 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -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;
 
diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h
index 30f5e9063e6..07d8bbdbf31 100644
--- a/intern/cycles/render/mesh.h
+++ b/intern/cycles/render/mesh.h
@@ -250,6 +250,8 @@ public:
 	size_t face_offset;
 	size_t corner_offset;
 
+	size_t attr_map_offset;
+
 	size_t num_subd_verts;
 
 	/* Functions */
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index 3b93b0c0d1e..a12a0d297f0 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -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++;
 	}
 
diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h
index 6927bbfe4c7..9f86c342acd 100644
--- a/intern/cycles/render/object.h
+++ b/intern/cycles/render/object.h
@@ -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);



More information about the Bf-blender-cvs mailing list