[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [29519] branches/render25/source/blender/ render/intern/raytrace: Render Branch: save a few percentages on simple scenes, doesn't seem to help

Brecht Van Lommel brecht at blender.org
Thu Jun 17 12:02:52 CEST 2010


Revision: 29519
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=29519
Author:   blendix
Date:     2010-06-17 12:02:52 +0200 (Thu, 17 Jun 2010)

Log Message:
-----------
Render Branch: save a few percentages on simple scenes, doesn't seem to help
on more complex ones, but makes things easier to analyze.

* reorganize svbvh code so all the traversal functions are in one file
* don't do test for root so that push_childs can be inlined
* make shadow a template parameter so it doesn't need to be runtime checked

Modified Paths:
--------------
    branches/render25/source/blender/render/intern/raytrace/bvh.h
    branches/render25/source/blender/render/intern/raytrace/rayobject_qbvh.cpp
    branches/render25/source/blender/render/intern/raytrace/rayobject_svbvh.cpp
    branches/render25/source/blender/render/intern/raytrace/rayobject_vbvh.cpp
    branches/render25/source/blender/render/intern/raytrace/svbvh.h

Modified: branches/render25/source/blender/render/intern/raytrace/bvh.h
===================================================================
--- branches/render25/source/blender/render/intern/raytrace/bvh.h	2010-06-17 08:42:15 UTC (rev 29518)
+++ branches/render25/source/blender/render/intern/raytrace/bvh.h	2010-06-17 10:02:52 UTC (rev 29519)
@@ -165,7 +165,7 @@
  */
 template<class Node> static inline void bvh_node_push_childs(Node *node, Isect *isec, Node **stack, int &stack_pos);
 
-template<class Node,int MAX_STACK_SIZE,bool TEST_ROOT>
+template<class Node,int MAX_STACK_SIZE,bool TEST_ROOT,bool SHADOW>
 static int bvh_node_stack_raycast(Node *root, Isect *isec)
 {
 	Node *stack[MAX_STACK_SIZE];
@@ -190,7 +190,7 @@
 		else
 		{
 			hit |= RE_rayobject_intersect( (RayObject*)node, isec);
-			if(hit && isec->mode == RE_RAY_SHADOW) return hit;
+			if(SHADOW && hit) return hit;
 		}
 	}
 	return hit;

Modified: branches/render25/source/blender/render/intern/raytrace/rayobject_qbvh.cpp
===================================================================
--- branches/render25/source/blender/render/intern/raytrace/rayobject_qbvh.cpp	2010-06-17 08:42:15 UTC (rev 29518)
+++ branches/render25/source/blender/render/intern/raytrace/rayobject_qbvh.cpp	2010-06-17 10:02:52 UTC (rev 29519)
@@ -93,8 +93,12 @@
 int intersect(QBVHTree *obj, Isect* isec)
 {
 	//TODO renable hint support
-	if(RE_rayobject_isAligned(obj->root))
-		return bvh_node_stack_raycast<SVBVHNode,StackSize,false>( obj->root, isec);
+	if(RE_rayobject_isAligned(obj->root)) {
+		if(isec->mode == RE_RAY_SHADOW)
+			return svbvh_node_stack_raycast<StackSize,true>(obj->root, isec);
+		else
+			return svbvh_node_stack_raycast<StackSize,false>(obj->root, isec);
+	}
 	else
 		return RE_rayobject_intersect((RayObject*)obj->root, isec);
 }

Modified: branches/render25/source/blender/render/intern/raytrace/rayobject_svbvh.cpp
===================================================================
--- branches/render25/source/blender/render/intern/raytrace/rayobject_svbvh.cpp	2010-06-17 08:42:15 UTC (rev 29518)
+++ branches/render25/source/blender/render/intern/raytrace/rayobject_svbvh.cpp	2010-06-17 10:02:52 UTC (rev 29519)
@@ -128,8 +128,12 @@
 int intersect(SVBVHTree *obj, Isect* isec)
 {
 	//TODO renable hint support
-	if(RE_rayobject_isAligned(obj->root))
-		return bvh_node_stack_raycast<SVBVHNode,StackSize,false>( obj->root, isec);
+	if(RE_rayobject_isAligned(obj->root)) {
+		if(isec->mode == RE_RAY_SHADOW)
+			return svbvh_node_stack_raycast<StackSize,true>(obj->root, isec);
+		else
+			return svbvh_node_stack_raycast<StackSize,false>(obj->root, isec);
+	}
 	else
 		return RE_rayobject_intersect( (RayObject*) obj->root, isec );
 }

Modified: branches/render25/source/blender/render/intern/raytrace/rayobject_vbvh.cpp
===================================================================
--- branches/render25/source/blender/render/intern/raytrace/rayobject_vbvh.cpp	2010-06-17 08:42:15 UTC (rev 29518)
+++ branches/render25/source/blender/render/intern/raytrace/rayobject_vbvh.cpp	2010-06-17 10:02:52 UTC (rev 29519)
@@ -130,8 +130,12 @@
 int intersect(VBVHTree *obj, Isect* isec)
 {
 	//TODO renable hint support
-	if(RE_rayobject_isAligned(obj->root))
-		return bvh_node_stack_raycast<VBVHNode,StackSize,false>( obj->root, isec);
+	if(RE_rayobject_isAligned(obj->root)) {
+		if(isec->mode == RE_RAY_SHADOW)
+			return bvh_node_stack_raycast<VBVHNode,StackSize,false,true>( obj->root, isec);
+		else
+			return bvh_node_stack_raycast<VBVHNode,StackSize,false,false>( obj->root, isec);
+	}
 	else
 		return RE_rayobject_intersect( (RayObject*) obj->root, isec );
 }

Modified: branches/render25/source/blender/render/intern/raytrace/svbvh.h
===================================================================
--- branches/render25/source/blender/render/intern/raytrace/svbvh.h	2010-06-17 08:42:15 UTC (rev 29518)
+++ branches/render25/source/blender/render/intern/raytrace/svbvh.h	2010-06-17 10:02:52 UTC (rev 29519)
@@ -47,45 +47,119 @@
 	SVBVHNode **child;
 };
 
-template<>
-inline int bvh_node_hit_test<SVBVHNode>(SVBVHNode *node, Isect *isec)
+static int svbvh_bb_intersect_test_simd4(const Isect *isec, const __m128 *bb_group)
 {
+	const __m128 tmin0 = _mm_setzero_ps();
+	const __m128 tmax0 = _mm_set_ps1(isec->dist);
+
+	const __m128 start0 = _mm_set_ps1(isec->start[0]);
+	const __m128 start1 = _mm_set_ps1(isec->start[1]);
+	const __m128 start2 = _mm_set_ps1(isec->start[2]);
+	const __m128 sub0 = _mm_sub_ps(bb_group[isec->bv_index[0]], start0);
+	const __m128 sub1 = _mm_sub_ps(bb_group[isec->bv_index[1]], start0);
+	const __m128 sub2 = _mm_sub_ps(bb_group[isec->bv_index[2]], start1);
+	const __m128 sub3 = _mm_sub_ps(bb_group[isec->bv_index[3]], start1);
+	const __m128 sub4 = _mm_sub_ps(bb_group[isec->bv_index[4]], start2);
+	const __m128 sub5 = _mm_sub_ps(bb_group[isec->bv_index[5]], start2);
+	const __m128 idot_axis0 = _mm_set_ps1(isec->idot_axis[0]);
+	const __m128 idot_axis1 = _mm_set_ps1(isec->idot_axis[1]);
+	const __m128 idot_axis2 = _mm_set_ps1(isec->idot_axis[2]);
+	const __m128 mul0 = _mm_mul_ps(sub0, idot_axis0);
+	const __m128 mul1 = _mm_mul_ps(sub1, idot_axis0);
+	const __m128 mul2 = _mm_mul_ps(sub2, idot_axis1);
+	const __m128 mul3 = _mm_mul_ps(sub3, idot_axis1);
+	const __m128 mul4 = _mm_mul_ps(sub4, idot_axis2);
+	const __m128 mul5 = _mm_mul_ps(sub5, idot_axis2);
+	const __m128 tmin1 = _mm_max_ps(tmin0, mul0);
+	const __m128 tmax1 = _mm_min_ps(tmax0, mul1);
+	const __m128 tmin2 = _mm_max_ps(tmin1, mul2);
+	const __m128 tmax2 = _mm_min_ps(tmax1, mul3);
+	const __m128 tmin3 = _mm_max_ps(tmin2, mul4);
+	const __m128 tmax3 = _mm_min_ps(tmax2, mul5);
+	
+	return _mm_movemask_ps(_mm_cmpge_ps(tmax3, tmin3));
+}
+
+static int svbvh_bb_intersect_test(const Isect *isec, const float *_bb)
+{
+	const float *bb = _bb;
+	
+	float t1x = (bb[isec->bv_index[0]] - isec->start[0]) * isec->idot_axis[0];
+	float t2x = (bb[isec->bv_index[1]] - isec->start[0]) * isec->idot_axis[0];
+	float t1y = (bb[isec->bv_index[2]] - isec->start[1]) * isec->idot_axis[1];
+	float t2y = (bb[isec->bv_index[3]] - isec->start[1]) * isec->idot_axis[1];
+	float t1z = (bb[isec->bv_index[4]] - isec->start[2]) * isec->idot_axis[2];
+	float t2z = (bb[isec->bv_index[5]] - isec->start[2]) * isec->idot_axis[2];
+	
+	RE_RC_COUNT(isec->raycounter->bb.test);
+
+	if(t1x > t2y || t2x < t1y || t1x > t2z || t2x < t1z || t1y > t2z || t2y < t1z) return 0;
+	if(t2x < 0.0 || t2y < 0.0 || t2z < 0.0) return 0;
+	if(t1x > isec->dist || t1y > isec->dist || t1z > isec->dist) return 0;
+
+	RE_RC_COUNT(isec->raycounter->bb.hit);	
+
 	return 1;
 }
 
-template<>
-inline void bvh_node_push_childs<SVBVHNode>(SVBVHNode *node, Isect *isec, SVBVHNode **stack, int &stack_pos)
+static bool svbvh_node_is_leaf(SVBVHNode *node)
 {
-	SVBVHNode **child= node->child;
-	float *child_bb= node->child_bb;
-	int i=0, nchilds= node->nchilds;
+	return !RE_rayobject_isAligned(node);
+}
 
-	while(i+4 <= nchilds)
+template<int MAX_STACK_SIZE, bool SHADOW>
+static int svbvh_node_stack_raycast(SVBVHNode *root, Isect *isec)
+{
+	SVBVHNode *stack[MAX_STACK_SIZE], *node;
+	int hit = 0, stack_pos = 0;
+
+	stack[stack_pos++] = root;
+
+	while(stack_pos)
 	{
-		int res = test_bb_group4( (__m128*) (child_bb+6*i), isec );
-		RE_RC_COUNT(isec->raycounter->simd_bb.test);
-		
-		if(res & 1) { stack[stack_pos++] = child[i+0]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); }
-		if(res & 2) { stack[stack_pos++] = child[i+1]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); }
-		if(res & 4) { stack[stack_pos++] = child[i+2]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); }
-		if(res & 8) { stack[stack_pos++] = child[i+3]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); }
-		
-		i += 4;
+		node = stack[--stack_pos];
+
+		if(!svbvh_node_is_leaf(node))
+		{
+			float *child_bb= node->child_bb;
+			SVBVHNode **child= node->child;
+			int i=0, nchilds= node->nchilds;
+
+			while(i+4 <= nchilds) {
+				int res = svbvh_bb_intersect_test_simd4(isec, (__m128*) child_bb);
+
+				RE_RC_COUNT(isec->raycounter->simd_bb.test);
+
+				if(res & 1) { stack[stack_pos++] = child[0]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); }
+				if(res & 2) { stack[stack_pos++] = child[1]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); }
+				if(res & 4) { stack[stack_pos++] = child[2]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); }
+				if(res & 8) { stack[stack_pos++] = child[3]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); }
+
+				i += 4;
+			}
+
+			for(; i<nchilds; i++) {
+				if(svbvh_bb_intersect_test(isec, (float*)child_bb+6*i))
+					stack[stack_pos++] = child[i];
+			}
+		}
+		else
+		{
+			hit |= RE_rayobject_intersect((RayObject*)node, isec);
+			if(SHADOW && hit) break;
+		}
 	}
-	while(i < nchilds)
-	{
-		if(rayobject_bb_intersect_test(isec, (const float*)child_bb+6*i))
-			stack[stack_pos++] = child[i];
-		i++;
-	}
+
+	return hit;
 }
 
+
 template<>
 inline void bvh_node_merge_bb<SVBVHNode>(SVBVHNode *node, float *min, float *max)
 {
 	if(is_leaf(node))
 	{
-		RE_rayobject_merge_bb( (RayObject*)node, min, max);
+		RE_rayobject_merge_bb((RayObject*)node, min, max);
 	}
 	else
 	{
@@ -167,7 +241,7 @@
 	
 	void copy_bb(float *bb, const float *old_bb)
 	{
-		std::copy( old_bb, old_bb+6, bb );
+		std::copy(old_bb, old_bb+6, bb);
 	}
 	
 	void prepare_for_simd(SVBVHNode *node)
@@ -177,7 +251,7 @@
 		{
 			float vec_tmp[4*6];
 			float *res = node->child_bb+6*i;
-			std::copy( res, res+6*4, vec_tmp);
+			std::copy(res, res+6*4, vec_tmp);
 			
 			for(int j=0; j<6; j++)
 			{
@@ -234,7 +308,7 @@
 			{
 				float bb[6];
 				INIT_MINMAX(bb, bb+3);
-				RE_rayobject_merge_bb( (RayObject*)o_child, bb, bb+3);
+				RE_rayobject_merge_bb((RayObject*)o_child, bb, bb+3);
 				copy_bb(node->child_bb+i*6, bb);
 				break;
 			}
@@ -243,7 +317,7 @@
 				copy_bb(node->child_bb+i*6, o_child->bb);
 			}
 		}
-		assert( i == 0 );
+		assert(i == 0);
 
 		prepare_for_simd(node);
 		





More information about the Bf-blender-cvs mailing list