Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/kernel/geom/geom_bvh_subsurface.h
| Show All 19 Lines | |||||
| #ifdef __QBVH__ | #ifdef __QBVH__ | ||||
| #include "geom_qbvh_subsurface.h" | #include "geom_qbvh_subsurface.h" | ||||
| #endif | #endif | ||||
| /* This is a template BVH traversal function for subsurface scattering, where | /* This is a template BVH traversal function for subsurface scattering, where | ||||
| * various features can be enabled/disabled. This way we can compile optimized | * various features can be enabled/disabled. This way we can compile optimized | ||||
| * versions for each case without new features slowing things down. | * versions for each case without new features slowing things down. | ||||
| * | * | ||||
| * BVH_INSTANCING: object instancing | |||||
| * BVH_MOTION: motion blur rendering | * BVH_MOTION: motion blur rendering | ||||
| * | * | ||||
| */ | */ | ||||
| ccl_device void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, | ccl_device void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, | ||||
| const Ray *ray, | const Ray *ray, | ||||
| SubsurfaceIntersection *ss_isect, | SubsurfaceIntersection *ss_isect, | ||||
| int subsurface_object, | int subsurface_object, | ||||
| uint *lcg_state, | uint *lcg_state, | ||||
| int max_hits) | int max_hits) | ||||
| { | { | ||||
| /* todo: | /* todo: | ||||
| * - test if pushing distance on the stack helps (for non shadow rays) | * - test if pushing distance on the stack helps (for non shadow rays) | ||||
| * - separate version for shadow rays | * - separate version for shadow rays | ||||
| * - likely and unlikely for if() statements | * - likely and unlikely for if() statements | ||||
| * - SSE for hair | |||||
| * - test restrict attribute for pointers | * - test restrict attribute for pointers | ||||
| */ | */ | ||||
| /* traversal stack in CUDA thread-local memory */ | /* traversal stack in CUDA thread-local memory */ | ||||
| int traversalStack[BVH_STACK_SIZE]; | int traversalStack[BVH_STACK_SIZE]; | ||||
| traversalStack[0] = ENTRYPOINT_SENTINEL; | traversalStack[0] = ENTRYPOINT_SENTINEL; | ||||
| /* traversal variables in registers */ | /* traversal variables in registers */ | ||||
| int stackPtr = 0; | int stackPtr = 0; | ||||
| int nodeAddr = kernel_data.bvh.root; | int nodeAddr = kernel_tex_fetch(__object_node, subsurface_object); | ||||
| /* ray parameters in registers */ | /* ray parameters in registers */ | ||||
| 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 = ray->t; | float isect_t = ray->t; | ||||
| ss_isect->num_hits = 0; | ss_isect->num_hits = 0; | ||||
| const int object_flag = kernel_tex_fetch(__object_flag, subsurface_object); | |||||
| if(!(object_flag & SD_TRANSFORM_APPLIED)) { | |||||
| #if BVH_FEATURE(BVH_MOTION) | #if BVH_FEATURE(BVH_MOTION) | ||||
| Transform ob_itfm; | Transform ob_itfm; | ||||
| bvh_instance_motion_push(kg, | |||||
| subsurface_object, | |||||
| ray, | |||||
| &P, | |||||
| &dir, | |||||
| &idir, | |||||
| &isect_t, | |||||
| &ob_itfm); | |||||
| #else | |||||
| bvh_instance_push(kg, subsurface_object, ray, &P, &dir, &idir, &isect_t); | |||||
brecht: These push calls don't seem to have a corresponding pop? | |||||
sergeyAuthorUnsubmitted Not Done Inline ActionsWell, that's the subsurface intersection discussion we had before strikes back. Intersections are in the object space, so you don't need to adjust intersection distance there. And since we're always within a single instance, we don't need to pop anything during traversal and we don't care of pre-calculations state after we've done with traversal. sergey: Well, that's the subsurface intersection discussion we had before strikes back. Intersections… | |||||
brechtUnsubmitted Not Done Inline ActionsOh right, it's coming back to me now. brecht: Oh right, it's coming back to me now. | |||||
| #endif | #endif | ||||
| object = subsurface_object; | |||||
| } | |||||
| #if defined(__KERNEL_SSE2__) | #if defined(__KERNEL_SSE2__) | ||||
| const shuffle_swap_t shuf_identity = shuffle_swap_identity(); | const shuffle_swap_t shuf_identity = shuffle_swap_identity(); | ||||
| const shuffle_swap_t shuf_swap = shuffle_swap_swap(); | const shuffle_swap_t shuf_swap = shuffle_swap_swap(); | ||||
| const ssef pn = cast(ssei(0, 0, 0x80000000, 0x80000000)); | const ssef pn = cast(ssei(0, 0, 0x80000000, 0x80000000)); | ||||
| ssef Psplat[3], idirsplat[3]; | ssef Psplat[3], idirsplat[3]; | ||||
| shuffle_swap_t shufflexyz[3]; | shuffle_swap_t shufflexyz[3]; | ||||
| Psplat[0] = ssef(P.x); | Psplat[0] = ssef(P.x); | ||||
| Psplat[1] = ssef(P.y); | Psplat[1] = ssef(P.y); | ||||
| Psplat[2] = ssef(P.z); | Psplat[2] = ssef(P.z); | ||||
| ▲ Show 20 Lines • Show All 104 Lines • ▼ Show 20 Lines | #endif | ||||
| } | } | ||||
| } | } | ||||
| /* if node is leaf, fetch triangle list */ | /* if node is leaf, fetch triangle list */ | ||||
| if(nodeAddr < 0) { | if(nodeAddr < 0) { | ||||
| float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_NODE_LEAF_SIZE); | float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_NODE_LEAF_SIZE); | ||||
| int primAddr = __float_as_int(leaf.x); | int primAddr = __float_as_int(leaf.x); | ||||
| #if BVH_FEATURE(BVH_INSTANCING) | |||||
| if(primAddr >= 0) { | |||||
| #endif | |||||
| const int primAddr2 = __float_as_int(leaf.y); | const int primAddr2 = __float_as_int(leaf.y); | ||||
| const uint type = __float_as_int(leaf.w); | const uint type = __float_as_int(leaf.w); | ||||
| /* pop */ | /* pop */ | ||||
| nodeAddr = traversalStack[stackPtr]; | nodeAddr = traversalStack[stackPtr]; | ||||
| --stackPtr; | --stackPtr; | ||||
| /* primitive intersection */ | /* primitive intersection */ | ||||
| switch(type & PRIMITIVE_ALL) { | switch(type & PRIMITIVE_ALL) { | ||||
| case PRIMITIVE_TRIANGLE: { | case PRIMITIVE_TRIANGLE: { | ||||
| /* intersect ray against primitive */ | /* intersect ray against primitive */ | ||||
| for(; primAddr < primAddr2; primAddr++) { | for(; primAddr < primAddr2; primAddr++) { | ||||
| kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); | kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); | ||||
| /* only primitives from the same object */ | |||||
| uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object; | |||||
| if(tri_object != subsurface_object) | |||||
| continue; | |||||
| triangle_intersect_subsurface(kg, | triangle_intersect_subsurface(kg, | ||||
| &isect_precalc, | &isect_precalc, | ||||
| ss_isect, | ss_isect, | ||||
| P, | P, | ||||
| object, | object, | ||||
| primAddr, | primAddr, | ||||
| isect_t, | isect_t, | ||||
| lcg_state, | lcg_state, | ||||
| max_hits); | max_hits); | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| #if BVH_FEATURE(BVH_MOTION) | #if BVH_FEATURE(BVH_MOTION) | ||||
| case PRIMITIVE_MOTION_TRIANGLE: { | case PRIMITIVE_MOTION_TRIANGLE: { | ||||
| /* intersect ray against primitive */ | /* intersect ray against primitive */ | ||||
| for(; primAddr < primAddr2; primAddr++) { | for(; primAddr < primAddr2; primAddr++) { | ||||
| kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); | kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); | ||||
| /* only primitives from the same object */ | |||||
| uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object; | |||||
| if(tri_object != subsurface_object) | |||||
| continue; | |||||
| motion_triangle_intersect_subsurface(kg, | motion_triangle_intersect_subsurface(kg, | ||||
| ss_isect, | ss_isect, | ||||
| P, | P, | ||||
| dir, | dir, | ||||
| ray->time, | ray->time, | ||||
| object, | object, | ||||
| primAddr, | primAddr, | ||||
| isect_t, | isect_t, | ||||
| lcg_state, | lcg_state, | ||||
| max_hits); | max_hits); | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| #endif | #endif | ||||
| default: { | default: { | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| #if BVH_FEATURE(BVH_INSTANCING) | |||||
| else { | |||||
| /* instance push */ | |||||
| if(subsurface_object == kernel_tex_fetch(__prim_object, -primAddr-1)) { | |||||
| object = subsurface_object; | |||||
| #if BVH_FEATURE(BVH_MOTION) | |||||
| bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_itfm); | |||||
| #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); | |||||
| Psplat[1] = ssef(P.y); | |||||
| Psplat[2] = ssef(P.z); | |||||
| tsplat = ssef(0.0f, 0.0f, -isect_t, -isect_t); | |||||
| gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); | |||||
| #endif | |||||
| ++stackPtr; | |||||
| kernel_assert(stackPtr < BVH_STACK_SIZE); | |||||
| traversalStack[stackPtr] = ENTRYPOINT_SENTINEL; | |||||
| nodeAddr = kernel_tex_fetch(__object_node, object); | |||||
| } | |||||
| else { | |||||
| /* pop */ | |||||
| nodeAddr = traversalStack[stackPtr]; | |||||
| --stackPtr; | |||||
| } | |||||
| } | |||||
| } | |||||
| #endif /* FEATURE(BVH_INSTANCING) */ | |||||
| } while(nodeAddr != ENTRYPOINT_SENTINEL); | } while(nodeAddr != ENTRYPOINT_SENTINEL); | ||||
| #if BVH_FEATURE(BVH_INSTANCING) | |||||
| if(stackPtr >= 0) { | |||||
| kernel_assert(object != OBJECT_NONE); | |||||
| /* instance pop */ | |||||
| #if BVH_FEATURE(BVH_MOTION) | |||||
| bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_itfm); | |||||
| #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); | |||||
| Psplat[1] = ssef(P.y); | |||||
| Psplat[2] = ssef(P.z); | |||||
| tsplat = ssef(0.0f, 0.0f, -isect_t, -isect_t); | |||||
| gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); | |||||
| #endif | |||||
| object = OBJECT_NONE; | |||||
| nodeAddr = traversalStack[stackPtr]; | |||||
| --stackPtr; | |||||
| } | |||||
| #endif /* FEATURE(BVH_INSTANCING) */ | |||||
| } while(nodeAddr != ENTRYPOINT_SENTINEL); | } while(nodeAddr != ENTRYPOINT_SENTINEL); | ||||
| } | } | ||||
| ccl_device_inline void BVH_FUNCTION_NAME(KernelGlobals *kg, | ccl_device_inline void BVH_FUNCTION_NAME(KernelGlobals *kg, | ||||
| const Ray *ray, | const Ray *ray, | ||||
| SubsurfaceIntersection *ss_isect, | SubsurfaceIntersection *ss_isect, | ||||
| int subsurface_object, | int subsurface_object, | ||||
| uint *lcg_state, | uint *lcg_state, | ||||
| Show All 26 Lines | |||||
These push calls don't seem to have a corresponding pop?