[Bf-blender-cvs] [593af14] cycles_bvh: Cycles: Fix crash when true displacement is used

Sergey Sharybin noreply at git.blender.org
Wed Jun 15 11:39:16 CEST 2016


Commit: 593af14c87a8a04544c66f5d2d243bbbac6a832b
Author: Sergey Sharybin
Date:   Wed Jun 15 10:47:46 2016 +0200
Branches: cycles_bvh
https://developer.blender.org/rB593af14c87a8a04544c66f5d2d243bbbac6a832b

Cycles: Fix crash when true displacement is used

Not fastest code from device_update() timing point of view, but
keeps memory usage same small as final renders.

At this point we are back to full test suit pass when QBVH is used.

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

M	intern/cycles/render/mesh.cpp
M	intern/cycles/render/mesh.h

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

diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index d1de262..661719e 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -1115,7 +1115,11 @@ void MeshManager::mesh_calc_offset(Scene *scene)
 	}
 }
 
-void MeshManager::device_update_mesh(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
+void MeshManager::device_update_mesh(Device *device,
+                                     DeviceScene *dscene,
+                                     Scene *scene,
+                                     bool for_displacement,
+                                     Progress& progress)
 {
 	/* Count. */
 	size_t vert_size = 0;
@@ -1129,15 +1133,25 @@ void MeshManager::device_update_mesh(Device *device, DeviceScene *dscene, Scene
 		curve_size += mesh->num_curves();
 	}
 	/* Create mapping from triangle to primitive triangle array. */
-	vector<uint> tri_prim_index;
-	PackedBVH& pack = bvh->pack;
-	tri_prim_index.resize(tri_size);
-	for(size_t i = 0; i < tri_size; ++i) {
-		tri_prim_index[i] = -1;
+	vector<uint> tri_prim_index(tri_size);
+	if(for_displacement) {
+		/* For displacement kernels we do some trickery to make them believe
+		 * we've got all required data ready. However, that data is different
+		 * from final render kernels since we don't have BVH yet, so can't
+		 * really use same semantic of arrays.
+		 */
+		foreach(Mesh *mesh, scene->meshes) {
+			for(size_t i = 0; i < mesh->num_triangles(); ++i) {
+				tri_prim_index[i + mesh->tri_offset] = 3 * (i + mesh->tri_offset);
+			}
+		}
 	}
-	for(size_t i = 0; i < pack.prim_index.size(); ++i) {
-		if ((pack.prim_type[i] & PRIMITIVE_ALL_TRIANGLE) != 0) {
-			tri_prim_index[pack.prim_index[i]] = pack.prim_tri_index[i];
+	else {
+		PackedBVH& pack = bvh->pack;
+		for(size_t i = 0; i < pack.prim_index.size(); ++i) {
+			if ((pack.prim_type[i] & PRIMITIVE_ALL_TRIANGLE) != 0) {
+				tri_prim_index[pack.prim_index[i]] = pack.prim_tri_index[i];
+			}
 		}
 	}
 	/* Fill in all the arrays. */
@@ -1181,6 +1195,19 @@ void MeshManager::device_update_mesh(Device *device, DeviceScene *dscene, Scene
 		device->tex_alloc("__curve_keys", dscene->curve_keys);
 		device->tex_alloc("__curves", dscene->curves);
 	}
+	if(for_displacement) {
+		float4 *prim_tri_verts = dscene->prim_tri_verts.resize(tri_size * 3);
+		foreach(Mesh *mesh, scene->meshes) {
+			for(size_t i = 0; i < mesh->num_triangles(); ++i) {
+				Mesh::Triangle t = mesh->get_triangle(i);
+				size_t offset = 3 * (i + mesh->tri_offset);
+				prim_tri_verts[offset + 0] = float3_to_float4(mesh->verts[t.v[0]]);
+				prim_tri_verts[offset + 1] = float3_to_float4(mesh->verts[t.v[1]]);
+				prim_tri_verts[offset + 2] = float3_to_float4(mesh->verts[t.v[2]]);
+			}
+		}
+		device->tex_alloc("__prim_tri_verts", dscene->prim_tri_verts);
+	}
 }
 
 void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
@@ -1327,7 +1354,7 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
 
 	VLOG(1) << "Total " << scene->meshes.size() << " meshes.";
 
-	/* update normals */
+	/* Update normals. */
 	foreach(Mesh *mesh, scene->meshes) {
 		foreach(Shader *shader, mesh->used_shaders) {
 			if(shader->need_update_attributes)
@@ -1343,17 +1370,17 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
 	}
 
 	/* Update images needed for true displacement. */
-	bool need_displacement_images = false;
+	bool true_displacement_used = false;
 	bool old_need_object_flags_update = false;
 	foreach(Mesh *mesh, scene->meshes) {
 		if(mesh->need_update &&
 		   mesh->displacement_method != Mesh::DISPLACE_BUMP)
 		{
-			need_displacement_images = true;
+			true_displacement_used = true;
 			break;
 		}
 	}
-	if(need_displacement_images) {
+	if(true_displacement_used) {
 		VLOG(1) << "Updating images used for true displacement.";
 		device_update_displacement_images(device, dscene, scene, progress);
 		old_need_object_flags_update = scene->object_manager->need_flags_update;
@@ -1364,48 +1391,47 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
 		                                           false);
 	}
 
-	/* device update */
+	/* Device update. */
 	device_free(device, dscene);
 
 	mesh_calc_offset(scene);
+	if(true_displacement_used) {
+		device_update_mesh(device, dscene, scene, true, progress);
+	}
 	if(progress.get_cancel()) return;
 
 	device_update_attributes(device, dscene, scene, progress);
 	if(progress.get_cancel()) return;
 
-	/* update displacement */
+	/* Update displacement. */
 	bool displacement_done = false;
-
-	/* TODO(sergey): With current arrays formulation true displacement will
-	 * crash. Need some magic to avoid this.
-	 */
-	foreach(Mesh *mesh, scene->meshes)
-		if(mesh->need_update && displace(device, dscene, scene, mesh, progress))
+	foreach(Mesh *mesh, scene->meshes) {
+		if(mesh->need_update &&
+		   displace(device, dscene, scene, mesh, progress))
+		{
 			displacement_done = true;
+		}
+	}
 
-	/* todo: properly handle cancel halfway displacement */
+	/* TODO: properly handle cancel halfway displacement */
 	if(progress.get_cancel()) return;
 
-	/* device re-update after displacement */
+	/* Device re-update after displacement. */
 	if(displacement_done) {
 		device_free(device, dscene);
 
-		device_update_mesh(device, dscene, scene, progress);
-		if(progress.get_cancel()) return;
-
 		device_update_attributes(device, dscene, scene, progress);
 		if(progress.get_cancel()) return;
 	}
 
-	/* update bvh */
+	/* Update bvh. */
 	size_t i = 0, num_bvh = 0;
-
-	foreach(Mesh *mesh, scene->meshes)
-		if(mesh->need_update && mesh->need_build_bvh())
+	foreach(Mesh *mesh, scene->meshes) {
+		if(mesh->need_update && mesh->need_build_bvh()) {
 			num_bvh++;
-
+		}
+	}
 	TaskPool pool;
-
 	foreach(Mesh *mesh, scene->meshes) {
 		if(mesh->need_update) {
 			pool.push(function_bind(&Mesh::compute_bvh,
@@ -1420,14 +1446,14 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
 			}
 		}
 	}
-
 	TaskPool::Summary summary;
 	pool.wait_work(&summary);
 	VLOG(2) << "Objects BVH build pool statistics:\n"
 	        << summary.full_report();
 
-	foreach(Shader *shader, scene->shaders)
+	foreach(Shader *shader, scene->shaders) {
 		shader->need_update_attributes = false;
+	}
 
 #ifdef __OBJECT_MOTION__
 	Scene::MotionType need_motion = scene->need_motion(device->info.advanced_shading);
@@ -1436,22 +1462,23 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
 	bool motion_blur = false;
 #endif
 
-	/* update obejcts */
+	/* Update objects. */
 	vector<Object *> volume_objects;
-	foreach(Object *object, scene->objects)
+	foreach(Object *object, scene->objects) {
 		object->compute_bounds(motion_blur);
+	}
 
 	if(progress.get_cancel()) return;
 
 	device_update_bvh(device, dscene, scene, progress);
 	if(progress.get_cancel()) return;
 
-	device_update_mesh(device, dscene, scene, progress);
+	device_update_mesh(device, dscene, scene, false, progress);
 	if(progress.get_cancel()) return;
 
 	need_update = false;
 
-	if(need_displacement_images) {
+	if(true_displacement_used) {
 		/* Re-tag flags for update, so they're re-evaluated
 		 * for meshes with correct bounding boxes.
 		 *
diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h
index a091c45..0aea555 100644
--- a/intern/cycles/render/mesh.h
+++ b/intern/cycles/render/mesh.h
@@ -238,11 +238,31 @@ protected:
 	/* Calculate verts/triangles/curves offsets in global arrays. */
 	void mesh_calc_offset(Scene *scene);
 
-	void device_update_object(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
-	void device_update_mesh(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
-	void device_update_attributes(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
-	void device_update_bvh(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
-	void device_update_displacement_images(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
+	void device_update_object(Device *device,
+	                          DeviceScene *dscene,
+	                          Scene *scene,
+	                          Progress& progress);
+
+	void device_update_mesh(Device *device,
+	                        DeviceScene *dscene,
+	                        Scene *scene,
+	                        bool for_displacement,
+	                        Progress& progress);
+
+	void device_update_attributes(Device *device,
+	                              DeviceScene *dscene,
+	                              Scene *scene,
+	                              Progress& progress);
+
+	void device_update_bvh(Device *device,
+	                       DeviceScene *dscene,
+	                       Scene *scene,
+	                       Progress& progress);
+
+	void device_update_displacement_images(Device *device,
+	                                       DeviceScene *dscene,
+	                                       Scene *scene,
+	                                       Progress& progress);
 };
 
 CCL_NAMESPACE_END




More information about the Bf-blender-cvs mailing list