forked from bartvdbraak/blender
Cycles: Enable leaf split by primitive type and adopt BVH traversal for this
This commit enables BVH leaf nodes split by the primitive type and makes it so BVH traversal code is now aware and benefits from this. As was mentioned in original commit, this change is crucial to be able to do single ray to multiple triangle intersection. But it also appears to give barely visible speedup in some scene. In any case there should be no noticeable slowdown, and this change is what we need to have anyway.
This commit is contained in:
parent
c707b91ce6
commit
bc7ff3c2b4
@ -473,7 +473,7 @@ BVHNode *BVHBuild::create_primitive_leaf_node(const int *p_type,
|
||||
return new LeafNode(bounds, visibility, start, start + num);
|
||||
}
|
||||
|
||||
BVHNode* BVHBuild::create_leaf_node_split(const BVHRange& range)
|
||||
BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
|
||||
{
|
||||
#define MAX_LEAF_SIZE 8
|
||||
int p_num[PRIMITIVE_NUM_TOTAL] = {0};
|
||||
@ -564,68 +564,6 @@ BVHNode* BVHBuild::create_leaf_node_split(const BVHRange& range)
|
||||
#undef AMX_LEAF_SIZE
|
||||
}
|
||||
|
||||
BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
|
||||
{
|
||||
if(params.use_split_leaf_types) {
|
||||
/* Need to ensure leaf nodes has single primitive type only. */
|
||||
return create_leaf_node_split(range);
|
||||
}
|
||||
|
||||
vector<int>& p_type = prim_type;
|
||||
vector<int>& p_index = prim_index;
|
||||
vector<int>& p_object = prim_object;
|
||||
BoundBox bounds = BoundBox::empty;
|
||||
int num = 0, ob_num = 0;
|
||||
uint visibility = 0;
|
||||
|
||||
for(int i = 0; i < range.size(); i++) {
|
||||
BVHReference& ref = references[range.start() + i];
|
||||
|
||||
if(ref.prim_index() != -1) {
|
||||
if(range.start() + num == prim_index.size()) {
|
||||
assert(params.use_spatial_split);
|
||||
|
||||
p_type.push_back(ref.prim_type());
|
||||
p_index.push_back(ref.prim_index());
|
||||
p_object.push_back(ref.prim_object());
|
||||
}
|
||||
else {
|
||||
p_type[range.start() + num] = ref.prim_type();
|
||||
p_index[range.start() + num] = ref.prim_index();
|
||||
p_object[range.start() + num] = ref.prim_object();
|
||||
}
|
||||
|
||||
bounds.grow(ref.bounds());
|
||||
visibility |= objects[ref.prim_object()]->visibility;
|
||||
num++;
|
||||
}
|
||||
else {
|
||||
if(ob_num < i)
|
||||
references[range.start() + ob_num] = ref;
|
||||
ob_num++;
|
||||
}
|
||||
}
|
||||
|
||||
BVHNode *leaf = NULL;
|
||||
|
||||
if(num > 0) {
|
||||
leaf = new LeafNode(bounds, visibility, range.start(), range.start() + num);
|
||||
|
||||
if(num == range.size())
|
||||
return leaf;
|
||||
}
|
||||
|
||||
/* while there may be multiple triangles in a leaf, for object primitives
|
||||
* we want there to be the only one, so we keep splitting */
|
||||
const BVHReference *ref = (ob_num)? &references[range.start()]: NULL;
|
||||
BVHNode *oleaf = create_object_leaf_nodes(ref, range.start() + num, ob_num);
|
||||
|
||||
if(leaf)
|
||||
return new InnerNode(range.bounds(), leaf, oleaf);
|
||||
else
|
||||
return oleaf;
|
||||
}
|
||||
|
||||
/* Tree Rotations */
|
||||
|
||||
void BVHBuild::rotate(BVHNode *node, int max_depth, int iterations)
|
||||
|
@ -71,7 +71,6 @@ protected:
|
||||
BVHNode *create_object_leaf_nodes(const BVHReference *ref, int start, int num);
|
||||
|
||||
/* Leaf node type splitting. */
|
||||
BVHNode *create_leaf_node_split(const BVHRange& range);
|
||||
BVHNode *create_primitive_leaf_node(const int *p_type,
|
||||
const int *p_index,
|
||||
const int *p_object,
|
||||
|
@ -49,11 +49,6 @@ public:
|
||||
/* QBVH */
|
||||
int use_qbvh;
|
||||
|
||||
/* Split leaf nodes by primitive types,
|
||||
* leaving node containing primitives of single type only.
|
||||
*/
|
||||
int use_split_leaf_types;
|
||||
|
||||
/* fixed parameters */
|
||||
enum {
|
||||
MAX_DEPTH = 64,
|
||||
@ -78,7 +73,6 @@ public:
|
||||
top_level = false;
|
||||
use_cache = false;
|
||||
use_qbvh = false;
|
||||
use_split_leaf_types = false;
|
||||
}
|
||||
|
||||
/* SAH costs */
|
||||
|
@ -206,7 +206,9 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
|
||||
#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);
|
||||
const uint p_type = type & PRIMITIVE_ALL;
|
||||
|
||||
/* pop */
|
||||
nodeAddr = traversalStack[stackPtr];
|
||||
@ -215,13 +217,12 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
|
||||
/* primitive intersection */
|
||||
while(primAddr < primAddr2) {
|
||||
bool hit;
|
||||
uint type = kernel_tex_fetch(__prim_type, primAddr);
|
||||
|
||||
/* todo: specialized intersect functions which don't fill in
|
||||
* isect unless needed and check SD_HAS_TRANSPARENT_SHADOW?
|
||||
* might give a few % performance improvement */
|
||||
|
||||
switch(type & PRIMITIVE_ALL) {
|
||||
switch(p_type) {
|
||||
case PRIMITIVE_TRIANGLE: {
|
||||
hit = triangle_intersect(kg, &isect_precalc, isect_array, P, dir, PATH_RAY_SHADOW, object, primAddr);
|
||||
break;
|
||||
|
@ -193,37 +193,41 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
|
||||
#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 */
|
||||
for(; primAddr < primAddr2; primAddr++) {
|
||||
/* 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;
|
||||
|
||||
/* intersect ray against primitive */
|
||||
uint type = kernel_tex_fetch(__prim_type, primAddr);
|
||||
|
||||
switch(type & PRIMITIVE_ALL) {
|
||||
case PRIMITIVE_TRIANGLE: {
|
||||
switch(type & PRIMITIVE_ALL) {
|
||||
case PRIMITIVE_TRIANGLE: {
|
||||
/* intersect ray against primitive */
|
||||
for(; primAddr < primAddr2; primAddr++) {
|
||||
/* 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, &isect_precalc, isect_array, P, dir, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#if BVH_FEATURE(BVH_MOTION)
|
||||
case PRIMITIVE_MOTION_TRIANGLE: {
|
||||
case PRIMITIVE_MOTION_TRIANGLE: {
|
||||
/* intersect ray against primitive */
|
||||
for(; primAddr < primAddr2; primAddr++) {
|
||||
/* 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, isect_array, P, dir, ray->time, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -254,62 +254,82 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
|
||||
#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_precalc, isect, P, dir, visibility, object, primAddr);
|
||||
break;
|
||||
}
|
||||
#if BVH_FEATURE(BVH_MOTION)
|
||||
case PRIMITIVE_MOTION_TRIANGLE: {
|
||||
hit = motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr);
|
||||
break;
|
||||
}
|
||||
switch(type & PRIMITIVE_ALL) {
|
||||
case PRIMITIVE_TRIANGLE: {
|
||||
for(; primAddr < primAddr2; primAddr++) {
|
||||
#if defined(__KERNEL_DEBUG__)
|
||||
isect->num_traversal_steps++;
|
||||
#endif
|
||||
if(triangle_intersect(kg, &isect_precalc, isect, P, dir, 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;
|
||||
}
|
||||
#if BVH_FEATURE(BVH_MOTION)
|
||||
case PRIMITIVE_MOTION_TRIANGLE: {
|
||||
for(; primAddr < primAddr2; primAddr++) {
|
||||
#if defined(__KERNEL_DEBUG__)
|
||||
isect->num_traversal_steps++;
|
||||
#endif
|
||||
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: {
|
||||
if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
|
||||
case PRIMITIVE_CURVE:
|
||||
case PRIMITIVE_MOTION_CURVE: {
|
||||
for(; primAddr < primAddr2; primAddr++) {
|
||||
#if defined(__KERNEL_DEBUG__)
|
||||
isect->num_traversal_steps++;
|
||||
#endif
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__KERNEL_DEBUG__)
|
||||
isect->num_traversal_steps++;
|
||||
#endif
|
||||
|
||||
/* 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 BVH_FEATURE(BVH_INSTANCING)
|
||||
|
@ -194,49 +194,64 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
|
||||
#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 */
|
||||
for(; primAddr < primAddr2; primAddr++) {
|
||||
/* only primitives from volume object */
|
||||
uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
|
||||
int object_flag = kernel_tex_fetch(__object_flag, tri_object);
|
||||
|
||||
if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* intersect ray against primitive */
|
||||
uint type = kernel_tex_fetch(__prim_type, primAddr);
|
||||
|
||||
switch(type & PRIMITIVE_ALL) {
|
||||
case PRIMITIVE_TRIANGLE: {
|
||||
switch(type & PRIMITIVE_ALL) {
|
||||
case PRIMITIVE_TRIANGLE: {
|
||||
/* intersect ray against primitive */
|
||||
for(; primAddr < primAddr2; primAddr++) {
|
||||
/* only primitives from volume object */
|
||||
uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
|
||||
int object_flag = kernel_tex_fetch(__object_flag, tri_object);
|
||||
if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
|
||||
continue;
|
||||
}
|
||||
triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#if BVH_FEATURE(BVH_MOTION)
|
||||
case PRIMITIVE_MOTION_TRIANGLE: {
|
||||
case PRIMITIVE_MOTION_TRIANGLE: {
|
||||
/* intersect ray against primitive */
|
||||
for(; primAddr < primAddr2; primAddr++) {
|
||||
/* only primitives from volume object */
|
||||
uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
|
||||
int object_flag = kernel_tex_fetch(__object_flag, tri_object);
|
||||
if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
|
||||
continue;
|
||||
}
|
||||
motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if BVH_FEATURE(BVH_HAIR)
|
||||
case PRIMITIVE_CURVE:
|
||||
case PRIMITIVE_MOTION_CURVE: {
|
||||
if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
|
||||
case PRIMITIVE_CURVE:
|
||||
case PRIMITIVE_MOTION_CURVE: {
|
||||
/* intersect ray against primitive */
|
||||
for(; primAddr < primAddr2; primAddr++) {
|
||||
/* only primitives from volume object */
|
||||
uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
|
||||
int object_flag = kernel_tex_fetch(__object_flag, tri_object);
|
||||
if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
|
||||
continue;
|
||||
}
|
||||
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);
|
||||
else
|
||||
bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -216,6 +216,8 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
|
||||
if(primAddr >= 0) {
|
||||
#endif
|
||||
int primAddr2 = __float_as_int(leaf.y);
|
||||
const uint type = __float_as_int(leaf.w);
|
||||
const uint p_type = type & PRIMITIVE_ALL;
|
||||
|
||||
/* Pop. */
|
||||
nodeAddr = traversalStack[stackPtr].addr;
|
||||
@ -224,13 +226,12 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
|
||||
/* Primitive intersection. */
|
||||
while(primAddr < primAddr2) {
|
||||
bool hit;
|
||||
uint type = kernel_tex_fetch(__prim_type, primAddr);
|
||||
|
||||
/* todo: specialized intersect functions which don't fill in
|
||||
* isect unless needed and check SD_HAS_TRANSPARENT_SHADOW?
|
||||
* might give a few % performance improvement */
|
||||
|
||||
switch(type & PRIMITIVE_ALL) {
|
||||
switch(p_type) {
|
||||
case PRIMITIVE_TRIANGLE: {
|
||||
hit = triangle_intersect(kg, &isect_precalc, isect_array, P, dir, PATH_RAY_SHADOW, object, primAddr);
|
||||
break;
|
||||
|
@ -203,37 +203,42 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
|
||||
if(primAddr >= 0) {
|
||||
#endif
|
||||
int primAddr2 = __float_as_int(leaf.y);
|
||||
const uint type = __float_as_int(leaf.w);
|
||||
|
||||
/* Pop. */
|
||||
nodeAddr = traversalStack[stackPtr].addr;
|
||||
--stackPtr;
|
||||
|
||||
/* Primitive intersection. */
|
||||
for(; primAddr < primAddr2; primAddr++) {
|
||||
/* 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;
|
||||
|
||||
/* Intersect ray against primitive */
|
||||
uint type = kernel_tex_fetch(__prim_type, primAddr);
|
||||
|
||||
switch(type & PRIMITIVE_ALL) {
|
||||
case PRIMITIVE_TRIANGLE: {
|
||||
switch(type & PRIMITIVE_ALL) {
|
||||
case PRIMITIVE_TRIANGLE: {
|
||||
/* Intersect ray against primitive, */
|
||||
for(; primAddr < primAddr2; primAddr++) {
|
||||
/* 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, &isect_precalc, isect_array, P, dir, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
|
||||
break;
|
||||
}
|
||||
#if BVH_FEATURE(BVH_MOTION)
|
||||
case PRIMITIVE_MOTION_TRIANGLE: {
|
||||
motion_triangle_intersect_subsurface(kg, isect_array, P, dir, ray->time, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#if BVH_FEATURE(BVH_MOTION)
|
||||
case PRIMITIVE_MOTION_TRIANGLE: {
|
||||
/* Intersect ray against primitive. */
|
||||
for(; primAddr < primAddr2; primAddr++) {
|
||||
/* 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, isect_array, P, dir, ray->time, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if BVH_FEATURE(BVH_INSTANCING)
|
||||
|
@ -275,6 +275,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
|
||||
if(primAddr >= 0) {
|
||||
#endif
|
||||
int primAddr2 = __float_as_int(leaf.y);
|
||||
const uint type = __float_as_int(leaf.w);
|
||||
|
||||
/* Pop. */
|
||||
nodeAddr = traversalStack[stackPtr].addr;
|
||||
@ -282,49 +283,59 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
|
||||
--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_precalc, isect, P, dir, visibility, object, primAddr);
|
||||
break;
|
||||
}
|
||||
#if BVH_FEATURE(BVH_MOTION)
|
||||
case PRIMITIVE_MOTION_TRIANGLE: {
|
||||
hit = motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr);
|
||||
break;
|
||||
}
|
||||
switch(type & PRIMITIVE_ALL) {
|
||||
case PRIMITIVE_TRIANGLE: {
|
||||
#if defined(__KERNEL_DEBUG__)
|
||||
isect->num_traversal_steps++;
|
||||
#endif
|
||||
for(; primAddr < primAddr2; primAddr++) {
|
||||
if(triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr)) {
|
||||
tfar = ssef(isect->t);
|
||||
/* Shadow ray early termination. */
|
||||
if(visibility == PATH_RAY_SHADOW_OPAQUE)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#if BVH_FEATURE(BVH_MOTION)
|
||||
case PRIMITIVE_MOTION_TRIANGLE: {
|
||||
for(; primAddr < primAddr2; primAddr++) {
|
||||
#if defined(__KERNEL_DEBUG__)
|
||||
isect->num_traversal_steps++;
|
||||
#endif
|
||||
if(motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr)) {
|
||||
tfar = ssef(isect->t);
|
||||
/* Shadow ray early termination. */
|
||||
if(visibility == PATH_RAY_SHADOW_OPAQUE)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /* BVH_FEATURE(BVH_MOTION) */
|
||||
#if BVH_FEATURE(BVH_HAIR)
|
||||
case PRIMITIVE_CURVE:
|
||||
case PRIMITIVE_MOTION_CURVE: {
|
||||
if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
|
||||
case PRIMITIVE_CURVE:
|
||||
case PRIMITIVE_MOTION_CURVE: {
|
||||
for(; primAddr < primAddr2; primAddr++) {
|
||||
#if defined(__KERNEL_DEBUG__)
|
||||
isect->num_traversal_steps++;
|
||||
#endif
|
||||
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;
|
||||
if(hit) {
|
||||
tfar = ssef(isect->t);
|
||||
/* Shadow ray early termination. */
|
||||
if(visibility == PATH_RAY_SHADOW_OPAQUE)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(__KERNEL_DEBUG__)
|
||||
isect->num_traversal_steps++;
|
||||
#endif
|
||||
|
||||
/* Shadow ray early termination. */
|
||||
if(hit) {
|
||||
tfar = ssef(isect->t);
|
||||
if(visibility == PATH_RAY_SHADOW_OPAQUE)
|
||||
return true;
|
||||
}
|
||||
|
||||
primAddr++;
|
||||
#endif /* BVH_FEATURE(BVH_HAIR) */
|
||||
}
|
||||
}
|
||||
#if BVH_FEATURE(BVH_INSTANCING)
|
||||
|
@ -209,49 +209,62 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
|
||||
if(primAddr >= 0) {
|
||||
#endif
|
||||
int primAddr2 = __float_as_int(leaf.y);
|
||||
const uint type = __float_as_int(leaf.w);
|
||||
const uint p_type = type & PRIMITIVE_ALL;
|
||||
|
||||
/* Pop. */
|
||||
nodeAddr = traversalStack[stackPtr].addr;
|
||||
--stackPtr;
|
||||
|
||||
/* Primitive intersection. */
|
||||
for(; primAddr < primAddr2; primAddr++) {
|
||||
/* Only primitives from volume object. */
|
||||
uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
|
||||
int object_flag = kernel_tex_fetch(__object_flag, tri_object);
|
||||
|
||||
if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Intersect ray against primitive. */
|
||||
uint type = kernel_tex_fetch(__prim_type, primAddr);
|
||||
|
||||
switch(type & PRIMITIVE_ALL) {
|
||||
case PRIMITIVE_TRIANGLE: {
|
||||
switch(p_type) {
|
||||
case PRIMITIVE_TRIANGLE: {
|
||||
for(; primAddr < primAddr2; primAddr++) {
|
||||
/* Only primitives from volume object. */
|
||||
uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
|
||||
int object_flag = kernel_tex_fetch(__object_flag, tri_object);
|
||||
if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
|
||||
continue;
|
||||
}
|
||||
/* Intersect ray against primitive. */
|
||||
triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#if BVH_FEATURE(BVH_MOTION)
|
||||
case PRIMITIVE_MOTION_TRIANGLE: {
|
||||
case PRIMITIVE_MOTION_TRIANGLE: {
|
||||
for(; primAddr < primAddr2; primAddr++) {
|
||||
/* Only primitives from volume object. */
|
||||
uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
|
||||
int object_flag = kernel_tex_fetch(__object_flag, tri_object);
|
||||
if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
|
||||
continue;
|
||||
}
|
||||
/* Intersect ray against primitive. */
|
||||
motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if BVH_FEATURE(BVH_HAIR)
|
||||
case PRIMITIVE_CURVE:
|
||||
case PRIMITIVE_MOTION_CURVE: {
|
||||
if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
|
||||
case PRIMITIVE_CURVE:
|
||||
case PRIMITIVE_MOTION_CURVE: {
|
||||
for(; primAddr < primAddr2; primAddr++) {
|
||||
/* Only primitives from volume object. */
|
||||
uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
|
||||
int object_flag = kernel_tex_fetch(__object_flag, tri_object);
|
||||
if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
|
||||
continue;
|
||||
}
|
||||
/* Intersect ray against primitive. */
|
||||
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);
|
||||
else
|
||||
bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#if BVH_FEATURE(BVH_INSTANCING)
|
||||
|
Loading…
Reference in New Issue
Block a user