Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/kernel/geom/geom_qbvh_volume.h
| Context not available. | |||||
| * | * | ||||
| */ | */ | ||||
| ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, | ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, | ||||
| const Ray *ray, | const Ray *ray, | ||||
| Intersection *isect) | Intersection *isect_array, | ||||
| const uint max_hits) | |||||
| { | { | ||||
| /* TODO(sergey): | /* TODO(sergey): | ||||
| * - Test if pushing distance on the stack helps. | * - Test if pushing distance on the stack helps. | ||||
| Context not available. | |||||
| int nodeAddr = kernel_data.bvh.root; | int nodeAddr = kernel_data.bvh.root; | ||||
| /* Ray parameters in registers. */ | /* Ray parameters in registers. */ | ||||
| const float tmax = ray->t; | |||||
| float3 P = ray->P; | float3 P = ray->P; | ||||
| float3 dir = bvh_clamp_direction(ray->D); | float3 dir = bvh_clamp_direction(ray->D); | ||||
| float3 idir = bvh_inverse_direction(dir); | float3 idir = bvh_inverse_direction(dir); | ||||
| int object = OBJECT_NONE; | int object = OBJECT_NONE; | ||||
| float isect_t = tmax; | |||||
| const uint visibility = PATH_RAY_ALL_VISIBILITY; | const uint visibility = PATH_RAY_ALL_VISIBILITY; | ||||
| Context not available. | |||||
| } | } | ||||
| #endif | #endif | ||||
| isect->t = ray->t; | #if BVH_FEATURE(BVH_INSTANCING) | ||||
| isect->u = 0.0f; | int num_hits_in_instance = 0; | ||||
| isect->v = 0.0f; | #endif | ||||
| isect->prim = PRIM_NONE; | |||||
| isect->object = OBJECT_NONE; | |||||
| ssef tnear(0.0f), tfar(ray->t); | uint num_hits = 0; | ||||
| isect_array->t = tmax; | |||||
| ssef tnear(0.0f), tfar(isect_t); | |||||
| sse3f idir4(ssef(idir.x), ssef(idir.y), ssef(idir.z)); | sse3f idir4(ssef(idir.x), ssef(idir.y), ssef(idir.z)); | ||||
| #ifdef __KERNEL_AVX2__ | #ifdef __KERNEL_AVX2__ | ||||
| Context not available. | |||||
| do { | do { | ||||
| /* Traverse internal nodes. */ | /* Traverse internal nodes. */ | ||||
| while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) { | while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) { | ||||
| #if defined(__KERNEL_DEBUG__) | |||||
| isect->num_traversal_steps++; | |||||
| #endif | |||||
| ssef dist; | ssef dist; | ||||
| int traverseChild = qbvh_node_intersect(kg, | int traverseChild = qbvh_node_intersect(kg, | ||||
| tnear, | tnear, | ||||
| Context not available. | |||||
| int primAddr2 = __float_as_int(leaf.y); | int primAddr2 = __float_as_int(leaf.y); | ||||
| const uint type = __float_as_int(leaf.w); | const uint type = __float_as_int(leaf.w); | ||||
| const uint p_type = type & PRIMITIVE_ALL; | const uint p_type = type & PRIMITIVE_ALL; | ||||
| bool hit; | |||||
| /* Pop. */ | /* Pop. */ | ||||
| nodeAddr = traversalStack[stackPtr].addr; | nodeAddr = traversalStack[stackPtr].addr; | ||||
| Context not available. | |||||
| continue; | continue; | ||||
| } | } | ||||
| /* Intersect ray against primitive. */ | /* Intersect ray against primitive. */ | ||||
| triangle_intersect(kg, &isect_precalc, isect, P, visibility, object, primAddr); | hit = triangle_intersect(kg, &isect_precalc, isect_array, P, visibility, object, primAddr); | ||||
| if(hit) { | |||||
| /* Move on to next entry in intersections array. */ | |||||
| isect_array++; | |||||
| num_hits++; | |||||
| #if BVH_FEATURE(BVH_INSTANCING) | |||||
| num_hits_in_instance++; | |||||
| #endif | |||||
| isect_array->t = isect_t; | |||||
| if(num_hits == max_hits) { | |||||
| #if BVH_FEATURE(BVH_INSTANCING) | |||||
| #if BVH_FEATURE(BVH_MOTION) | |||||
| float t_fac = len(transform_direction(&ob_tfm, 1.0f/idir)); | |||||
| #else | |||||
| Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); | |||||
| float t_fac = len(transform_direction(&tfm, 1.0f/idir)); | |||||
| #endif | |||||
| for(int i = 0; i < num_hits_in_instance; i++) { | |||||
| (isect_array-i-1)->t *= t_fac; | |||||
| } | |||||
| #endif /* BVH_FEATURE(BVH_INSTANCING) */ | |||||
| return num_hits; | |||||
| } | |||||
| } | |||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| Context not available. | |||||
| continue; | continue; | ||||
| } | } | ||||
| /* Intersect ray against primitive. */ | /* Intersect ray against primitive. */ | ||||
| motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr); | hit = motion_triangle_intersect(kg, isect_array, P, dir, ray->time, visibility, object, primAddr); | ||||
| if(hit) { | |||||
| /* Move on to next entry in intersections array. */ | |||||
| isect_array++; | |||||
| num_hits++; | |||||
| #if BVH_FEATURE(BVH_INSTANCING) | |||||
| num_hits_in_instance++; | |||||
| #endif | |||||
| isect_array->t = isect_t; | |||||
| if(num_hits == max_hits) { | |||||
| #if BVH_FEATURE(BVH_INSTANCING) | |||||
| # if BVH_FEATURE(BVH_MOTION) | |||||
| float t_fac = len(transform_direction(&ob_tfm, 1.0f/idir)); | |||||
| # else | |||||
| Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); | |||||
| float t_fac = len(transform_direction(&tfm, 1.0f/idir)); | |||||
| #endif | |||||
| for(int i = 0; i < num_hits_in_instance; i++) { | |||||
| (isect_array-i-1)->t *= t_fac; | |||||
| } | |||||
| #endif /* BVH_FEATURE(BVH_INSTANCING) */ | |||||
| return num_hits; | |||||
| } | |||||
| } | |||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| Context not available. | |||||
| } | } | ||||
| /* Intersect ray against primitive. */ | /* Intersect ray against primitive. */ | ||||
| if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) | if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) | ||||
| bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0); | hit = bvh_cardinal_curve_intersect(kg, isect_array, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0); | ||||
| else | else | ||||
| bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0); | hit = bvh_curve_intersect(kg, isect_array, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0); | ||||
| if(hit) { | |||||
| /* Move on to next entry in intersections array. */ | |||||
| isect_array++; | |||||
| num_hits++; | |||||
| #if BVH_FEATURE(BVH_INSTANCING) | |||||
| num_hits_in_instance++; | |||||
| #endif | |||||
| isect_array->t = isect_t; | |||||
| if(num_hits == max_hits) { | |||||
| #if BVH_FEATURE(BVH_INSTANCING) | |||||
| # if BVH_FEATURE(BVH_MOTION) | |||||
| float t_fac = len(transform_direction(&ob_tfm, 1.0f/idir)); | |||||
| # else | |||||
| Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); | |||||
| float t_fac = len(transform_direction(&tfm, 1.0f/idir)); | |||||
| #endif | |||||
| for(int i = 0; i < num_hits_in_instance; i++) { | |||||
| (isect_array-i-1)->t *= t_fac; | |||||
| } | |||||
| #endif /* BVH_FEATURE(BVH_INSTANCING) */ | |||||
| return num_hits; | |||||
| } | |||||
| } | |||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| Context not available. | |||||
| if(object_flag & SD_OBJECT_HAS_VOLUME) { | if(object_flag & SD_OBJECT_HAS_VOLUME) { | ||||
| #if BVH_FEATURE(BVH_MOTION) | #if BVH_FEATURE(BVH_MOTION) | ||||
| bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_tfm); | bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_tfm); | ||||
| #else | #else | ||||
| bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect->t); | bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect_t); | ||||
| #endif | #endif | ||||
| if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; } | if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; } | ||||
| if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; } | if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; } | ||||
| if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; } | if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; } | ||||
| tfar = ssef(isect->t); | tfar = ssef(isect_t); | ||||
| idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z)); | idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z)); | ||||
| #ifdef __KERNEL_AVX2__ | #ifdef __KERNEL_AVX2__ | ||||
| P_idir = P*idir; | P_idir = P*idir; | ||||
| Context not available. | |||||
| org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z)); | org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z)); | ||||
| #endif | #endif | ||||
| triangle_intersect_precalc(dir, &isect_precalc); | triangle_intersect_precalc(dir, &isect_precalc); | ||||
| num_hits_in_instance = 0; | |||||
| isect_array->t = isect_t; | |||||
| ++stackPtr; | ++stackPtr; | ||||
| kernel_assert(stackPtr < BVH_QSTACK_SIZE); | kernel_assert(stackPtr < BVH_QSTACK_SIZE); | ||||
| Context not available. | |||||
| kernel_assert(object != OBJECT_NONE); | kernel_assert(object != OBJECT_NONE); | ||||
| /* Instance pop. */ | /* Instance pop. */ | ||||
| if(num_hits_in_instance) { | |||||
| float t_fac; | |||||
| #if BVH_FEATURE(BVH_MOTION) | #if BVH_FEATURE(BVH_MOTION) | ||||
| bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_tfm); | bvh_instance_motion_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac, &ob_tfm); | ||||
| #else | #else | ||||
| bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &isect->t); | bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac); | ||||
| #endif | #endif | ||||
| 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; | |||||
| } | |||||
| } | |||||
| else { | |||||
| float ignore_t = FLT_MAX; | |||||
| #if BVH_FEATURE(BVH_MOTION) | |||||
| bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &ignore_t, &ob_tfm); | |||||
| #else | |||||
| bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &ignore_t); | |||||
| #endif | |||||
| triangle_intersect_precalc(dir, &isect_precalc); | |||||
| } | |||||
| if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; } | if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; } | ||||
| if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; } | if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; } | ||||
| if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; } | if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; } | ||||
| tfar = ssef(isect->t); | tfar = ssef(isect_t); | ||||
| idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z)); | idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z)); | ||||
| #ifdef __KERNEL_AVX2__ | #ifdef __KERNEL_AVX2__ | ||||
| P_idir = P*idir; | P_idir = P*idir; | ||||
| Context not available. | |||||
| org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z)); | org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z)); | ||||
| #endif | #endif | ||||
| triangle_intersect_precalc(dir, &isect_precalc); | triangle_intersect_precalc(dir, &isect_precalc); | ||||
| isect_t = tmax; | |||||
| isect_array->t = isect_t; | |||||
| object = OBJECT_NONE; | object = OBJECT_NONE; | ||||
| nodeAddr = traversalStack[stackPtr].addr; | nodeAddr = traversalStack[stackPtr].addr; | ||||
| Context not available. | |||||
| #endif /* FEATURE(BVH_INSTANCING) */ | #endif /* FEATURE(BVH_INSTANCING) */ | ||||
| } while(nodeAddr != ENTRYPOINT_SENTINEL); | } while(nodeAddr != ENTRYPOINT_SENTINEL); | ||||
| return (isect->prim != PRIM_NONE); | return num_hits; | ||||
| } | } | ||||
| Context not available. | |||||