From f8a999c965435ed6cf3ed83aa4f1121c79f2a403 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 23 Mar 2017 13:01:42 +0100 Subject: Cycles: Move triangle intersection precalc to an util file This is a preparation work for the followup commit which wil l move remaining parts of Woop intersection logic to an utility file. Doing it as a separate commit to keep changes more atomic and easier to bisect when/if needed. --- intern/cycles/kernel/bvh/bvh_shadow_all.h | 10 +-- intern/cycles/kernel/bvh/bvh_subsurface.h | 4 +- intern/cycles/kernel/bvh/bvh_traversal.h | 8 +-- intern/cycles/kernel/bvh/bvh_volume.h | 8 +-- intern/cycles/kernel/bvh/bvh_volume_all.h | 10 +-- intern/cycles/kernel/bvh/qbvh_shadow_all.h | 8 +-- intern/cycles/kernel/bvh/qbvh_subsurface.h | 4 +- intern/cycles/kernel/bvh/qbvh_traversal.h | 8 +-- intern/cycles/kernel/bvh/qbvh_volume.h | 8 +-- intern/cycles/kernel/bvh/qbvh_volume_all.h | 8 +-- .../cycles/kernel/geom/geom_triangle_intersect.h | 60 +---------------- intern/cycles/util/util_math_intersect.h | 76 ++++++++++++++++++++++ 12 files changed, 116 insertions(+), 96 deletions(-) diff --git a/intern/cycles/kernel/bvh/bvh_shadow_all.h b/intern/cycles/kernel/bvh/bvh_shadow_all.h index b4f65bc8efd..a6e23d9f381 100644 --- a/intern/cycles/kernel/bvh/bvh_shadow_all.h +++ b/intern/cycles/kernel/bvh/bvh_shadow_all.h @@ -100,8 +100,8 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); #endif /* __KERNEL_SSE2__ */ - IsectPrecalc isect_precalc; - triangle_intersect_precalc(dir, &isect_precalc); + TriangleIsectPrecalc isect_precalc; + ray_triangle_intersect_precalc(dir, &isect_precalc); /* traversal loop */ do { @@ -314,7 +314,7 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, isect_t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect_t); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); num_hits_in_instance = 0; isect_array->t = isect_t; @@ -354,7 +354,7 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); /* scale isect->t to adjust for instancing */ for(int i = 0; i < num_hits_in_instance; i++) { @@ -367,7 +367,7 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, # else bvh_instance_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); } isect_t = tmax; diff --git a/intern/cycles/kernel/bvh/bvh_subsurface.h b/intern/cycles/kernel/bvh/bvh_subsurface.h index 583f7f7c469..11ea1f89c8b 100644 --- a/intern/cycles/kernel/bvh/bvh_subsurface.h +++ b/intern/cycles/kernel/bvh/bvh_subsurface.h @@ -109,8 +109,8 @@ void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); #endif - IsectPrecalc isect_precalc; - triangle_intersect_precalc(dir, &isect_precalc); + TriangleIsectPrecalc isect_precalc; + ray_triangle_intersect_precalc(dir, &isect_precalc); /* traversal loop */ do { diff --git a/intern/cycles/kernel/bvh/bvh_traversal.h b/intern/cycles/kernel/bvh/bvh_traversal.h index 0eca0c8e38b..7c4671e074f 100644 --- a/intern/cycles/kernel/bvh/bvh_traversal.h +++ b/intern/cycles/kernel/bvh/bvh_traversal.h @@ -104,8 +104,8 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); #endif - IsectPrecalc isect_precalc; - triangle_intersect_precalc(dir, &isect_precalc); + TriangleIsectPrecalc isect_precalc; + ray_triangle_intersect_precalc(dir, &isect_precalc); /* traversal loop */ do { @@ -358,7 +358,7 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, # else isect->t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect->t); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); # if defined(__KERNEL_SSE2__) Psplat[0] = ssef(P.x); @@ -395,7 +395,7 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, # else isect->t = bvh_instance_pop(kg, object, ray, &P, &dir, &idir, isect->t); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); # if defined(__KERNEL_SSE2__) Psplat[0] = ssef(P.x); diff --git a/intern/cycles/kernel/bvh/bvh_volume.h b/intern/cycles/kernel/bvh/bvh_volume.h index 136034aa484..45b5a3c687b 100644 --- a/intern/cycles/kernel/bvh/bvh_volume.h +++ b/intern/cycles/kernel/bvh/bvh_volume.h @@ -97,8 +97,8 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); #endif - IsectPrecalc isect_precalc; - triangle_intersect_precalc(dir, &isect_precalc); + TriangleIsectPrecalc isect_precalc; + ray_triangle_intersect_precalc(dir, &isect_precalc); /* traversal loop */ do { @@ -243,7 +243,7 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, isect->t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect->t); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); # if defined(__KERNEL_SSE2__) Psplat[0] = ssef(P.x); @@ -286,7 +286,7 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, isect->t = bvh_instance_pop(kg, object, ray, &P, &dir, &idir, isect->t); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); # if defined(__KERNEL_SSE2__) Psplat[0] = ssef(P.x); diff --git a/intern/cycles/kernel/bvh/bvh_volume_all.h b/intern/cycles/kernel/bvh/bvh_volume_all.h index 6f3346e7634..62018e06e97 100644 --- a/intern/cycles/kernel/bvh/bvh_volume_all.h +++ b/intern/cycles/kernel/bvh/bvh_volume_all.h @@ -101,8 +101,8 @@ uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); #endif /* __KERNEL_SSE2__ */ - IsectPrecalc isect_precalc; - triangle_intersect_precalc(dir, &isect_precalc); + TriangleIsectPrecalc isect_precalc; + ray_triangle_intersect_precalc(dir, &isect_precalc); /* traversal loop */ do { @@ -294,7 +294,7 @@ uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, isect_t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect_t); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); num_hits_in_instance = 0; isect_array->t = isect_t; @@ -340,7 +340,7 @@ uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, # else bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); /* Scale isect->t to adjust for instancing. */ for(int i = 0; i < num_hits_in_instance; i++) { (isect_array-i-1)->t *= t_fac; @@ -352,7 +352,7 @@ uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, # else bvh_instance_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); } isect_t = tmax; diff --git a/intern/cycles/kernel/bvh/qbvh_shadow_all.h b/intern/cycles/kernel/bvh/qbvh_shadow_all.h index 2a4da3eea82..5a8ec4768d6 100644 --- a/intern/cycles/kernel/bvh/qbvh_shadow_all.h +++ b/intern/cycles/kernel/bvh/qbvh_shadow_all.h @@ -96,8 +96,8 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z); - IsectPrecalc isect_precalc; - triangle_intersect_precalc(dir, &isect_precalc); + TriangleIsectPrecalc isect_precalc; + ray_triangle_intersect_precalc(dir, &isect_precalc); /* Traversal loop. */ do { @@ -414,7 +414,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z)); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); ++stack_ptr; kernel_assert(stack_ptr < BVH_QSTACK_SIZE); @@ -471,7 +471,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z)); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); object = OBJECT_NONE; node_addr = traversal_stack[stack_ptr].addr; diff --git a/intern/cycles/kernel/bvh/qbvh_subsurface.h b/intern/cycles/kernel/bvh/qbvh_subsurface.h index a6431a94e6e..d466fe73d24 100644 --- a/intern/cycles/kernel/bvh/qbvh_subsurface.h +++ b/intern/cycles/kernel/bvh/qbvh_subsurface.h @@ -105,8 +105,8 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z); - IsectPrecalc isect_precalc; - triangle_intersect_precalc(dir, &isect_precalc); + TriangleIsectPrecalc isect_precalc; + ray_triangle_intersect_precalc(dir, &isect_precalc); /* Traversal loop. */ do { diff --git a/intern/cycles/kernel/bvh/qbvh_traversal.h b/intern/cycles/kernel/bvh/qbvh_traversal.h index c20a8f3703f..bf69bfade1b 100644 --- a/intern/cycles/kernel/bvh/qbvh_traversal.h +++ b/intern/cycles/kernel/bvh/qbvh_traversal.h @@ -106,8 +106,8 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z); - IsectPrecalc isect_precalc; - triangle_intersect_precalc(dir, &isect_precalc); + TriangleIsectPrecalc isect_precalc; + ray_triangle_intersect_precalc(dir, &isect_precalc); /* Traversal loop. */ do { @@ -447,7 +447,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z)); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); ++stack_ptr; kernel_assert(stack_ptr < BVH_QSTACK_SIZE); @@ -489,7 +489,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z)); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); object = OBJECT_NONE; node_addr = traversal_stack[stack_ptr].addr; diff --git a/intern/cycles/kernel/bvh/qbvh_volume.h b/intern/cycles/kernel/bvh/qbvh_volume.h index 859c5da808b..d34ddb6ea2b 100644 --- a/intern/cycles/kernel/bvh/qbvh_volume.h +++ b/intern/cycles/kernel/bvh/qbvh_volume.h @@ -91,8 +91,8 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z); - IsectPrecalc isect_precalc; - triangle_intersect_precalc(dir, &isect_precalc); + TriangleIsectPrecalc isect_precalc; + ray_triangle_intersect_precalc(dir, &isect_precalc); /* Traversal loop. */ do { @@ -316,7 +316,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z)); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); ++stack_ptr; kernel_assert(stack_ptr < BVH_QSTACK_SIZE); @@ -362,7 +362,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z)); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); object = OBJECT_NONE; node_addr = traversal_stack[stack_ptr].addr; diff --git a/intern/cycles/kernel/bvh/qbvh_volume_all.h b/intern/cycles/kernel/bvh/qbvh_volume_all.h index bbe588c878f..4e1ee04916b 100644 --- a/intern/cycles/kernel/bvh/qbvh_volume_all.h +++ b/intern/cycles/kernel/bvh/qbvh_volume_all.h @@ -95,8 +95,8 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z); - IsectPrecalc isect_precalc; - triangle_intersect_precalc(dir, &isect_precalc); + TriangleIsectPrecalc isect_precalc; + ray_triangle_intersect_precalc(dir, &isect_precalc); /* Traversal loop. */ do { @@ -367,7 +367,7 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z)); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); num_hits_in_instance = 0; isect_array->t = isect_t; @@ -432,7 +432,7 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z)); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); object = OBJECT_NONE; node_addr = traversal_stack[stack_ptr].addr; diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h index ca6e54c6b33..12700c7a246 100644 --- a/intern/cycles/kernel/geom/geom_triangle_intersect.h +++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h @@ -40,64 +40,8 @@ CCL_NAMESPACE_BEGIN * http://jcgt.org/published/0002/01/05/paper.pdf */ -/* Precalculated data for the ray->tri intersection. */ -typedef struct IsectPrecalc { - /* Maximal dimension kz, and orthogonal dimensions. */ - int kx, ky, kz; - - /* Shear constants. */ - float Sx, Sy, Sz; -} IsectPrecalc; - -#if (defined(__KERNEL_OPENCL_APPLE__)) || \ - (defined(__KERNEL_CUDA__) && (defined(i386) || defined(_M_IX86))) -ccl_device_noinline -#else -ccl_device_inline -#endif -void triangle_intersect_precalc(float3 dir, - IsectPrecalc *isect_precalc) -{ - /* Calculate dimension where the ray direction is maximal. */ -#ifndef __KERNEL_SSE__ - int kz = util_max_axis(make_float3(fabsf(dir.x), - fabsf(dir.y), - fabsf(dir.z))); - int kx = kz + 1; if(kx == 3) kx = 0; - int ky = kx + 1; if(ky == 3) ky = 0; -#else - int kx, ky, kz; - /* Avoiding mispredicted branch on direction. */ - kz = util_max_axis(fabs(dir)); - static const char inc_xaxis[] = {1, 2, 0, 55}; - static const char inc_yaxis[] = {2, 0, 1, 55}; - kx = inc_xaxis[kz]; - ky = inc_yaxis[kz]; -#endif - - float dir_kz = IDX(dir, kz); - - /* Swap kx and ky dimensions to preserve winding direction of triangles. */ - if(dir_kz < 0.0f) { - int tmp = kx; - kx = ky; - ky = tmp; - } - - /* Calculate the shear constants. */ - float inv_dir_z = 1.0f / dir_kz; - isect_precalc->Sx = IDX(dir, kx) * inv_dir_z; - isect_precalc->Sy = IDX(dir, ky) * inv_dir_z; - isect_precalc->Sz = inv_dir_z; - - /* Store the dimensions. */ - isect_precalc->kx = kx; - isect_precalc->ky = ky; - isect_precalc->kz = kz; -} - ccl_device_inline bool triangle_intersect(KernelGlobals *kg, - const IsectPrecalc *isect_precalc, + const TriangleIsectPrecalc *isect_precalc, Intersection *isect, float3 P, uint visibility, @@ -255,7 +199,7 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg, #ifdef __SUBSURFACE__ ccl_device_inline void triangle_intersect_subsurface( KernelGlobals *kg, - const IsectPrecalc *isect_precalc, + const TriangleIsectPrecalc *isect_precalc, SubsurfaceIntersection *ss_isect, float3 P, int object, diff --git a/intern/cycles/util/util_math_intersect.h b/intern/cycles/util/util_math_intersect.h index 870f33cee0c..7e02c04d939 100644 --- a/intern/cycles/util/util_math_intersect.h +++ b/intern/cycles/util/util_math_intersect.h @@ -79,6 +79,82 @@ ccl_device bool ray_aligned_disk_intersect( return true; } +/* Optimized watertight ray-triangle intersection. + * + * Sven Woop + * Watertight Ray/Triangle Intersection + * + * http://jcgt.org/published/0002/01/05/paper.pdf + */ + +/* Precalculated data for the ray->tri intersection. */ +typedef struct TriangleIsectPrecalc { + /* Maximal dimension kz, and orthogonal dimensions. */ + int kx, ky, kz; + + /* Shear constants. */ + float Sx, Sy, Sz; +} TriangleIsectPrecalc; + +/* Workaround stupidness of CUDA/OpenCL which doesn't allow to access indexed + * component of float3 value. + */ +#ifdef __KERNEL_GPU__ +# define IDX(vec, idx) \ + ((idx == 0) ? ((vec).x) : ( (idx == 1) ? ((vec).y) : ((vec).z) )) +#else +# define IDX(vec, idx) ((vec)[idx]) +#endif + +#if (defined(__KERNEL_OPENCL_APPLE__)) || \ + (defined(__KERNEL_CUDA__) && (defined(i386) || defined(_M_IX86))) +ccl_device_noinline +#else +ccl_device_inline +#endif +void ray_triangle_intersect_precalc(float3 dir, + TriangleIsectPrecalc *isect_precalc) +{ + /* Calculate dimension where the ray direction is maximal. */ +#ifndef __KERNEL_SSE__ + int kz = util_max_axis(make_float3(fabsf(dir.x), + fabsf(dir.y), + fabsf(dir.z))); + int kx = kz + 1; if(kx == 3) kx = 0; + int ky = kx + 1; if(ky == 3) ky = 0; +#else + int kx, ky, kz; + /* Avoiding mispredicted branch on direction. */ + kz = util_max_axis(fabs(dir)); + static const char inc_xaxis[] = {1, 2, 0, 55}; + static const char inc_yaxis[] = {2, 0, 1, 55}; + kx = inc_xaxis[kz]; + ky = inc_yaxis[kz]; +#endif + + float dir_kz = IDX(dir, kz); + + /* Swap kx and ky dimensions to preserve winding direction of triangles. */ + if(dir_kz < 0.0f) { + int tmp = kx; + kx = ky; + ky = tmp; + } + + /* Calculate the shear constants. */ + float inv_dir_z = 1.0f / dir_kz; + isect_precalc->Sx = IDX(dir, kx) * inv_dir_z; + isect_precalc->Sy = IDX(dir, ky) * inv_dir_z; + isect_precalc->Sz = inv_dir_z; + + /* Store the dimensions. */ + isect_precalc->kx = kx; + isect_precalc->ky = ky; + isect_precalc->kz = kz; +} + +#undef IDX + ccl_device_inline bool ray_triangle_intersect_uv( float3 ray_P, float3 ray_D, float ray_t, float3 v0, float3 v1, float3 v2, -- cgit v1.2.3