[Bf-blender-cvs] [333e2f8] cycles_hair_bvh: Cycles: Support oriented bounding boxes for spatial split BVH

Sergey Sharybin noreply at git.blender.org
Thu May 12 16:19:34 CEST 2016


Commit: 333e2f8ed33de83aadbd484e009041633fff818a
Author: Sergey Sharybin
Date:   Thu May 12 16:14:17 2016 +0200
Branches: cycles_hair_bvh
https://developer.blender.org/rB333e2f8ed33de83aadbd484e009041633fff818a

Cycles: Support oriented bounding boxes for spatial split BVH

Very quick implementation, which will re-calculate bounding box
for primitives several times, but that we will optimize shortly.

This is already good enough to run further tests.

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

M	intern/cycles/bvh/bvh_build.cpp
M	intern/cycles/bvh/bvh_sort.cpp
M	intern/cycles/bvh/bvh_sort.h
M	intern/cycles/bvh/bvh_split.cpp
M	intern/cycles/bvh/bvh_split.h
M	intern/cycles/bvh/bvh_unaligned.cpp

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

diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp
index afa488a..dbe38a3 100644
--- a/intern/cycles/bvh/bvh_build.cpp
+++ b/intern/cycles/bvh/bvh_build.cpp
@@ -564,16 +564,54 @@ BVHNode* BVHBuild::build_node(const BVHRange& range,
 			return create_leaf_node(range, *references);
 		}
 	}
+	float leafSAH = params.sah_primitive_cost * split.leafSAH;
+	float splitSAH = params.sah_node_cost * range.bounds().half_area() +
+	                 params.sah_primitive_cost * split.nodeSAH;
+
+	BVHMixedSplit unaligned_split;
+	float unalignedSplitSAH = FLT_MAX;
+	/* float unalignedLeafSAH = FLT_MAX; */
+	Transform aligned_space;
+	if(params.use_unaligned_nodes && splitSAH > 0.7f*leafSAH) {
+		aligned_space =
+		        unaligned_heuristic.compute_aligned_space(range, &references->at(0));
+		unaligned_split = BVHMixedSplit(this,
+		                                storage,
+		                                range,
+		                                references,
+		                                level,
+		                                &unaligned_heuristic,
+		                                &aligned_space);
+		/* unalignedLeafSAH = params.sah_primitive_cost * split.leafSAH; */
+		unalignedSplitSAH = params.sah_node_cost * unaligned_split.bounds.half_area() +
+		                    params.sah_primitive_cost * unaligned_split.nodeSAH;
+		/* TOOD(sergey): Check we can create leaf already. */
+
+		unalignedSplitSAH = splitSAH - 1.0f;
+	}
 
 	/* Do split. */
 	BVHRange left, right;
-	split.split(this, left, right, range);
+	if(unalignedSplitSAH < splitSAH) {
+		unaligned_split.split(this, left, right, range);
+	}
+	else {
+		split.split(this, left, right, range);
+	}
 
 	progress_total += left.size() + right.size() - range.size();
 
+	BoundBox bounds;
+	if(unalignedSplitSAH < splitSAH) {
+		bounds = unaligned_heuristic.compute_aligned_boundbox(
+		        range, &references->at(0), aligned_space);
+	}
+	else {
+		bounds = range.bounds();
+	}
+
 	/* Create inner node. */
 	InnerNode *inner;
-
 	if(range.size() < THREAD_TASK_SIZE) {
 		/* Local build. */
 
@@ -587,11 +625,11 @@ BVHNode* BVHBuild::build_node(const BVHRange& range,
 		/* Build right node. */
 		BVHNode *rightnode = build_node(right, &copy, level + 1, thread_id);
 
-		inner = new InnerNode(range.bounds(), leftnode, rightnode);
+		inner = new InnerNode(bounds, leftnode, rightnode);
 	}
 	else {
 		/* Threaded build. */
-		inner = new InnerNode(range.bounds());
+		inner = new InnerNode(bounds);
 		task_pool.push(new BVHSpatialSplitBuildTask(this,
 		                                            inner,
 		                                            0,
@@ -608,6 +646,10 @@ BVHNode* BVHBuild::build_node(const BVHRange& range,
 		               true);
 	}
 
+	if(unalignedSplitSAH < splitSAH) {
+		inner->set_aligned_space(aligned_space);
+	}
+
 	return inner;
 }
 
diff --git a/intern/cycles/bvh/bvh_sort.cpp b/intern/cycles/bvh/bvh_sort.cpp
index f6bbdb2..7e13fbd 100644
--- a/intern/cycles/bvh/bvh_sort.cpp
+++ b/intern/cycles/bvh/bvh_sort.cpp
@@ -39,10 +39,24 @@ static const int BVH_SORT_THRESHOLD = 4096;
 struct BVHReferenceCompare {
 public:
 	int dim;
+	const BVHUnaligned *unaligned_heuristic;
+	const Transform *aligned_space;
+
+	BVHReferenceCompare(int dim,
+	                    const BVHUnaligned *unaligned_heuristic,
+	                    const Transform *aligned_space)
+	        : dim(dim),
+	          unaligned_heuristic(unaligned_heuristic),
+	          aligned_space(aligned_space)
+	{
+	}
 
-	explicit BVHReferenceCompare(int dim_)
+	__forceinline BoundBox get_prim_bounds(const BVHReference& prim) const
 	{
-		dim = dim_;
+		return (aligned_space != NULL)
+		        ? unaligned_heuristic->compute_aligned_prim_boundbox(
+		                  prim, *aligned_space)
+		        : prim.bounds();
 	}
 
 	/* Compare two references.
@@ -52,8 +66,10 @@ public:
 	__forceinline int compare(const BVHReference& ra,
 	                          const BVHReference& rb) const
 	{
-		NO_EXTENDED_PRECISION float ca = ra.bounds().min[dim] + ra.bounds().max[dim];
-		NO_EXTENDED_PRECISION float cb = rb.bounds().min[dim] + rb.bounds().max[dim];
+		BoundBox ra_bounds = get_prim_bounds(ra),
+		         rb_bounds = get_prim_bounds(rb);
+		NO_EXTENDED_PRECISION float ca = ra_bounds.min[dim] + ra_bounds.max[dim];
+		NO_EXTENDED_PRECISION float cb = rb_bounds.min[dim] + rb_bounds.max[dim];
 
 		if(ca < cb) return -1;
 		else if(ca > cb) return 1;
@@ -171,10 +187,15 @@ static void bvh_reference_sort_threaded(TaskPool *task_pool,
 	}
 }
 
-void bvh_reference_sort(int start, int end, BVHReference *data, int dim)
+void bvh_reference_sort(int start,
+                        int end,
+                        BVHReference *data,
+                        int dim,
+                        const BVHUnaligned *unaligned_heuristic,
+                        const Transform *aligned_space)
 {
 	const int count = end - start;
-	BVHReferenceCompare compare(dim);
+	BVHReferenceCompare compare(dim, unaligned_heuristic, aligned_space);
 	if(count < BVH_SORT_THRESHOLD) {
 		/* It is important to not use any mutex if array is small enough,
 		 * otherwise we end up in situation when we're going to sleep far
diff --git a/intern/cycles/bvh/bvh_sort.h b/intern/cycles/bvh/bvh_sort.h
index 18aafb5..0d24b61 100644
--- a/intern/cycles/bvh/bvh_sort.h
+++ b/intern/cycles/bvh/bvh_sort.h
@@ -20,7 +20,15 @@
 
 CCL_NAMESPACE_BEGIN
 
-void bvh_reference_sort(int start, int end, BVHReference *data, int dim);
+class BVHUnaligned;
+class Transform;
+
+void bvh_reference_sort(int start,
+                        int end,
+                        BVHReference *data,
+                        int dim,
+                        const BVHUnaligned *unaligned_heuristic = NULL,
+                        const Transform *aligned_space = NULL);
 
 CCL_NAMESPACE_END
 
diff --git a/intern/cycles/bvh/bvh_split.cpp b/intern/cycles/bvh/bvh_split.cpp
index 8084975..70b03a0 100644
--- a/intern/cycles/bvh/bvh_split.cpp
+++ b/intern/cycles/bvh/bvh_split.cpp
@@ -32,14 +32,18 @@ BVHObjectSplit::BVHObjectSplit(BVHBuild *builder,
                                BVHSpatialStorage *storage,
                                const BVHRange& range,
                                vector<BVHReference> *references,
-                               float nodeSAH)
+                               float nodeSAH,
+                               const BVHUnaligned *unaligned_heuristic,
+                               const Transform *aligned_space)
 : sah(FLT_MAX),
   dim(0),
   num_left(0),
   left_bounds(BoundBox::empty),
   right_bounds(BoundBox::empty),
   storage_(storage),
-  references_(references)
+  references_(references),
+  unaligned_heuristic_(unaligned_heuristic),
+  aligned_space_(aligned_space)
 {
 	const BVHReference *ref_ptr = &references_->at(range.start());
 	float min_sah = FLT_MAX;
@@ -51,12 +55,15 @@ BVHObjectSplit::BVHObjectSplit(BVHBuild *builder,
 		bvh_reference_sort(range.start(),
 		                   range.end(),
 		                   &references_->at(0),
-		                   dim);
+		                   dim,
+		                   unaligned_heuristic_,
+		                   aligned_space_);
 
 		/* sweep right to left and determine bounds. */
 		BoundBox right_bounds = BoundBox::empty;
 		for(int i = range.size() - 1; i > 0; i--) {
-			right_bounds.grow(ref_ptr[i].bounds());
+			BoundBox prim_bounds = get_prim_bounds(ref_ptr[i]);
+			right_bounds.grow(prim_bounds);
 			storage_->right_bounds[i - 1] = right_bounds;
 		}
 
@@ -64,7 +71,8 @@ BVHObjectSplit::BVHObjectSplit(BVHBuild *builder,
 		BoundBox left_bounds = BoundBox::empty;
 
 		for(int i = 1; i < range.size(); i++) {
-			left_bounds.grow(ref_ptr[i - 1].bounds());
+			BoundBox prim_bounds = get_prim_bounds(ref_ptr[i - 1]);
+			left_bounds.grow(prim_bounds);
 			right_bounds = storage_->right_bounds[i - 1];
 
 			float sah = nodeSAH +
@@ -88,16 +96,37 @@ void BVHObjectSplit::split(BVHRange& left,
                            BVHRange& right,
                            const BVHRange& range)
 {
+	assert(references_->size() > 0);
 	/* sort references according to split */
 	bvh_reference_sort(range.start(),
 	                   range.end(),
 	                   &references_->at(0),
-	                   this->dim);
+	                   this->dim,
+	                   unaligned_heuristic_,
+	                   aligned_space_);
+
+	BoundBox left_bounds, rightb_ounds;
+	const int num_right = range.size() - this->num_left;
+	if(aligned_space_ == NULL) {
+		left_bounds = this->left_bounds;
+		right_bounds = this->right_bounds;
+	}
+	else {
+		left_bounds = BoundBox::empty;
+		right_bounds = BoundBox::empty;
+		for(int i = 0; i < this->num_left; ++i) {
+			BoundBox prim_boundbox = references_->at(range.start() + i).bounds();
+			left_bounds.grow(prim_boundbox);
+		}
+		for(int i = 0; i < num_right; ++i) {
+			BoundBox prim_boundbox = references_->at(range.start() + this->num_left + i).bounds();
+			right_bounds.grow(prim_boundbox);
+		}
+	}
 
 	/* split node ranges */
-	left = BVHRange(this->left_bounds, range.start(), this->num_left);
-	right = BVHRange(this->right_bounds, left.end(), range.size() - this->num_left);
-
+	left = BVHRange(left_bounds, range.start(), this->num_left);
+	right = BVHRange(right_bounds, left.end(), num_right);
 }
 
 /* Spatial Split */
@@ -106,16 +135,31 @@ BVHSpatialSplit::BVHSpatialSplit(const BVHBuild& builder,
                                  BVHSpatialStorage *storage,
                                  const BVHRange& range,
                                  vector<BVHReference> *references,
-                                 float nodeSAH)
+                                 float nodeSAH,
+                                 const BVHUnaligned *unaligned_heuristic,
+                                 const Transform *aligned_space)
 : sah(FLT_MAX),
   dim(0),
   pos(0.0f),
   storage_(storage),
-  references_(references)
+  references_(references),
+  unaligned_heuristic_(unaligned_heuristic),
+  aligned_space_(aligned_space)
 {
 	/* initialize bins. */
-	float3 origin = range.bounds().min;
-	float3 binSize = (range.bounds().max - origin) * (1.0f / (float)BVHParams::NUM_SPATIAL_

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list