diff options
Diffstat (limited to 'intern/cycles/kernel/geom/geom_bvh_traversal.h')
-rw-r--r-- | intern/cycles/kernel/geom/geom_bvh_traversal.h | 210 |
1 files changed, 151 insertions, 59 deletions
diff --git a/intern/cycles/kernel/geom/geom_bvh_traversal.h b/intern/cycles/kernel/geom/geom_bvh_traversal.h index e39228c33de..73d79fd78ee 100644 --- a/intern/cycles/kernel/geom/geom_bvh_traversal.h +++ b/intern/cycles/kernel/geom/geom_bvh_traversal.h @@ -17,6 +17,10 @@ * limitations under the License. */ +#ifdef __QBVH__ +#include "geom_qbvh_traversal.h" +#endif + /* This is a template BVH traversal function, where various features can be * enabled/disabled. This way we can compile optimized versions for each case * without new features slowing things down. @@ -28,14 +32,16 @@ * */ -#define FEATURE(f) (((BVH_FUNCTION_FEATURES) & (f)) != 0) - -ccl_device bool BVH_FUNCTION_NAME -(KernelGlobals *kg, const Ray *ray, Intersection *isect, const uint visibility -#if FEATURE(BVH_HAIR_MINIMUM_WIDTH) -, uint *lcg_state, float difl, float extmax +ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, + const Ray *ray, + Intersection *isect, + const uint visibility +#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH) + , uint *lcg_state, + float difl, + float extmax #endif -) + ) { /* todo: * - test if pushing distance on the stack helps (for non shadow rays) @@ -58,15 +64,20 @@ ccl_device bool BVH_FUNCTION_NAME float3 idir = bvh_inverse_direction(dir); int object = OBJECT_NONE; -#if FEATURE(BVH_MOTION) +#if BVH_FEATURE(BVH_MOTION) Transform ob_tfm; #endif isect->t = ray->t; - isect->object = OBJECT_NONE; - isect->prim = PRIM_NONE; isect->u = 0.0f; isect->v = 0.0f; + isect->prim = PRIM_NONE; + isect->object = OBJECT_NONE; + +#if defined(__KERNEL_DEBUG__) + isect->num_traversal_steps = 0; + isect->num_traversed_instances = 0; +#endif #if defined(__KERNEL_SSE2__) const shuffle_swap_t shuf_identity = shuffle_swap_identity(); @@ -85,6 +96,9 @@ ccl_device bool BVH_FUNCTION_NAME gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); #endif + IsectPrecalc isect_precalc; + triangle_intersect_precalc(dir, &isect_precalc); + /* traversal loop */ do { do { @@ -122,7 +136,7 @@ ccl_device bool BVH_FUNCTION_NAME NO_EXTENDED_PRECISION float c1min = max4(min(c1lox, c1hix), min(c1loy, c1hiy), min(c1loz, c1hiz), 0.0f); NO_EXTENDED_PRECISION float c1max = min4(max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz), t); -#if FEATURE(BVH_HAIR_MINIMUM_WIDTH) +#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH) if(difl != 0.0f) { float hdiff = 1.0f + difl; float ldiff = 1.0f - difl; @@ -163,7 +177,7 @@ ccl_device bool BVH_FUNCTION_NAME ssef minmax = max(max(tminmaxx, tminmaxy), max(tminmaxz, tsplat)); const ssef tminmax = minmax ^ pn; -#if FEATURE(BVH_HAIR_MINIMUM_WIDTH) +#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH) if(difl != 0.0f) { float4 *tminmaxview = (float4*)&tminmax; float &c0min = tminmaxview->x, &c1min = tminmaxview->y; @@ -213,6 +227,7 @@ ccl_device bool BVH_FUNCTION_NAME } ++stackPtr; + kernel_assert(stackPtr < BVH_STACK_SIZE); traversalStack[stackPtr] = nodeAddrChild1; } else { @@ -226,80 +241,112 @@ ccl_device bool BVH_FUNCTION_NAME --stackPtr; } } + +#if defined(__KERNEL_DEBUG__) + isect->num_traversal_steps++; +#endif } /* if node is leaf, fetch triangle list */ if(nodeAddr < 0) { - float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_NODE_SIZE+(BVH_NODE_SIZE-1)); + float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_NODE_LEAF_SIZE); int primAddr = __float_as_int(leaf.x); -#if FEATURE(BVH_INSTANCING) +#if BVH_FEATURE(BVH_INSTANCING) if(primAddr >= 0) { #endif - int primAddr2 = __float_as_int(leaf.y); + const int primAddr2 = __float_as_int(leaf.y); + const uint type = __float_as_int(leaf.w); /* pop */ nodeAddr = traversalStack[stackPtr]; --stackPtr; /* primitive intersection */ - while(primAddr < primAddr2) { - bool hit; - uint type = kernel_tex_fetch(__prim_type, primAddr); - - switch(type & PRIMITIVE_ALL) { - case PRIMITIVE_TRIANGLE: { - hit = triangle_intersect(kg, isect, P, dir, visibility, object, primAddr); - break; + switch(type & PRIMITIVE_ALL) { + case PRIMITIVE_TRIANGLE: { + for(; primAddr < primAddr2; primAddr++) { +#if defined(__KERNEL_DEBUG__) + isect->num_traversal_steps++; +#endif + kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); + if(triangle_intersect(kg, &isect_precalc, isect, P, visibility, object, primAddr)) { + /* shadow ray early termination */ +#if defined(__KERNEL_SSE2__) + if(visibility == PATH_RAY_SHADOW_OPAQUE) + return true; + tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t); +#else + if(visibility == PATH_RAY_SHADOW_OPAQUE) + return true; +#endif + } } -#if FEATURE(BVH_MOTION) - case PRIMITIVE_MOTION_TRIANGLE: { - hit = motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr); - break; + break; + } +#if BVH_FEATURE(BVH_MOTION) + case PRIMITIVE_MOTION_TRIANGLE: { + for(; primAddr < primAddr2; primAddr++) { +#if defined(__KERNEL_DEBUG__) + isect->num_traversal_steps++; +#endif + kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); + if(motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr)) { + /* shadow ray early termination */ +#if defined(__KERNEL_SSE2__) + if(visibility == PATH_RAY_SHADOW_OPAQUE) + return true; + tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t); +#else + if(visibility == PATH_RAY_SHADOW_OPAQUE) + return true; +#endif + } } + break; + } +#endif /* BVH_FEATURE(BVH_MOTION) */ +#if BVH_FEATURE(BVH_HAIR) + case PRIMITIVE_CURVE: + case PRIMITIVE_MOTION_CURVE: { + for(; primAddr < primAddr2; primAddr++) { +#if defined(__KERNEL_DEBUG__) + isect->num_traversal_steps++; #endif -#if FEATURE(BVH_HAIR) - case PRIMITIVE_CURVE: - case PRIMITIVE_MOTION_CURVE: { - if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) + kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); + bool hit; + if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) hit = bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax); else hit = bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax); - break; - } -#endif - default: { - hit = false; - break; - } - } - - /* shadow ray early termination */ + if(hit) { + /* shadow ray early termination */ #if defined(__KERNEL_SSE2__) - if(hit) { - if(visibility == PATH_RAY_SHADOW_OPAQUE) - return true; - - tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t); - } + if(visibility == PATH_RAY_SHADOW_OPAQUE) + return true; + tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t); #else - if(hit && visibility == PATH_RAY_SHADOW_OPAQUE) - return true; + if(visibility == PATH_RAY_SHADOW_OPAQUE) + return true; #endif - - primAddr++; + } + } + break; + } +#endif /* BVH_FEATURE(BVH_HAIR) */ } } -#if FEATURE(BVH_INSTANCING) +#if BVH_FEATURE(BVH_INSTANCING) else { /* instance push */ object = kernel_tex_fetch(__prim_object, -primAddr-1); -#if FEATURE(BVH_MOTION) +#if BVH_FEATURE(BVH_MOTION) bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_tfm); #else bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect->t); #endif + triangle_intersect_precalc(dir, &isect_precalc); #if defined(__KERNEL_SSE2__) Psplat[0] = ssef(P.x); @@ -312,24 +359,30 @@ ccl_device bool BVH_FUNCTION_NAME #endif ++stackPtr; + kernel_assert(stackPtr < BVH_STACK_SIZE); traversalStack[stackPtr] = ENTRYPOINT_SENTINEL; nodeAddr = kernel_tex_fetch(__object_node, object); + +#if defined(__KERNEL_DEBUG__) + isect->num_traversed_instances++; +#endif } } -#endif +#endif /* FEATURE(BVH_INSTANCING) */ } while(nodeAddr != ENTRYPOINT_SENTINEL); -#if FEATURE(BVH_INSTANCING) +#if BVH_FEATURE(BVH_INSTANCING) if(stackPtr >= 0) { kernel_assert(object != OBJECT_NONE); /* instance pop */ -#if FEATURE(BVH_MOTION) +#if BVH_FEATURE(BVH_MOTION) bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_tfm); #else bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &isect->t); #endif + triangle_intersect_precalc(dir, &isect_precalc); #if defined(__KERNEL_SSE2__) Psplat[0] = ssef(P.x); @@ -345,13 +398,52 @@ ccl_device bool BVH_FUNCTION_NAME nodeAddr = traversalStack[stackPtr]; --stackPtr; } -#endif +#endif /* FEATURE(BVH_INSTANCING) */ } while(nodeAddr != ENTRYPOINT_SENTINEL); return (isect->prim != PRIM_NONE); } -#undef FEATURE +ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg, + const Ray *ray, + Intersection *isect, + const uint visibility +#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH) + , uint *lcg_state, + float difl, + float extmax +#endif + ) +{ +#ifdef __QBVH__ + if(kernel_data.bvh.use_qbvh) { + return BVH_FUNCTION_FULL_NAME(QBVH)(kg, + ray, + isect, + visibility +#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH) + , lcg_state, + difl, + extmax +#endif + ); + } + else +#endif + { + kernel_assert(kernel_data.bvh.use_qbvh == false); + return BVH_FUNCTION_FULL_NAME(BVH)(kg, + ray, + isect, + visibility +#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH) + , lcg_state, + difl, + extmax +#endif + ); + } +} + #undef BVH_FUNCTION_NAME #undef BVH_FUNCTION_FEATURES - |