[Bf-blender-cvs] [09d8e29] cycles_hair_bvh: Cycles: Use affine space for unaligned nodes

Sergey Sharybin noreply at git.blender.org
Mon Apr 25 19:16:51 CEST 2016


Commit: 09d8e295315ad88982bdd3ba233ed68d7dc5c1a3
Author: Sergey Sharybin
Date:   Mon Apr 25 19:15:31 2016 +0200
Branches: cycles_hair_bvh
https://developer.blender.org/rB09d8e295315ad88982bdd3ba233ed68d7dc5c1a3

Cycles: Use affine space for unaligned nodes

This way we always know node's boundbox is within 0..1 which simplifies
intersection check and saves some per-node memory.

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

M	intern/cycles/bvh/bvh.cpp
M	intern/cycles/bvh/bvh.h
M	intern/cycles/bvh/bvh_unaligned.cpp
M	intern/cycles/bvh/bvh_unaligned.h
M	intern/cycles/kernel/geom/geom.h
M	intern/cycles/kernel/geom/geom_bvh_hair.h
M	intern/cycles/kernel/geom/geom_bvh_traversal_hair.h

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

diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp
index 83a912f..b7ba422 100644
--- a/intern/cycles/bvh/bvh.cpp
+++ b/intern/cycles/bvh/bvh.cpp
@@ -24,6 +24,7 @@
 #include "bvh_build.h"
 #include "bvh_node.h"
 #include "bvh_params.h"
+#include "bvh_unaligned.h"
 
 #include "util_debug.h"
 #include "util_foreach.h"
@@ -366,7 +367,7 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
 			 */
 			size_t nsize_bbox = (use_qbvh)? 6: 3;
 			if(params.use_unaligned_nodes) {
-				nsize_bbox = 6;
+				nsize_bbox = 4;
 			}
 			int4 *bvh_nodes = &bvh->pack.nodes[0];
 			size_t bvh_nodes_size = bvh->pack.nodes.size(); 
@@ -466,15 +467,15 @@ void RegularBVH::pack_unaligned_leaf(const BVHStackEntry& e,
 {
 	const Transform& aligned_space = e.node->m_aligned_space;
 	const BoundBox& bounds = e.node->m_bounds;
+	Transform space = BVHUnaligned::compute_node_transform(bounds,
+	                                                       aligned_space);
 	float4 data[BVH_UNALIGNED_NODE_LEAF_SIZE] =
 	{
 		make_float4(0.0f, 0.0f, 0.0f, 0.0f),
-		aligned_space.x,
-		aligned_space.y,
-		aligned_space.z,
-		aligned_space.w,
-		float3_to_float4(bounds.min),
-		float3_to_float4(bounds.max)
+		space.x,
+		space.y,
+		space.z,
+		space.w,
 	};
 
 	if(leaf->num_triangles() == 1 && pack.prim_index[leaf->m_lo] == -1) {
@@ -514,14 +515,14 @@ void RegularBVH::pack_unaligned_node(int idx,
                                      int c0, int c1,
                                      uint visibility0, uint visibility1)
 {
+	Transform space = BVHUnaligned::compute_node_transform(bounds,
+	                                                       aligned_space);
 	int4 data[BVH_UNALIGNED_NODE_SIZE] =
 	{
-		make_int4(__float_as_int(aligned_space.x.x), __float_as_int(aligned_space.x.y), __float_as_int(aligned_space.x.z), __float_as_int(aligned_space.x.w)),
-		make_int4(__float_as_int(aligned_space.y.x), __float_as_int(aligned_space.y.y), __float_as_int(aligned_space.y.z), __float_as_int(aligned_space.y.w)),
-		make_int4(__float_as_int(aligned_space.z.x), __float_as_int(aligned_space.z.y), __float_as_int(aligned_space.z.z), __float_as_int(aligned_space.z.w)),
-		make_int4(__float_as_int(aligned_space.w.x), __float_as_int(aligned_space.w.y), __float_as_int(aligned_space.w.z), __float_as_int(aligned_space.w.w)),
-		make_int4(__float_as_int(bounds.min.x), __float_as_int(bounds.min.y), __float_as_int(bounds.min.z), 0),
-		make_int4(__float_as_int(bounds.max.x), __float_as_int(bounds.max.y), __float_as_int(bounds.max.z), 0),
+		make_int4(__float_as_int(space.x.x), __float_as_int(space.x.y), __float_as_int(space.x.z), __float_as_int(space.x.w)),
+		make_int4(__float_as_int(space.y.x), __float_as_int(space.y.y), __float_as_int(space.y.z), __float_as_int(space.y.w)),
+		make_int4(__float_as_int(space.z.x), __float_as_int(space.z.y), __float_as_int(space.z.z), __float_as_int(space.z.w)),
+		make_int4(__float_as_int(space.w.x), __float_as_int(space.w.y), __float_as_int(space.w.z), __float_as_int(space.w.w)),
 		make_int4(c0, c1, visibility0, visibility1)
 	};
 
diff --git a/intern/cycles/bvh/bvh.h b/intern/cycles/bvh/bvh.h
index d8b4930..b38ab6e 100644
--- a/intern/cycles/bvh/bvh.h
+++ b/intern/cycles/bvh/bvh.h
@@ -39,8 +39,8 @@ class Progress;
 #define BVH_QNODE_LEAF_SIZE	1
 #define BVH_ALIGN		4096
 #define TRI_NODE_SIZE	3
-#define BVH_UNALIGNED_NODE_SIZE 7
-#define BVH_UNALIGNED_NODE_LEAF_SIZE 7
+#define BVH_UNALIGNED_NODE_SIZE 5
+#define BVH_UNALIGNED_NODE_LEAF_SIZE 5
 
 /* Packed BVH
  *
diff --git a/intern/cycles/bvh/bvh_unaligned.cpp b/intern/cycles/bvh/bvh_unaligned.cpp
index 3145206..f5aad23 100644
--- a/intern/cycles/bvh/bvh_unaligned.cpp
+++ b/intern/cycles/bvh/bvh_unaligned.cpp
@@ -111,4 +111,18 @@ BoundBox BVHUnaligned::compute_aligned_boundbox(
 	return bounds;
 }
 
+Transform BVHUnaligned::compute_node_transform(
+        const BoundBox& bounds,
+        const Transform& aligned_space)
+{
+	Transform space = aligned_space;
+	space.x.w -= bounds.min.x;
+	space.y.w -= bounds.min.y;
+	space.z.w -= bounds.min.z;
+	float3 dim = bounds.max - bounds.min;
+	return transform_scale(1.0f / max(1e-18f, dim.x),
+	                       1.0f / max(1e-18f, dim.y),
+	                       1.0f / max(1e-18f, dim.z)) * space;
+}
+
 CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh_unaligned.h b/intern/cycles/bvh/bvh_unaligned.h
index c6c1a3b..23a4579 100644
--- a/intern/cycles/bvh/bvh_unaligned.h
+++ b/intern/cycles/bvh/bvh_unaligned.h
@@ -55,6 +55,11 @@ public:
 	        const vector<BVHReference>& references,
 	        const Transform& aligned_space) const;
 
+	/* Calculate affine transform for node packing.
+	 * Bounds will be in the range of 0..1.
+	 */
+	static Transform compute_node_transform(const BoundBox& bounds,
+	                                        const Transform& aligned_space);
 protected:
 	/* List of objects BVH is being created for. */
 	const vector<Object*>& objects_;
diff --git a/intern/cycles/kernel/geom/geom.h b/intern/cycles/kernel/geom/geom.h
index c0e79c0..9e9acbf 100644
--- a/intern/cycles/kernel/geom/geom.h
+++ b/intern/cycles/kernel/geom/geom.h
@@ -26,8 +26,8 @@
 #define BVH_QNODE_SIZE 7
 #define BVH_QNODE_LEAF_SIZE 1
 #define TRI_NODE_SIZE 3
-#define BVH_UNALIGNED_NODE_SIZE 7
-#define BVH_UNALIGNED_NODE_LEAF_SIZE 7
+#define BVH_UNALIGNED_NODE_SIZE 5
+#define BVH_UNALIGNED_NODE_LEAF_SIZE 5
 
 /* silly workaround for float extended precision that happens when compiling
  * without sse support on x86, it results in different results for float ops
diff --git a/intern/cycles/kernel/geom/geom_bvh_hair.h b/intern/cycles/kernel/geom/geom_bvh_hair.h
index a53ff64..aed266a 100644
--- a/intern/cycles/kernel/geom/geom_bvh_hair.h
+++ b/intern/cycles/kernel/geom/geom_bvh_hair.h
@@ -46,40 +46,32 @@ ccl_device_inline bool bvh_hair_intersect_single_node(KernelGlobals *kg,
 	Transform aligned_space  = bvh_hair_fetch_aligned_space(kg, nodeAddr);
 	float3 aligned_dir = transform_direction(&aligned_space, dir);
 	float3 aligned_P = transform_point(&aligned_space, P);
-	float3 idir = bvh_inverse_direction(aligned_dir);
-
-	float4 node4, node5;
-	if(nodeAddr >= 0) {
-		node4 = kernel_tex_fetch(__bvh_curve_nodes, nodeAddr*BVH_UNALIGNED_NODE_SIZE+4);
-		node5 = kernel_tex_fetch(__bvh_curve_nodes, nodeAddr*BVH_UNALIGNED_NODE_SIZE+5);
-	}
-	else {
-		int leafAddr = -nodeAddr-1;
-		node4 = kernel_tex_fetch(__bvh_curve_leaf_nodes, leafAddr*BVH_UNALIGNED_NODE_LEAF_SIZE+5);
-		node5 = kernel_tex_fetch(__bvh_curve_leaf_nodes, leafAddr*BVH_UNALIGNED_NODE_LEAF_SIZE+6);
+	float3 nrdir = -1.0f * bvh_inverse_direction(aligned_dir);
+	float3 tLowerXYZ = make_float3(aligned_P.x * nrdir.x,
+	                               aligned_P.y * nrdir.y,
+	                               aligned_P.z * nrdir.z);
+	float3 tUpperXYZ = tLowerXYZ - nrdir;
+	const float tNearX = min(tLowerXYZ.x, tUpperXYZ.x);
+	const float tNearY = min(tLowerXYZ.y, tUpperXYZ.y);
+	const float tNearZ = min(tLowerXYZ.z, tUpperXYZ.z);
+	const float tFarX  = max(tLowerXYZ.x, tUpperXYZ.x);
+	const float tFarY  = max(tLowerXYZ.y, tUpperXYZ.y);
+	const float tFarZ  = max(tLowerXYZ.z, tUpperXYZ.z);
+	const float tNear  = max4(0.0f, tNearX, tNearY, tNearZ);
+	const float tFar   = min4(t, tFarX, tFarY, tFarZ);
+	if(dist != NULL) {
+		*dist = tNear;
 	}
-
-	NO_EXTENDED_PRECISION float c0lox = (node4.x - aligned_P.x) * idir.x;
-	NO_EXTENDED_PRECISION float c0hix = (node5.x - aligned_P.x) * idir.x;
-	NO_EXTENDED_PRECISION float c0loy = (node4.y - aligned_P.y) * idir.y;
-	NO_EXTENDED_PRECISION float c0hiy = (node5.y - aligned_P.y) * idir.y;
-	NO_EXTENDED_PRECISION float c0loz = (node4.z - aligned_P.z) * idir.z;
-	NO_EXTENDED_PRECISION float c0hiz = (node5.z - aligned_P.z) * idir.z;
-	NO_EXTENDED_PRECISION float c0min = max4(min(c0lox, c0hix), min(c0loy, c0hiy), min(c0loz, c0hiz), 0.0f);
-	NO_EXTENDED_PRECISION float c0max = min4(max(c0lox, c0hix), max(c0loy, c0hiy), max(c0loz, c0hiz), t);
-
 	if(difl != 0.0f) {
-		float hdiff = 1.0f + difl;
-		float ldiff = 1.0f - difl;
-		c0min = max(ldiff * c0min, c0min - extmax);
-		c0max = min(hdiff * c0max, c0max + extmax);
+		/* TODO(sergey): Same as for QBVH, needs a proper use. */
+		(void)extmax;
+		const float round_down = 1.0f - difl;
+		const float round_up = 1.0f + difl;
+		return round_down*tNear <= round_up*tFar;
 	}
-
-	if(dist != NULL) {
-		*dist = c0min;
+	else {
+		return tNear <= tFar;
 	}
-
-	return (c0max >= c0min);
 }
 
 int ccl_device bvh_hair_intersect_node(KernelGlobals *kg,
@@ -94,7 +86,7 @@ int ccl_device bvh_hair_intersect_node(KernelGlobals *kg,
 {
 	int mask = 0;
 	if(bvh_hair_intersect_single_node(kg, P, dir, t, difl, extmax, nodeAddr, NULL)) {
-		float4 cnodes = kernel_tex_fetch(__bvh_curve_nodes, nodeAddr*BVH_UNALIGNED_NODE_SIZE+6);
+		float4 cnodes = kernel_tex_fetch(__bvh_curve_nodes, nodeAddr*BVH_UNALIGNED_NODE_SIZE+4);
 		int nodeAddrChild0 = __float_as_int(cnodes.x);
 		int nodeAddrChild1 = __float_as_int(cnodes.y);
 		if(bvh_hair_intersect_single_node(kg, P, dir, t, difl, extmax, nodeAddrChild0, &dist[0])) {
diff --git a/intern/cycles/kernel/geom/geom_bvh_traversal_hair.h b/intern/cycles/kernel/geom/geom_bvh_traversal_hair.h
index 33cf0b6..4669d8b 100644
--- a/intern/cycles/kernel/geom/geom_bvh_traversal_hair.h
+++ b/intern/cycles/kernel/geom/geom_bvh_traversal_hair.h
@@ -68,15 +68,12 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
 	Transform ob_itfm;
 #endif
 
-	IsectPrecalc isect_precalc;
-	triangle_intersect_precalc(dir, &isect_precalc);
-
 	/* traversal loop */
 	do {
 		do {
 			/* traverse internal nodes */
 			while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) {
-				float4 cnodes = kernel_tex_fetch(__bvh_curve_nodes, nodeAddr*BVH_UNALIGNED_NODE_SIZE+6);
+				float4 cnodes = kernel_tex_fetch(__bvh_curve_nodes, nodeAddr*BVH_UNALIGNED_NODE_SIZE+4);
 				float dist[2];
 				int mask = bvh_hair_intersect_node(kg,
 				                                   P,
@@ -171,7 +168,6 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
 #  else
 					bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect->t);
 #  endif
-					triangle_intersect_precalc(dir, &isect_precalc);
 
 					++stackPtr;
 					kernel_assert(stac

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list