Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/kernel/bvh/bvh.h
| Show All 19 Lines | |||||
| * of the same BVH traversal function for faster rendering when some types of | * of the same BVH traversal function for faster rendering when some types of | ||||
| * primitives are not needed, using #includes to work around the lack of | * primitives are not needed, using #includes to work around the lack of | ||||
| * C++ templates in OpenCL. | * C++ templates in OpenCL. | ||||
| * | * | ||||
| * Originally based on "Understanding the Efficiency of Ray Traversal on GPUs", | * Originally based on "Understanding the Efficiency of Ray Traversal on GPUs", | ||||
| * the code has been extended and modified to support more primitives and work | * the code has been extended and modified to support more primitives and work | ||||
| * with CPU/CUDA/OpenCL. */ | * with CPU/CUDA/OpenCL. */ | ||||
| #pragma once | |||||
| #ifdef __EMBREE__ | #ifdef __EMBREE__ | ||||
| # include "kernel/bvh/bvh_embree.h" | # include "kernel/bvh/bvh_embree.h" | ||||
| #endif | #endif | ||||
| #include "kernel/bvh/bvh_types.h" | #include "kernel/bvh/bvh_types.h" | ||||
| #include "kernel/bvh/bvh_util.h" | #include "kernel/bvh/bvh_util.h" | ||||
| CCL_NAMESPACE_BEGIN | CCL_NAMESPACE_BEGIN | ||||
| ▲ Show 20 Lines • Show All 111 Lines • ▼ Show 20 Lines | ccl_device_inline bool scene_intersect_valid(const Ray *ray) | ||||
| * From production scenes so far it seems it's enough to test first element | * From production scenes so far it seems it's enough to test first element | ||||
| * only. | * only. | ||||
| * Scene intersection may also called with empty rays for conditional trace | * Scene intersection may also called with empty rays for conditional trace | ||||
| * calls that evaluate to false, so filter those out. | * calls that evaluate to false, so filter those out. | ||||
| */ | */ | ||||
| return isfinite_safe(ray->P.x) && isfinite_safe(ray->D.x) && len_squared(ray->D) != 0.0f; | return isfinite_safe(ray->P.x) && isfinite_safe(ray->D.x) && len_squared(ray->D) != 0.0f; | ||||
| } | } | ||||
| ccl_device_intersect bool scene_intersect(KernelGlobals *kg, | ccl_device_intersect bool scene_intersect(const KernelGlobals *kg, | ||||
| const Ray *ray, | const Ray *ray, | ||||
| const uint visibility, | const uint visibility, | ||||
| Intersection *isect) | Intersection *isect) | ||||
| { | { | ||||
| PROFILING_INIT(kg, PROFILING_INTERSECT); | |||||
| #ifdef __KERNEL_OPTIX__ | #ifdef __KERNEL_OPTIX__ | ||||
| uint p0 = 0; | uint p0 = 0; | ||||
| uint p1 = 0; | uint p1 = 0; | ||||
| uint p2 = 0; | uint p2 = 0; | ||||
| uint p3 = 0; | uint p3 = 0; | ||||
| uint p4 = visibility; | uint p4 = visibility; | ||||
| uint p5 = PRIMITIVE_NONE; | uint p5 = PRIMITIVE_NONE; | ||||
| ▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | # ifdef __HAIR__ | ||||
| } | } | ||||
| # endif /* __HAIR__ */ | # endif /* __HAIR__ */ | ||||
| return bvh_intersect(kg, ray, isect, visibility); | return bvh_intersect(kg, ray, isect, visibility); | ||||
| #endif /* __KERNEL_OPTIX__ */ | #endif /* __KERNEL_OPTIX__ */ | ||||
| } | } | ||||
| #ifdef __BVH_LOCAL__ | #ifdef __BVH_LOCAL__ | ||||
| ccl_device_intersect bool scene_intersect_local(KernelGlobals *kg, | ccl_device_intersect bool scene_intersect_local(const KernelGlobals *kg, | ||||
| const Ray *ray, | const Ray *ray, | ||||
| LocalIntersection *local_isect, | LocalIntersection *local_isect, | ||||
| int local_object, | int local_object, | ||||
| uint *lcg_state, | uint *lcg_state, | ||||
| int max_hits) | int max_hits) | ||||
| { | { | ||||
| PROFILING_INIT(kg, PROFILING_INTERSECT_LOCAL); | |||||
| # ifdef __KERNEL_OPTIX__ | # ifdef __KERNEL_OPTIX__ | ||||
| uint p0 = ((uint64_t)lcg_state) & 0xFFFFFFFF; | uint p0 = ((uint64_t)lcg_state) & 0xFFFFFFFF; | ||||
| uint p1 = (((uint64_t)lcg_state) >> 32) & 0xFFFFFFFF; | uint p1 = (((uint64_t)lcg_state) >> 32) & 0xFFFFFFFF; | ||||
| uint p2 = ((uint64_t)local_isect) & 0xFFFFFFFF; | uint p2 = ((uint64_t)local_isect) & 0xFFFFFFFF; | ||||
| uint p3 = (((uint64_t)local_isect) >> 32) & 0xFFFFFFFF; | uint p3 = (((uint64_t)local_isect) >> 32) & 0xFFFFFFFF; | ||||
| uint p4 = local_object; | uint p4 = local_object; | ||||
| // Is set to zero on miss or if ray is aborted, so can be used as return value | // Is set to zero on miss or if ray is aborted, so can be used as return value | ||||
| uint p5 = max_hits; | uint p5 = max_hits; | ||||
| ▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | if (kernel_data.bvh.scene) { | ||||
| /* If this object has its own BVH, use it. */ | /* If this object has its own BVH, use it. */ | ||||
| if (has_bvh) { | if (has_bvh) { | ||||
| RTCGeometry geom = rtcGetGeometry(kernel_data.bvh.scene, local_object * 2); | RTCGeometry geom = rtcGetGeometry(kernel_data.bvh.scene, local_object * 2); | ||||
| if (geom) { | if (geom) { | ||||
| float3 P = ray->P; | float3 P = ray->P; | ||||
| float3 dir = ray->D; | float3 dir = ray->D; | ||||
| float3 idir = ray->D; | float3 idir = ray->D; | ||||
| Transform ob_itfm; | Transform ob_itfm; | ||||
| rtc_ray.tfar = bvh_instance_motion_push( | rtc_ray.tfar = ray->t * | ||||
| kg, local_object, ray, &P, &dir, &idir, ray->t, &ob_itfm); | bvh_instance_motion_push(kg, local_object, ray, &P, &dir, &idir, &ob_itfm); | ||||
| /* bvh_instance_motion_push() returns the inverse transform but | /* bvh_instance_motion_push() returns the inverse transform but | ||||
| * it's not needed here. */ | * it's not needed here. */ | ||||
| (void)ob_itfm; | (void)ob_itfm; | ||||
| rtc_ray.org_x = P.x; | rtc_ray.org_x = P.x; | ||||
| rtc_ray.org_y = P.y; | rtc_ray.org_y = P.y; | ||||
| rtc_ray.org_z = P.z; | rtc_ray.org_z = P.z; | ||||
| rtc_ray.dir_x = dir.x; | rtc_ray.dir_x = dir.x; | ||||
| Show All 22 Lines | # ifdef __OBJECT_MOTION__ | ||||
| } | } | ||||
| # endif /* __OBJECT_MOTION__ */ | # endif /* __OBJECT_MOTION__ */ | ||||
| return bvh_intersect_local(kg, ray, local_isect, local_object, lcg_state, max_hits); | return bvh_intersect_local(kg, ray, local_isect, local_object, lcg_state, max_hits); | ||||
| # endif /* __KERNEL_OPTIX__ */ | # endif /* __KERNEL_OPTIX__ */ | ||||
| } | } | ||||
| #endif | #endif | ||||
| #ifdef __SHADOW_RECORD_ALL__ | #ifdef __SHADOW_RECORD_ALL__ | ||||
| ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals *kg, | ccl_device_intersect bool scene_intersect_shadow_all(const KernelGlobals *kg, | ||||
| const Ray *ray, | const Ray *ray, | ||||
| Intersection *isect, | Intersection *isect, | ||||
| uint visibility, | uint visibility, | ||||
| uint max_hits, | uint max_hits, | ||||
| uint *num_hits) | uint *num_hits) | ||||
| { | { | ||||
| PROFILING_INIT(kg, PROFILING_INTERSECT_SHADOW_ALL); | |||||
| # ifdef __KERNEL_OPTIX__ | # ifdef __KERNEL_OPTIX__ | ||||
| uint p0 = ((uint64_t)isect) & 0xFFFFFFFF; | uint p0 = ((uint64_t)isect) & 0xFFFFFFFF; | ||||
| uint p1 = (((uint64_t)isect) >> 32) & 0xFFFFFFFF; | uint p1 = (((uint64_t)isect) >> 32) & 0xFFFFFFFF; | ||||
| uint p3 = max_hits; | uint p3 = max_hits; | ||||
| uint p4 = visibility; | uint p4 = visibility; | ||||
| uint p5 = false; | uint p5 = false; | ||||
| *num_hits = 0; // Initialize hit count to zero | *num_hits = 0; // Initialize hit count to zero | ||||
| Show All 23 Lines | if (!scene_intersect_valid(ray)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| # ifdef __EMBREE__ | # ifdef __EMBREE__ | ||||
| if (kernel_data.bvh.scene) { | if (kernel_data.bvh.scene) { | ||||
| CCLIntersectContext ctx(kg, CCLIntersectContext::RAY_SHADOW_ALL); | CCLIntersectContext ctx(kg, CCLIntersectContext::RAY_SHADOW_ALL); | ||||
| ctx.isect_s = isect; | ctx.isect_s = isect; | ||||
| ctx.max_hits = max_hits; | ctx.max_hits = max_hits; | ||||
| ctx.num_hits = 0; | |||||
| IntersectContext rtc_ctx(&ctx); | IntersectContext rtc_ctx(&ctx); | ||||
| RTCRay rtc_ray; | RTCRay rtc_ray; | ||||
| kernel_embree_setup_ray(*ray, rtc_ray, visibility); | kernel_embree_setup_ray(*ray, rtc_ray, visibility); | ||||
| rtcOccluded1(kernel_data.bvh.scene, &rtc_ctx.context, &rtc_ray); | rtcOccluded1(kernel_data.bvh.scene, &rtc_ctx.context, &rtc_ray); | ||||
| if (ctx.num_hits > max_hits) { | |||||
| return true; | |||||
| } | |||||
| *num_hits = ctx.num_hits; | *num_hits = ctx.num_hits; | ||||
| return rtc_ray.tfar == -INFINITY; | return ctx.opaque_hit; | ||||
| } | } | ||||
| # endif /* __EMBREE__ */ | # endif /* __EMBREE__ */ | ||||
| # ifdef __OBJECT_MOTION__ | # ifdef __OBJECT_MOTION__ | ||||
| if (kernel_data.bvh.have_motion) { | if (kernel_data.bvh.have_motion) { | ||||
| # ifdef __HAIR__ | # ifdef __HAIR__ | ||||
| if (kernel_data.bvh.have_curves) { | if (kernel_data.bvh.have_curves) { | ||||
| return bvh_intersect_shadow_all_hair_motion(kg, ray, isect, visibility, max_hits, num_hits); | return bvh_intersect_shadow_all_hair_motion(kg, ray, isect, visibility, max_hits, num_hits); | ||||
| Show All 11 Lines | |||||
| # endif /* __HAIR__ */ | # endif /* __HAIR__ */ | ||||
| return bvh_intersect_shadow_all(kg, ray, isect, visibility, max_hits, num_hits); | return bvh_intersect_shadow_all(kg, ray, isect, visibility, max_hits, num_hits); | ||||
| # endif /* __KERNEL_OPTIX__ */ | # endif /* __KERNEL_OPTIX__ */ | ||||
| } | } | ||||
| #endif /* __SHADOW_RECORD_ALL__ */ | #endif /* __SHADOW_RECORD_ALL__ */ | ||||
| #ifdef __VOLUME__ | #ifdef __VOLUME__ | ||||
| ccl_device_intersect bool scene_intersect_volume(KernelGlobals *kg, | ccl_device_intersect bool scene_intersect_volume(const KernelGlobals *kg, | ||||
| const Ray *ray, | const Ray *ray, | ||||
| Intersection *isect, | Intersection *isect, | ||||
| const uint visibility) | const uint visibility) | ||||
| { | { | ||||
| PROFILING_INIT(kg, PROFILING_INTERSECT_VOLUME); | |||||
| # ifdef __KERNEL_OPTIX__ | # ifdef __KERNEL_OPTIX__ | ||||
| uint p0 = 0; | uint p0 = 0; | ||||
| uint p1 = 0; | uint p1 = 0; | ||||
| uint p2 = 0; | uint p2 = 0; | ||||
| uint p3 = 0; | uint p3 = 0; | ||||
| uint p4 = visibility; | uint p4 = visibility; | ||||
| uint p5 = PRIMITIVE_NONE; | uint p5 = PRIMITIVE_NONE; | ||||
| Show All 36 Lines | |||||
| # endif /* __OBJECT_MOTION__ */ | # endif /* __OBJECT_MOTION__ */ | ||||
| return bvh_intersect_volume(kg, ray, isect, visibility); | return bvh_intersect_volume(kg, ray, isect, visibility); | ||||
| # endif /* __KERNEL_OPTIX__ */ | # endif /* __KERNEL_OPTIX__ */ | ||||
| } | } | ||||
| #endif /* __VOLUME__ */ | #endif /* __VOLUME__ */ | ||||
| #ifdef __VOLUME_RECORD_ALL__ | #ifdef __VOLUME_RECORD_ALL__ | ||||
| ccl_device_intersect uint scene_intersect_volume_all(KernelGlobals *kg, | ccl_device_intersect uint scene_intersect_volume_all(const KernelGlobals *kg, | ||||
| const Ray *ray, | const Ray *ray, | ||||
| Intersection *isect, | Intersection *isect, | ||||
| const uint max_hits, | const uint max_hits, | ||||
| const uint visibility) | const uint visibility) | ||||
| { | { | ||||
| PROFILING_INIT(kg, PROFILING_INTERSECT_VOLUME_ALL); | |||||
| if (!scene_intersect_valid(ray)) { | if (!scene_intersect_valid(ray)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| # ifdef __EMBREE__ | # ifdef __EMBREE__ | ||||
| if (kernel_data.bvh.scene) { | if (kernel_data.bvh.scene) { | ||||
| CCLIntersectContext ctx(kg, CCLIntersectContext::RAY_VOLUME_ALL); | CCLIntersectContext ctx(kg, CCLIntersectContext::RAY_VOLUME_ALL); | ||||
| ctx.isect_s = isect; | ctx.isect_s = isect; | ||||
| Show All 21 Lines | |||||