[Bf-blender-cvs] [bfe812e] cycles_hair_bvh: Cycles: Use dedicated BVH for triangles and hair

Sergey Sharybin noreply at git.blender.org
Wed Apr 13 15:01:42 CEST 2016


Commit: bfe812e3c94af27fe468bd262e3590e940449e00
Author: Sergey Sharybin
Date:   Tue Apr 12 08:52:15 2016 +0200
Branches: cycles_hair_bvh
https://developer.blender.org/rBbfe812e3c94af27fe468bd262e3590e940449e00

Cycles: Use dedicated BVH for triangles and hair

This is a required step forward OBB type of BVH which will be more optimal
for hair but less optimal for triangles. Which means, we'll need to have
dedicated hair BVH once we'll start working on OBB BVH.

This commits does exactly that: there are now two separate BVH, one is
fully dedicated to triangles and another one is fully dedicated to hair.
They are built separately and also traversed separately.

This allows:

- Get rid of triangle storage for curve primitives, which solves memory
  usage issue without slowdown of triangles intersection test.

- Perform test against triangles for shadow rays, which will often lead
  to som speed gain because ray often hits opaque triangle and in this
  case it's not needed to do any ray-to-curve intersections.

Unfortunately, current implementation used 7 more textures, which is quite
bad on lower end GPUs due to tight number of textures limit, which means
less image textures can be used now.

Here are some numbers:

                               Master          Patch
Koro.blend
  Memory during render(Mb):    910             814
  Peak memory(Mb):             984             963
  Render time:                 5m 51s          5m 21s

Bunny.blend
  Memory during render(Mb):    8034            6375
  Peak memory(Mb):             9058            7713
  Render time:                 9, 25s          7m 44s

There are some render result difference with low number of samples,
probably because of different order of geometry hits when there are
multiple primitives at the same depth. But that's to be doublechecked.

There should be no affect on scenes with just triangles.

Since there are some interesting results already decided to put it
online for some more tests.

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

M	intern/cycles/bvh/bvh.cpp
M	intern/cycles/bvh/bvh_build.cpp
M	intern/cycles/bvh/bvh_params.h
M	intern/cycles/kernel/CMakeLists.txt
M	intern/cycles/kernel/geom/geom_bvh.h
M	intern/cycles/kernel/geom/geom_bvh_shadow.h
A	intern/cycles/kernel/geom/geom_bvh_shadow_hair.h
M	intern/cycles/kernel/geom/geom_bvh_traversal.h
A	intern/cycles/kernel/geom/geom_bvh_traversal_hair.h
M	intern/cycles/kernel/geom/geom_bvh_volume.h
M	intern/cycles/kernel/geom/geom_bvh_volume_all.h
M	intern/cycles/kernel/geom/geom_curve.h
M	intern/cycles/kernel/geom/geom_qbvh.h
M	intern/cycles/kernel/geom/geom_qbvh_shadow.h
A	intern/cycles/kernel/geom/geom_qbvh_shadow_hair.h
M	intern/cycles/kernel/geom/geom_qbvh_traversal.h
A	intern/cycles/kernel/geom/geom_qbvh_traversal_hair.h
M	intern/cycles/kernel/geom/geom_qbvh_volume.h
M	intern/cycles/kernel/geom/geom_qbvh_volume_all.h
M	intern/cycles/kernel/kernel_shader.h
M	intern/cycles/kernel/kernel_textures.h
M	intern/cycles/kernel/kernel_types.h
M	intern/cycles/kernel/svm/svm_image.h
M	intern/cycles/render/mesh.cpp
M	intern/cycles/render/mesh.h
M	intern/cycles/render/scene.h

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

diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp
index 9e63485..59ca170 100644
--- a/intern/cycles/bvh/bvh.cpp
+++ b/intern/cycles/bvh/bvh.cpp
@@ -145,34 +145,40 @@ void BVH::pack_primitives()
 	size_t tidx_size = pack.prim_index.size();
 
 	pack.tri_storage.clear();
-	pack.tri_storage.resize(tidx_size * nsize);
+	if(params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) {
+		pack.tri_storage.resize(tidx_size * nsize);
+	}
 	pack.prim_visibility.clear();
 	pack.prim_visibility.resize(tidx_size);
 
 	for(unsigned int i = 0; i < tidx_size; i++) {
 		if(pack.prim_index[i] != -1) {
-			float4 storage[3];
+			if(params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) {
+				float4 storage[3];
+				if(pack.prim_type[i] & PRIMITIVE_TRIANGLE) {
+					pack_triangle(i, storage);
+				}
+				else {
+					/* Avoid use of uninitialized memory. */
+					memset(&storage, 0, sizeof(storage));
+				}
 
-			if(pack.prim_type[i] & PRIMITIVE_TRIANGLE) {
-				pack_triangle(i, storage);
-			}
-			else {
-				/* Avoid use of uninitialized memory. */
-				memset(&storage, 0, sizeof(storage));
+				memcpy(&pack.tri_storage[i * nsize], storage, sizeof(float4)*3);
 			}
 
-			memcpy(&pack.tri_storage[i * nsize], storage, sizeof(float4)*3);
-
 			int tob = pack.prim_object[i];
 			Object *ob = objects[tob];
 			pack.prim_visibility[i] = ob->visibility;
 
-			if(pack.prim_type[i] & PRIMITIVE_ALL_CURVE)
+			if(pack.prim_type[i] & PRIMITIVE_ALL_CURVE) {
 				pack.prim_visibility[i] |= PATH_RAY_CURVE;
+			}
 		}
 		else {
-			memset(&pack.tri_storage[i * nsize], 0, sizeof(float4)*3);
-			pack.prim_visibility[i] = 0;
+			if(params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) {
+				memset(&pack.tri_storage[i * nsize], 0, sizeof(float4)*3);
+				pack.prim_visibility[i] = 0;
+			}
 		}
 	}
 }
@@ -220,7 +226,14 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
 
 	foreach(Object *ob, objects) {
 		Mesh *mesh = ob->mesh;
-		BVH *bvh = mesh->bvh;
+		BVH *bvh;
+		if(params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) {
+			bvh = mesh->triangle_bvh;
+		}
+		else {
+			assert(params.primitive_mask & PRIMITIVE_ALL_CURVE);
+			bvh = mesh->curve_bvh;
+		}
 
 		if(mesh->need_build_bvh()) {
 			if(mesh_map.find(mesh) == mesh_map.end()) {
@@ -275,7 +288,14 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
 			continue;
 		}
 
-		BVH *bvh = mesh->bvh;
+		BVH *bvh;
+		if(params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) {
+			bvh = mesh->triangle_bvh;
+		}
+		else {
+			assert(params.primitive_mask & PRIMITIVE_ALL_CURVE);
+			bvh = mesh->curve_bvh;
+		}
 
 		int noffset = nodes_offset/nsize;
 		int noffset_leaf = nodes_leaf_offset/nsize_leaf;
diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp
index d666805..d5efbe5 100644
--- a/intern/cycles/bvh/bvh_build.cpp
+++ b/intern/cycles/bvh/bvh_build.cpp
@@ -112,68 +112,72 @@ BVHBuild::~BVHBuild()
 
 void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, int i)
 {
-	Attribute *attr_mP = NULL;
-	
-	if(mesh->has_motion_blur())
-		attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+	if(params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) {
+		Attribute *attr_mP = NULL;
 
-	for(uint j = 0; j < mesh->triangles.size(); j++) {
-		Mesh::Triangle t = mesh->triangles[j];
-		BoundBox bounds = BoundBox::empty;
-		PrimitiveType type = PRIMITIVE_TRIANGLE;
+		if(mesh->has_motion_blur())
+			attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
 
-		t.bounds_grow(&mesh->verts[0], bounds);
+		for(uint j = 0; j < mesh->triangles.size(); j++) {
+			Mesh::Triangle t = mesh->triangles[j];
+			BoundBox bounds = BoundBox::empty;
+			PrimitiveType type = PRIMITIVE_TRIANGLE;
 
-		/* motion triangles */
-		if(attr_mP) {
-			size_t mesh_size = mesh->verts.size();
-			size_t steps = mesh->motion_steps - 1;
-			float3 *vert_steps = attr_mP->data_float3();
+			t.bounds_grow(&mesh->verts[0], bounds);
 
-			for(size_t i = 0; i < steps; i++)
-				t.bounds_grow(vert_steps + i*mesh_size, bounds);
+			/* motion triangles */
+			if(attr_mP) {
+				size_t mesh_size = mesh->verts.size();
+				size_t steps = mesh->motion_steps - 1;
+				float3 *vert_steps = attr_mP->data_float3();
 
-			type = PRIMITIVE_MOTION_TRIANGLE;
-		}
+				for(size_t i = 0; i < steps; i++)
+					t.bounds_grow(vert_steps + i*mesh_size, bounds);
 
-		if(bounds.valid()) {
-			references.push_back(BVHReference(bounds, j, i, type));
-			root.grow(bounds);
-			center.grow(bounds.center2());
+				type = PRIMITIVE_MOTION_TRIANGLE;
+			}
+
+			if(bounds.valid()) {
+				references.push_back(BVHReference(bounds, j, i, type));
+				root.grow(bounds);
+				center.grow(bounds.center2());
+			}
 		}
 	}
 
-	Attribute *curve_attr_mP = NULL;
+	if(params.primitive_mask & PRIMITIVE_ALL_CURVE) {
+		Attribute *curve_attr_mP = NULL;
 
-	if(mesh->has_motion_blur())
-		curve_attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+		if(mesh->has_motion_blur())
+			curve_attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
 
-	for(uint j = 0; j < mesh->curves.size(); j++) {
-		Mesh::Curve curve = mesh->curves[j];
-		PrimitiveType type = PRIMITIVE_CURVE;
+		for(uint j = 0; j < mesh->curves.size(); j++) {
+			Mesh::Curve curve = mesh->curves[j];
+			PrimitiveType type = PRIMITIVE_CURVE;
 
-		for(int k = 0; k < curve.num_keys - 1; k++) {
-			BoundBox bounds = BoundBox::empty;
-			curve.bounds_grow(k, &mesh->curve_keys[0], bounds);
+			for(int k = 0; k < curve.num_keys - 1; k++) {
+				BoundBox bounds = BoundBox::empty;
+				curve.bounds_grow(k, &mesh->curve_keys[0], bounds);
 
-			/* motion curve */
-			if(curve_attr_mP) {
-				size_t mesh_size = mesh->curve_keys.size();
-				size_t steps = mesh->motion_steps - 1;
-				float4 *key_steps = curve_attr_mP->data_float4();
+				/* motion curve */
+				if(curve_attr_mP) {
+					size_t mesh_size = mesh->curve_keys.size();
+					size_t steps = mesh->motion_steps - 1;
+					float4 *key_steps = curve_attr_mP->data_float4();
 
-				for(size_t i = 0; i < steps; i++)
-					curve.bounds_grow(k, key_steps + i*mesh_size, bounds);
+					for(size_t i = 0; i < steps; i++)
+						curve.bounds_grow(k, key_steps + i*mesh_size, bounds);
 
-				type = PRIMITIVE_MOTION_CURVE;
-			}
+					type = PRIMITIVE_MOTION_CURVE;
+				}
 
-			if(bounds.valid()) {
-				int packed_type = PRIMITIVE_PACK_SEGMENT(type, k);
-				
-				references.push_back(BVHReference(bounds, j, i, packed_type));
-				root.grow(bounds);
-				center.grow(bounds.center2());
+				if(bounds.valid()) {
+					int packed_type = PRIMITIVE_PACK_SEGMENT(type, k);
+
+					references.push_back(BVHReference(bounds, j, i, packed_type));
+					root.grow(bounds);
+					center.grow(bounds.center2());
+				}
 			}
 		}
 	}
@@ -204,15 +208,23 @@ void BVHBuild::add_references(BVHRange& root)
 	foreach(Object *ob, objects) {
 		if(params.top_level) {
 			if(!ob->mesh->is_instanced()) {
-				num_alloc_references += ob->mesh->triangles.size();
-				num_alloc_references += count_curve_segments(ob->mesh);
+				if(params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) {
+					num_alloc_references += ob->mesh->triangles.size();
+				}
+				if(params.primitive_mask & PRIMITIVE_ALL_CURVE) {
+					num_alloc_references += count_curve_segments(ob->mesh);
+				}
 			}
 			else
 				num_alloc_references++;
 		}
 		else {
-			num_alloc_references += ob->mesh->triangles.size();
-			num_alloc_references += count_curve_segments(ob->mesh);
+			if(params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) {
+				num_alloc_references += ob->mesh->triangles.size();
+			}
+			if(params.primitive_mask & PRIMITIVE_ALL_CURVE) {
+				num_alloc_references += count_curve_segments(ob->mesh);
+			}
 		}
 	}
 
diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h
index cf683df..2d48349 100644
--- a/intern/cycles/bvh/bvh_params.h
+++ b/intern/cycles/bvh/bvh_params.h
@@ -20,6 +20,8 @@
 
 #include "util_boundbox.h"
 
+#include "kernel_types.h"
+
 CCL_NAMESPACE_BEGIN
 
 /* BVH Parameters */
@@ -46,6 +48,9 @@ public:
 	/* QBVH */
 	bool use_qbvh;
 
+	/* Mask of primitives to be included into the BVH. */
+	int primitive_mask;
+
 	/* fixed parameters */
 	enum {
 		MAX_DEPTH = 64,
@@ -69,6 +74,8 @@ public:
 
 		top_level = false;
 		use_qbvh = false;
+
+		primitive_mask = PRIMITIVE_ALL;
 	}
 
 	/* SAH costs */
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index 3c17429..6ba1c06 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -138,8 +138,10 @@ set(SRC_GEOM_HEADERS
 	geom/geom_attribute.h
 	geom/geom_bvh.h
 	geom/geom_bvh_shadow.h
+	geom/geom_bvh_shadow_hair.h
 	geom/geom_bvh_subsurface.h
 	geom/geom_bvh_traversal.h
+	geom/geom_bvh_traversal_hair.h
 	geom/geom_bvh_volume.h
 	geom/geom_bvh_volume_all.h
 	geom/geom_curve.h
@@ -149,8 +151,10 @@ set(SRC_GEOM_HEADERS
 	geom/geom_primitive.h
 	geom/geom_qbvh.h
 	geom/geom_qbvh_shadow.h
+	geom/geom_qbvh_shadow_hair.h
 	geom/geom_qbvh_subsurface.h
 	geom/geom_qbvh_traversal.h
+	geom/geom_qbvh_traversal_hair.h
 	geom/geom_qbvh_volume.h
 	geom/geom_qbvh_volume_all.h
 	geom/geom_triangle.h
diff --git a/intern/cycles/kernel/geom/geom_bvh.h b/intern/cycles/kernel/geom/geom_bvh.h
index 9eadc97..f62ef97 100644
--- a/intern/cycles/kernel/geom/geom_bvh.h
+++ b/intern/cycles/kernel/geom/geom_bvh.h
@@ -65,22 +65,24 @@ CCL_NAMESPACE_BEGIN
 #  include "geom_bvh_traversal.h"
 #endif
 
-#if defined(__HAIR__)
-#  define BVH_FUNCTION_NAME bvh_intersect_hair
-#  define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_HAIR_MINIMUM_WIDTH
-#  include "geom_bvh_traversal.h"
-#endif
-
 #if defined(__OBJECT_MOTION__)
 #  define BVH_FUNCTION_NAME bvh_intersect_motion
 #  define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION
 #  include "geom_bvh_traversal.h"
 #endif
 
+/* Regular Hair BVH traversal */
+
+#if defined(__HAIR__)
+#  define BVH_FUNCTION_NAME bvh_intersect_hair
+#  define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_HAIR_MINIMUM_WIDTH
+#  include "geom_bvh_traversal_hair.h"
+#endif
+
 #if defined(__HAIR__) && defined(__OBJECT_MOTION__)
 #  define BVH_FUNCTION_NAME bvh_intersect_hair_motion
 #  define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HA

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list