Compare commits

...
11 changed files with 468 additions and 138 deletions
Executable → Regular
View File
+2 -2
View File
@@ -136,8 +136,8 @@ namespace embree
Precalculations pre(ray,bvh);
/*! stack state */
NodeRef stack[stackSize]; //!< stack of nodes that still need to get traversed
NodeRef* stackPtr = stack+1; //!< current stack pointer
NodeRef stack[stackSize]; //!< stack of nodes that still need to get traversed
NodeRef* stackPtr = stack+1; //!< current stack pointer
NodeRef* stackEnd = stack+stackSize;
stack[0] = bvh->root;
+188 -53
View File
@@ -34,9 +34,11 @@
#define SWITCH_DURING_DOWN_TRAVERSAL 1
#define FORCE_SINGLE_MODE 0
#define ENABLE_FAST_COHERENT_CODEPATHS 1
#define STREAM_IN_HYBRID 0
namespace embree
{
namespace isa
@@ -147,7 +149,6 @@ namespace embree
size_t valid_bits = movemask(valid);
if (unlikely(valid_bits == 0)) return;
/* verify correct input */
assert(all(valid,ray.valid()));
assert(all(valid,ray.tnear >= 0.0f));
@@ -179,12 +180,9 @@ namespace embree
/* determine switch threshold based on flags */
const size_t switchThreshold = (context->user && isCoherent(context->user->flags)) ? 2 : switchThresholdIncoherent;
vint<K> octant =
select(vfloat<K>(rdir.x) < 0.0f,vint<K>(1),vint<K>(zero)) |
select(vfloat<K>(rdir.y) < 0.0f,vint<K>(2),vint<K>(zero)) |
select(vfloat<K>(rdir.z) < 0.0f,vint<K>(4),vint<K>(zero));
octant = select(valid,octant,vint<K>(0xffffffff));
vint<K> octant = ray.octant();
octant = select(valid, octant, vint<K>(0xffffffff));
do
{
const size_t valid_index = __bsf(valid_bits);
@@ -266,7 +264,7 @@ namespace embree
const NodeRef child = node->children[i];
if (unlikely(child == BVH::emptyNode)) break;
vfloat<K> lnearP;
vbool<K> lhit(valid_node);
vbool<K> lhit = valid_node;
BVHNNodeIntersectorK<N,K,types,robust>::intersect(nodeRef,i,org,ray_dir,rdir,org_rdir,ray_tnear,ray_tfar,ray.time,lnearP,lhit);
/* if we hit the child we choose to continue with that child if it
@@ -455,7 +453,7 @@ namespace embree
do {
const size_t i = __bscf(m_frusta_node);
vfloat<K> lnearP;
vbool<K> lhit( false );
vbool<K> lhit = false; // motion blur is not supported, so the initial value will be ignored
STAT3(normal.trav_nodes,1,1,1);
BVHNNodeIntersectorK<N,K,types,robust>::intersect(nodeRef,i,org,ray_dir,rdir,org_rdir,ray_tnear,ray_tfar,ray.time,lnearP,lhit);
@@ -500,7 +498,6 @@ namespace embree
std::swap(stackPtr[-3],stackPtr[-2]);
}
}
}
/* intersect leaf */
@@ -620,7 +617,7 @@ namespace embree
#endif
/* return if there are no valid rays */
const size_t valid_bits = movemask(valid);
size_t valid_bits = movemask(valid);
if (unlikely(valid_bits == 0)) return;
/* verify correct input */
@@ -638,6 +635,154 @@ namespace embree
const Vec3vf<K> org(ray_org), org_rdir = org * rdir;
ray_tnear = select(valid,ray_tnear,vfloat<K>(pos_inf));
ray_tfar = select(valid,ray_tfar ,vfloat<K>(neg_inf));
#if STREAM_IN_HYBRID == 1
Vec3vi<K> nearXYZ;
nearXYZ.x = select(rdir.x >= 0.0f,vint<K>(0*(int)sizeof(vfloat<N>)),vint<K>(1*(int)sizeof(vfloat<N>)));
nearXYZ.y = select(rdir.y >= 0.0f,vint<K>(2*(int)sizeof(vfloat<N>)),vint<K>(3*(int)sizeof(vfloat<N>)));
nearXYZ.z = select(rdir.z >= 0.0f,vint<K>(4*(int)sizeof(vfloat<N>)),vint<K>(5*(int)sizeof(vfloat<N>)));
const int shiftTable[8] = { (int)1 << 0, (int)1 << 1, (int)1 << 2, (int)1 << 3, (int)1 << 4, (int)1 << 5, (int)1 << 6, (int)1 << 7 };
{
/*! stack state */
StackItemT<NodeRef> stack[stackSizeSingle]; //!< stack of nodes
StackItemT<NodeRef>* stackPtr = stack + 1; //!< current stack pointer
//StackItemT<NodeRef>* stackEnd = stack + stackSizeSingle;
stack[0].ptr = bvh->root;
stack[0].dist = movemask(valid);
while (1) pop:
{
if (unlikely(stackPtr == stack)) break;
STAT3(shadow.trav_stack_pop,1,1,1);
stackPtr--;
NodeRef cur = NodeRef(stackPtr->ptr);
size_t cur_mask = stackPtr->dist & movemask(!terminated);
if (unlikely(cur_mask == 0)) continue;
while (true)
{
/*! stop if we found a leaf node */
if (unlikely(cur.isLeaf())) break;
const AlignedNode* __restrict__ const node = cur.alignedNode();
const vfloat<Nx> bminX = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x));
const vfloat<Nx> bmaxX = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->upper_x));
const vfloat<Nx> bminY = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_y));
const vfloat<Nx> bmaxY = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->upper_y));
const vfloat<Nx> bminZ = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_z));
const vfloat<Nx> bmaxZ = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->upper_z));
size_t bits = cur_mask;
#if defined(__AVX__)
STAT3(shadow.trav_hit_boxes[__popcnt(cur_mask)],1,1,1);
#endif
assert(bits);
const vbool<Nx> valid_children = bminX <= bmaxX;
vint<Nx> vmask(zero);
do
{
STAT3(shadow.trav_nodes,1,1,1);
const size_t i = __bscf(bits);
assert(i < K);
//const vint<Nx> bitmask = vint<Nx>((int)1 << i);
const vint<Nx> bitmask(shiftTable[i]);
const vfloat<Nx> tNearX = msub(bminX, rdir.x[i], org_rdir.x[i]);
const vfloat<Nx> tNearY = msub(bminY, rdir.y[i], org_rdir.y[i]);
const vfloat<Nx> tNearZ = msub(bminZ, rdir.z[i], org_rdir.z[i]);
const vfloat<Nx> tFarX = msub(bmaxX, rdir.x[i], org_rdir.x[i]);
const vfloat<Nx> tFarY = msub(bmaxY, rdir.y[i], org_rdir.y[i]);
const vfloat<Nx> tFarZ = msub(bmaxZ, rdir.z[i], org_rdir.z[i]);
const vfloat<Nx> tNear = maxi(mini(tNearX,tFarX), mini(tNearY,tFarY), mini(tNearZ,tFarZ), vfloat<Nx>(ray_tnear[i]));
const vfloat<Nx> tFar = mini(maxi(tNearX,tFarX), maxi(tNearY,tFarY), maxi(tNearZ,tFarZ), vfloat<Nx>(ray_tfar[i]));
const vbool<Nx> hit_mask = tNear <= tFar;
#if defined(__AVX2__)
vmask = vmask | (bitmask & vint<Nx>(hit_mask));
#else
vmask = select(hit_mask, vmask | bitmask, vmask);
#endif
} while(bits);
size_t mask = movemask( (vmask != vint<Nx>(zero)) & valid_children);
if (unlikely(mask == 0)) goto pop;
/* select next child and push other children */
//const BaseNode* node = cur.baseNode(types);
/*! one child is hit, continue with that child */
size_t r = __bscf(mask);
assert(r < N);
cur = node->child(r);
cur.prefetch(types);
cur_mask = vmask[r];
/* simple in order sequence */
assert(cur != BVH::emptyNode);
if (likely(mask == 0)) continue;
stackPtr->ptr = cur;
stackPtr->dist = cur_mask;
stackPtr++;
for (; ;)
{
r = __bscf(mask);
assert(r < N);
cur = node->child(r);
cur.prefetch(types);
cur_mask = vmask[r];
assert(cur != BVH::emptyNode);
if (likely(mask == 0)) break;
stackPtr->ptr = cur;
stackPtr->dist = cur_mask;
stackPtr++;
}
}
/*! this is a leaf node */
assert(cur != BVH::emptyNode);
STAT3(shadow.trav_leaves,1,1,1);
size_t num; Primitive* prim = (Primitive*) cur.leaf(num);
size_t bits = cur_mask;
size_t lazy_node = 0;
for (; bits!=0; )
{
const size_t k = __bscf(bits);
if (PrimitiveIntersectorK::occluded(pre,ray,k,context,prim,num,lazy_node)) {
ray.geomID[k] = 0;
set(terminated, k);
}
/* lazy node */
if (unlikely(lazy_node)) {
stackPtr->ptr = lazy_node;
stackPtr->dist = cur_mask;
stackPtr++;
}
}
if (all(terminated)) break;
}
}
// while(valid_bits);
#else
const vfloat<K> inf = vfloat<K>(pos_inf);
/* compute near/far per ray */
@@ -716,33 +861,23 @@ namespace embree
const NodeRef child = node->children[i];
if (unlikely(child == BVH::emptyNode)) break;
vfloat<K> lnearP;
vbool<K> lhit(valid_node);
vbool<K> lhit = valid_node;
BVHNNodeIntersectorK<N,K,types,robust>::intersect(nodeRef,i,org,ray_dir,rdir,org_rdir,ray_tnear,ray_tfar,ray.time,lnearP,lhit);
/* if we hit the child we choose to continue with that child if it
is closer than the current next child, or we push it onto the stack */
/* if we hit the child we push the previously hit node onto the stack, and continue with the currently hit child */
if (likely(any(lhit)))
{
assert(sptr_node < stackEnd);
assert(child != BVH::emptyNode);
const vfloat<K> childDist = select(lhit,lnearP,inf);
/* push cur node onto stack and continue with hit child */
if (any(childDist < curDist))
{
if (likely(cur != BVH::emptyNode)) {
*sptr_node = cur; sptr_node++;
*sptr_near = curDist; sptr_near++;
}
curDist = childDist;
cur = child;
}
/* push hit child onto stack */
else {
*sptr_node = child; sptr_node++;
*sptr_near = childDist; sptr_near++;
/* push 'cur' node onto stack and continue with hit child */
if (likely(cur != BVH::emptyNode)) {
*sptr_node = cur; sptr_node++;
*sptr_near = curDist; sptr_near++;
}
curDist = childDist;
cur = child;
}
}
if (unlikely(cur == BVH::emptyNode))
@@ -777,15 +912,20 @@ namespace embree
size_t items; const Primitive* prim = (Primitive*) cur.leaf(items);
size_t lazy_node = 0;
#if defined(__AVX__)
STAT3(shadow.trav_hit_boxes[popcnt(vbool<K>(!terminated))],1,1,1);
#endif
terminated |= PrimitiveIntersectorK::occluded(!terminated,pre,ray,context,prim,items,lazy_node);
if (all(terminated)) break;
ray_tfar = select(terminated,vfloat<K>(neg_inf),ray_tfar);
ray_tfar = select(terminated, vfloat<K>(neg_inf), ray_tfar); // ignore node intersections for terminated rays
if (unlikely(lazy_node)) {
*sptr_node = lazy_node; sptr_node++;
*sptr_near = neg_inf; sptr_near++;
}
}
#endif
vint<K>::store(valid & terminated,&ray.geomID,0);
AVX_ZERO_UPPER();
}
@@ -810,7 +950,7 @@ namespace embree
/* verify correct input */
assert(all(valid,ray.valid()));
assert(all(valid,ray.tnear >= 0.0f));
assert(!(types & BVH_MB) || all(valid,(ray.time >= 0.0f) & (ray.time <= 1.0f)));
assert(!(types & BVH_MB) || all(valid, (ray.time >= 0.0f) & (ray.time <= 1.0f)));
Precalculations pre(valid,ray);
/* load ray */
@@ -823,27 +963,24 @@ namespace embree
const Vec3vf<K> org(ray_org);
const Vec3vf<K> org_rdir = org * rdir;
vint<K> octant = \
select(vfloat<K>(rdir.x) < 0.0f,vint<K>(1),vint<K>(zero)) |
select(vfloat<K>(rdir.y) < 0.0f,vint<K>(2),vint<K>(zero)) |
select(vfloat<K>(rdir.z) < 0.0f,vint<K>(4),vint<K>(zero));
octant = select(valid,octant,vint<K>(0xffffffff));
vint<K> octant = ray.octant();
octant = select(valid, octant, vint<K>(0xffffffff));
do
{
const size_t valid_index = __bsf(valid_bits);
vbool<K> octant_valid = octant[valid_index] == octant;
valid_bits &= ~(size_t)movemask(octant_valid);
const vfloat<K> ray_tnear = select(octant_valid,org_ray_tnear,vfloat<K>(pos_inf));
const vfloat<K> ray_tfar = select(octant_valid,org_ray_tfar ,vfloat<K>(neg_inf));
const vfloat<K> ray_tnear = select(octant_valid, org_ray_tnear, vfloat<K>(pos_inf));
vfloat<K> ray_tfar = select(octant_valid, org_ray_tfar, vfloat<K>(neg_inf));
const Frustum<N,Nx,K,robust> frustum(octant_valid,org,rdir,ray_tnear,ray_tfar);
const Frustum<N,Nx,K,robust> frustum(octant_valid, org, rdir, ray_tnear, ray_tfar);
StackItemT<NodeRef> stack[stackSizeSingle]; //!< stack of nodes
StackItemT<NodeRef>* stackPtr = stack + 1; //!< current stack pointer
stack[0].ptr = bvh->root;
stack[0].dist = (unsigned int)movemask(octant_valid);
StackItemMaskT<NodeRef> stack[stackSizeSingle]; //!< stack of nodes
StackItemMaskT<NodeRef>* stackPtr = stack + 1; //!< current stack pointer
stack[0].ptr = bvh->root;
stack[0].mask = (unsigned int)movemask(octant_valid);
while (1) pop:
{
@@ -854,7 +991,7 @@ namespace embree
NodeRef cur = NodeRef(stackPtr->ptr);
/* cull node of active rays have already been terminated */
unsigned int m_active = stackPtr->dist & (~movemask(terminated));
unsigned int m_active = stackPtr->mask & (~movemask(terminated));
if (unlikely(m_active == 0)) continue;
@@ -879,7 +1016,7 @@ namespace embree
do {
const size_t i = __bscf(m_frusta_node);
vfloat<K> lnearP;
vbool<K> lhit( false );
vbool<K> lhit = false; // motion blur is not supported, so the initial value will be ignored
STAT3(normal.trav_nodes,1,1,1);
BVHNNodeIntersectorK<N,K,types,robust>::intersect(nodeRef,i,org,ray_dir,rdir,org_rdir,ray_tnear,ray_tfar,ray.time,lnearP,lhit);
@@ -891,7 +1028,7 @@ namespace embree
if (likely(cur != BVH::emptyNode)) {
num_child_hits++;
stackPtr->ptr = cur;
stackPtr->dist = m_active;
stackPtr->mask = m_active;
stackPtr++;
}
cur = child;
@@ -915,20 +1052,18 @@ namespace embree
terminated |= PrimitiveIntersectorK::occluded(!terminated,pre,ray,context,prim,items,lazy_node);
octant_valid &= !terminated;
if (unlikely(none(octant_valid))) break;
ray_tfar = select(terminated, vfloat<K>(neg_inf), ray_tfar); // ignore node intersections for terminated rays
if (unlikely(lazy_node)) {
stackPtr->ptr = lazy_node;
stackPtr->dist = (unsigned int)movemask(octant_valid);
stackPtr->mask = (unsigned int)movemask(octant_valid);
stackPtr++;
}
}
} while(valid_bits);
vint<K>::store(valid & terminated,&ray.geomID,0);
vint<K>::store(valid & terminated, &ray.geomID, 0);
AVX_ZERO_UPPER();
}
}
}
+74 -69
View File
@@ -23,9 +23,9 @@ namespace embree
namespace isa
{
template<int N, int Nx>
struct TravRay
struct TravRay
{
__forceinline TravRay () {}
__forceinline TravRay() {}
__forceinline TravRay(const Vec3fa& ray_org, const Vec3fa& ray_dir)
: org_xyz(ray_org), dir_xyz(ray_dir)
@@ -56,8 +56,8 @@ namespace embree
}
template<int K>
__forceinline TravRay (size_t k, const Vec3vf<K> &ray_org, const Vec3vf<K> &ray_dir,
const Vec3vf<K> &ray_rdir, const Vec3vi<K>& nearXYZ, const size_t flip = sizeof(vfloat<N>))
__forceinline TravRay(size_t k, const Vec3vf<K> &ray_org, const Vec3vf<K> &ray_dir,
const Vec3vf<K> &ray_rdir, const Vec3vi<K>& nearXYZ, const size_t flip = sizeof(vfloat<N>))
{
org = Vec3vf<Nx>(ray_org.x[k], ray_org.y[k], ray_org.z[k]);
dir = Vec3vf<Nx>(ray_dir.x[k], ray_dir.y[k], ray_dir.z[k]);
@@ -82,7 +82,7 @@ namespace embree
#endif
}
__forceinline TravRay (const TravRay& ray)
__forceinline TravRay(const TravRay& ray)
{
org_xyz = ray.org_xyz;
dir_xyz = ray.dir_xyz;
@@ -127,12 +127,12 @@ namespace embree
//////////////////////////////////////////////////////////////////////////////////////
template<int N, int Nx>
__forceinline size_t intersectNode(const typename BVHN<N>::AlignedNode* node, const TravRay<N,Nx>& ray,
const vfloat<Nx>& tnear, const vfloat<Nx>& tfar, vfloat<Nx>& dist);
__forceinline size_t intersectNode(const typename BVHN<N>::AlignedNode* node, const TravRay<N,Nx>& ray,
const vfloat<Nx>& tnear, const vfloat<Nx>& tfar, vfloat<Nx>& dist);
template<>
__forceinline size_t intersectNode<4,4>(const typename BVH4::AlignedNode* node, const TravRay<4,4>& ray,
const vfloat4& tnear, const vfloat4& tfar, vfloat4& dist)
__forceinline size_t intersectNode<4,4>(const typename BVH4::AlignedNode* node, const TravRay<4,4>& ray,
const vfloat4& tnear, const vfloat4& tfar, vfloat4& dist)
{
#if defined(__AVX2__)
const vfloat4 tNearX = msub(vfloat4::load((float*)((const char*)&node->lower_x+ray.nearX)), ray.rdir.x, ray.org_rdir.x);
@@ -173,8 +173,8 @@ namespace embree
#if defined(__AVX__)
template<>
__forceinline size_t intersectNode<8,8>(const typename BVH8::AlignedNode* node, const TravRay<8,8>& ray,
const vfloat8& tnear, const vfloat8& tfar, vfloat8& dist)
__forceinline size_t intersectNode<8,8>(const typename BVH8::AlignedNode* node, const TravRay<8,8>& ray,
const vfloat8& tnear, const vfloat8& tfar, vfloat8& dist)
{
#if defined(__AVX2__)
const vfloat8 tNearX = msub(vfloat8::load((float*)((const char*)&node->lower_x+ray.nearX)), ray.rdir.x, ray.org_rdir.x);
@@ -217,7 +217,7 @@ namespace embree
#if defined(__AVX512F__) && !defined(__AVX512VL__) // KNL
template<>
__forceinline size_t intersectNode<4,16>(const typename BVH4::AlignedNode* node, const TravRay<4,16>& ray, const vfloat16& tnear, const vfloat16& tfar, vfloat16& dist)
__forceinline size_t intersectNode<4,16>(const typename BVH4::AlignedNode* node, const TravRay<4,16>& ray, const vfloat16& tnear, const vfloat16& tfar, vfloat16& dist)
{
const vfloat16 tNearX = msub(vfloat16(*(vfloat4*)((const char*)&node->lower_x+ray.nearX)), ray.rdir.x, ray.org_rdir.x);
const vfloat16 tNearY = msub(vfloat16(*(vfloat4*)((const char*)&node->lower_x+ray.nearY)), ray.rdir.y, ray.org_rdir.y);
@@ -234,7 +234,7 @@ namespace embree
}
template<>
__forceinline size_t intersectNode<8,16>(const typename BVH8::AlignedNode* node, const TravRay<8,16>& ray, const vfloat16& tnear, const vfloat16& tfar, vfloat16& dist)
__forceinline size_t intersectNode<8,16>(const typename BVH8::AlignedNode* node, const TravRay<8,16>& ray, const vfloat16& tnear, const vfloat16& tfar, vfloat16& dist)
{
const vllong8 invalid((size_t)BVH8::emptyNode);
const vboold8 m_valid(invalid != vllong8::loadu(node->children));
@@ -255,10 +255,10 @@ namespace embree
#endif
template<int N, int K>
__forceinline vbool<K> intersectNode(const typename BVHN<N>::AlignedNode* node, size_t i,
const Vec3vf<K>& org, const Vec3vf<K>& dir, const Vec3vf<K>& rdir, const Vec3vf<K>& org_rdir,
const vfloat<K>& tnear, const vfloat<K>& tfar, vfloat<K>& dist)
__forceinline vbool<K> intersectNode(const typename BVHN<N>::AlignedNode* node, size_t i,
const Vec3vf<K>& org, const Vec3vf<K>& dir, const Vec3vf<K>& rdir, const Vec3vf<K>& org_rdir,
const vfloat<K>& tnear, const vfloat<K>& tfar, vfloat<K>& dist)
{
#if defined(__AVX2__)
const vfloat<K> lclipMinX = msub(node->lower_x[i],rdir.x,org_rdir.x);
@@ -306,8 +306,8 @@ namespace embree
//////////////////////////////////////////////////////////////////////////////////////
template<int N,int Nx>
__forceinline size_t intersectNodeRobust(const typename BVHN<N>::AlignedNode* node, const TravRay<N,Nx>& ray,
const vfloat<Nx>& tnear, const vfloat<Nx>& tfar, vfloat<Nx>& dist)
__forceinline size_t intersectNodeRobust(const typename BVHN<N>::AlignedNode* node, const TravRay<N,Nx>& ray,
const vfloat<Nx>& tnear, const vfloat<Nx>& tfar, vfloat<Nx>& dist)
{
const vfloat<N> tNearX = (vfloat<N>::load((float*)((const char*)&node->lower_x+ray.nearX)) - ray.org.x) * ray.rdir.x;
const vfloat<N> tNearY = (vfloat<N>::load((float*)((const char*)&node->lower_x+ray.nearY)) - ray.org.y) * ray.rdir.y;
@@ -328,8 +328,8 @@ namespace embree
#if defined(__AVX512F__) && !defined(__AVX512VL__) // KNL
template<>
__forceinline size_t intersectNodeRobust<4,16>(const typename BVHN<4>::AlignedNode* node, const TravRay<4,16>& ray,
const vfloat<16>& tnear, const vfloat<16>& tfar, vfloat<16>& dist)
__forceinline size_t intersectNodeRobust<4,16>(const typename BVHN<4>::AlignedNode* node, const TravRay<4,16>& ray,
const vfloat<16>& tnear, const vfloat<16>& tfar, vfloat<16>& dist)
{
const vfloat16 tNearX = (vfloat16(*(vfloat<4>*)((const char*)&node->lower_x+ray.nearX)) - ray.org.x) * ray.rdir.x;
const vfloat16 tNearY = (vfloat16(*(vfloat<4>*)((const char*)&node->lower_x+ray.nearY)) - ray.org.y) * ray.rdir.y;
@@ -348,8 +348,8 @@ namespace embree
}
template<>
__forceinline size_t intersectNodeRobust<8,16>(const typename BVHN<8>::AlignedNode* node, const TravRay<8,16>& ray,
const vfloat<16>& tnear, const vfloat<16>& tfar, vfloat<16>& dist)
__forceinline size_t intersectNodeRobust<8,16>(const typename BVHN<8>::AlignedNode* node, const TravRay<8,16>& ray,
const vfloat<16>& tnear, const vfloat<16>& tfar, vfloat<16>& dist)
{
const vfloat16 tNearX = (vfloat16(*(vfloat<8>*)((const char*)&node->lower_x+ray.nearX)) - ray.org.x) * ray.rdir.x;
const vfloat16 tNearY = (vfloat16(*(vfloat<8>*)((const char*)&node->lower_x+ray.nearY)) - ray.org.y) * ray.rdir.y;
@@ -370,9 +370,9 @@ namespace embree
#endif
template<int N, int K>
__forceinline vbool<K> intersectNodeRobust(const typename BVHN<N>::AlignedNode* node, size_t i,
const Vec3vf<K>& org, const Vec3vf<K>& dir, const Vec3vf<K>& rdir, const Vec3vf<K>& org_rdir,
const vfloat<K>& tnear, const vfloat<K>& tfar, vfloat<K>& dist)
__forceinline vbool<K> intersectNodeRobust(const typename BVHN<N>::AlignedNode* node, size_t i,
const Vec3vf<K>& org, const Vec3vf<K>& dir, const Vec3vf<K>& rdir, const Vec3vf<K>& org_rdir,
const vfloat<K>& tnear, const vfloat<K>& tfar, vfloat<K>& dist)
{
// FIXME: use per instruction rounding for AVX512
const vfloat<K> lclipMinX = (node->lower_x[i] - org.x) * rdir.x;
@@ -395,7 +395,7 @@ namespace embree
//////////////////////////////////////////////////////////////////////////////////////
template<int N>
__forceinline size_t intersectNode(const typename BVHN<N>::AlignedNodeMB* node, const TravRay<N,N>& ray, const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist)
__forceinline size_t intersectNode(const typename BVHN<N>::AlignedNodeMB* node, const TravRay<N,N>& ray, const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist)
{
const vfloat<N>* pNearX = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearX);
const vfloat<N>* pNearY = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearY);
@@ -496,7 +496,7 @@ namespace embree
//////////////////////////////////////////////////////////////////////////////////////
template<int N>
__forceinline size_t intersectNodeRobust(const typename BVHN<N>::AlignedNodeMB* node, const TravRay<N,N>& ray, const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist)
__forceinline size_t intersectNodeRobust(const typename BVHN<N>::AlignedNodeMB* node, const TravRay<N,N>& ray, const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist)
{
const vfloat<N>* pNearX = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearX);
const vfloat<N>* pNearY = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearY);
@@ -566,8 +566,8 @@ namespace embree
//////////////////////////////////////////////////////////////////////////////////////
template<int N>
__forceinline size_t intersectNodeMB4D(const typename BVHN<N>::NodeRef ref, const TravRay<N,N>& ray,
const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist)
__forceinline size_t intersectNodeMB4D(const typename BVHN<N>::NodeRef ref, const TravRay<N,N>& ray,
const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist)
{
const typename BVHN<N>::AlignedNodeMB* node = ref.alignedNodeMB();
@@ -655,8 +655,8 @@ namespace embree
//////////////////////////////////////////////////////////////////////////////////////
template<int N>
__forceinline size_t intersectNodeMB4DRobust(const typename BVHN<N>::NodeRef ref, const TravRay<N,N>& ray,
const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist)
__forceinline size_t intersectNodeMB4DRobust(const typename BVHN<N>::NodeRef ref, const TravRay<N,N>& ray,
const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist)
{
const typename BVHN<N>::AlignedNodeMB* node = ref.alignedNodeMB();
@@ -687,9 +687,9 @@ namespace embree
}
template<int N, int K>
__forceinline vbool<K> intersectNodeMB4DRobust(const typename BVHN<N>::NodeRef ref, const size_t i,
const Vec3vf<K>& org, const Vec3vf<K>& dir, const Vec3vf<K>& rdir, const Vec3vf<K>& org_rdir,
const vfloat<K>& tnear, const vfloat<K>& tfar, const vfloat<K>& time, vfloat<K>& dist)
__forceinline vbool<K> intersectNodeMB4DRobust(const typename BVHN<N>::NodeRef ref, const size_t i,
const Vec3vf<K>& org, const Vec3vf<K>& dir, const Vec3vf<K>& rdir, const Vec3vf<K>& org_rdir,
const vfloat<K>& tnear, const vfloat<K>& tfar, const vfloat<K>& time, vfloat<K>& dist)
{
const typename BVHN<N>::AlignedNodeMB* node = ref.alignedNodeMB();
@@ -726,10 +726,10 @@ namespace embree
//////////////////////////////////////////////////////////////////////////////////////
template<int N, int Nx>
__forceinline size_t intersectNode(const typename BVHN<N>::QuantizedNode* node, const TravRay<N,Nx>& ray, const vfloat<Nx>& tnear, const vfloat<Nx>& tfar, vfloat<Nx>& dist);
__forceinline size_t intersectNode(const typename BVHN<N>::QuantizedNode* node, const TravRay<N,Nx>& ray, const vfloat<Nx>& tnear, const vfloat<Nx>& tfar, vfloat<Nx>& dist);
template<>
__forceinline size_t intersectNode<4,4>(const typename BVH4::QuantizedNode* node, const TravRay<4,4>& ray, const vfloat4& tnear, const vfloat4& tfar, vfloat4& dist)
__forceinline size_t intersectNode<4,4>(const typename BVH4::QuantizedNode* node, const TravRay<4,4>& ray, const vfloat4& tnear, const vfloat4& tfar, vfloat4& dist)
{
const vfloat4 start_x(node->start.x);
const vfloat4 scale_x(node->scale.x);
@@ -783,7 +783,7 @@ namespace embree
#if defined(__AVX__)
template<>
__forceinline size_t intersectNode<8,8>(const typename BVH8::QuantizedNode* node, const TravRay<8,8>& ray, const vfloat8& tnear, const vfloat8& tfar, vfloat8& dist)
__forceinline size_t intersectNode<8,8>(const typename BVH8::QuantizedNode* node, const TravRay<8,8>& ray, const vfloat8& tnear, const vfloat8& tfar, vfloat8& dist)
{
const vfloat8 start_x(node->start.x);
const vfloat8 scale_x(node->scale.x);
@@ -839,7 +839,7 @@ namespace embree
#if defined(__AVX512F__) && !defined(__AVX512VL__) // KNL
template<>
__forceinline size_t intersectNode<4,16>(const typename BVH4::QuantizedNode* node, const TravRay<4,16>& ray, const vfloat16& tnear, const vfloat16& tfar, vfloat16& dist)
__forceinline size_t intersectNode<4,16>(const typename BVH4::QuantizedNode* node, const TravRay<4,16>& ray, const vfloat16& tnear, const vfloat16& tfar, vfloat16& dist)
{
const vfloat16 start_x(node->start.x);
const vfloat16 scale_x(node->scale.x);
@@ -869,7 +869,7 @@ namespace embree
}
template<>
__forceinline size_t intersectNode<8,16>(const typename BVH8::QuantizedNode* node, const TravRay<8,16>& ray, const vfloat16& tnear, const vfloat16& tfar, vfloat16& dist)
__forceinline size_t intersectNode<8,16>(const typename BVH8::QuantizedNode* node, const TravRay<8,16>& ray, const vfloat16& tnear, const vfloat16& tfar, vfloat16& dist)
{
const vllong8 invalid((size_t)BVH8::emptyNode);
const vboold8 m_valid(invalid != vllong8::loadu(node->children));
@@ -894,8 +894,8 @@ namespace embree
//////////////////////////////////////////////////////////////////////////////////////
template<int N>
__forceinline size_t intersectNode(const typename BVHN<N>::UnalignedNode* node, const TravRay<N,N>& ray,
const vfloat<N>& tnear, const vfloat<N>& tfar, vfloat<N>& dist)
__forceinline size_t intersectNode(const typename BVHN<N>::UnalignedNode* node, const TravRay<N,N>& ray,
const vfloat<N>& tnear, const vfloat<N>& tfar, vfloat<N>& dist)
{
const Vec3vf<N> dir = xfmVector(node->naabb,ray.dir);
//const Vec3vf<N> nrdir = Vec3vf<N>(vfloat<N>(-1.0f))/dir;
@@ -918,9 +918,9 @@ namespace embree
}
template<int N, int K>
__forceinline vbool<K> intersectNode(const typename BVHN<N>::UnalignedNode* node, const size_t i,
const Vec3vf<K>& org_i, const Vec3vf<K>& dir_i, const Vec3vf<K>& rdir_i, const Vec3vf<K>& org_rdir_i,
const vfloat<K>& tnear, const vfloat<K>& tfar, vfloat<K>& dist)
__forceinline vbool<K> intersectNode(const typename BVHN<N>::UnalignedNode* node, const size_t i,
const Vec3vf<K>& org_i, const Vec3vf<K>& dir_i, const Vec3vf<K>& rdir_i, const Vec3vf<K>& org_rdir_i,
const vfloat<K>& tnear, const vfloat<K>& tfar, vfloat<K>& dist)
{
const AffineSpace3vf<K> naabb(Vec3f(node->naabb.l.vx.x[i],node->naabb.l.vx.y[i],node->naabb.l.vx.z[i]),
Vec3f(node->naabb.l.vy.x[i],node->naabb.l.vy.y[i],node->naabb.l.vy.z[i]),
@@ -950,8 +950,8 @@ namespace embree
//////////////////////////////////////////////////////////////////////////////////////
template<int N>
__forceinline size_t intersectNode(const typename BVHN<N>::UnalignedNodeMB* node, const TravRay<N,N>& ray,
const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist)
__forceinline size_t intersectNode(const typename BVHN<N>::UnalignedNodeMB* node, const TravRay<N,N>& ray,
const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist)
{
const AffineSpace3vf<N> xfm = node->space0;
const Vec3vf<N> b0_lower = zero;
@@ -981,9 +981,9 @@ namespace embree
}
template<int N, int K>
__forceinline vbool<K> intersectNode(const typename BVHN<N>::UnalignedNodeMB* node, const size_t i,
const Vec3vf<K>& org_i, const Vec3vf<K>& dir_i, const Vec3vf<K>& rdir_i, const Vec3vf<K>& org_rdir_i,
const vfloat<K>& tnear, const vfloat<K>& tfar, const vfloat<K>& time, vfloat<K>& dist)
__forceinline vbool<K> intersectNode(const typename BVHN<N>::UnalignedNodeMB* node, const size_t i,
const Vec3vf<K>& org_i, const Vec3vf<K>& dir_i, const Vec3vf<K>& rdir_i, const Vec3vf<K>& org_rdir_i,
const vfloat<K>& tnear, const vfloat<K>& tfar, const vfloat<K>& time, vfloat<K>& dist)
{
const AffineSpace3vf<K> xfm(Vec3f(node->space0.l.vx.x[i],node->space0.l.vx.y[i],node->space0.l.vx.z[i]),
Vec3f(node->space0.l.vy.x[i],node->space0.l.vy.y[i],node->space0.l.vy.z[i]),
@@ -1024,7 +1024,7 @@ namespace embree
struct BVHNNodeIntersector1;
template<int N, int Nx>
struct BVHNNodeIntersector1<N,Nx,BVH_AN1,false>
struct BVHNNodeIntersector1<N,Nx,BVH_AN1,false>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx>& ray, const vfloat<Nx>& tnear, const vfloat<Nx>& tfar, const float time, vfloat<Nx>& dist, size_t& mask)
{
@@ -1035,7 +1035,7 @@ namespace embree
};
template<int N, int Nx>
struct BVHNNodeIntersector1<N,Nx,BVH_AN1,true>
struct BVHNNodeIntersector1<N,Nx,BVH_AN1,true>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx>& ray, const vfloat<Nx>& tnear, const vfloat<Nx>& tfar, const float time, vfloat<Nx>& dist, size_t& mask)
{
@@ -1046,7 +1046,7 @@ namespace embree
};
template<int N, int Nx>
struct BVHNNodeIntersector1<N,Nx,BVH_AN2,false>
struct BVHNNodeIntersector1<N,Nx,BVH_AN2,false>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx>& ray, const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist, size_t& mask)
{
@@ -1057,7 +1057,7 @@ namespace embree
};
template<int N, int Nx>
struct BVHNNodeIntersector1<N,Nx,BVH_AN2,true>
struct BVHNNodeIntersector1<N,Nx,BVH_AN2,true>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx>& ray, const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist, size_t& mask)
{
@@ -1068,7 +1068,7 @@ namespace embree
};
template<int N, int Nx>
struct BVHNNodeIntersector1<N,Nx,BVH_AN2_AN4D,false>
struct BVHNNodeIntersector1<N,Nx,BVH_AN2_AN4D,false>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx>& ray, const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist, size_t& mask)
{
@@ -1079,7 +1079,7 @@ namespace embree
};
template<int N, int Nx>
struct BVHNNodeIntersector1<N,Nx,BVH_AN2_AN4D,true>
struct BVHNNodeIntersector1<N,Nx,BVH_AN2_AN4D,true>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx>& ray, const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist, size_t& mask)
{
@@ -1090,7 +1090,7 @@ namespace embree
};
template<int N, int Nx>
struct BVHNNodeIntersector1<N,Nx,BVH_AN1_UN1,false>
struct BVHNNodeIntersector1<N,Nx,BVH_AN1_UN1,false>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx>& ray, const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist, size_t& mask)
{
@@ -1102,7 +1102,7 @@ namespace embree
};
template<int N, int Nx>
struct BVHNNodeIntersector1<N,Nx,BVH_AN2_UN2,false>
struct BVHNNodeIntersector1<N,Nx,BVH_AN2_UN2,false>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx>& ray, const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist, size_t& mask)
{
@@ -1114,7 +1114,7 @@ namespace embree
};
template<int N, int Nx>
struct BVHNNodeIntersector1<N,Nx,BVH_AN2_AN4D_UN2,false>
struct BVHNNodeIntersector1<N,Nx,BVH_AN2_AN4D_UN2,false>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx>& ray, const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist, size_t& mask)
{
@@ -1126,7 +1126,7 @@ namespace embree
};
template<int N, int Nx>
struct BVHNNodeIntersector1<N,Nx,BVH_TN_AN1,false>
struct BVHNNodeIntersector1<N,Nx,BVH_TN_AN1,false>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx>& ray, const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist, size_t& mask)
{
@@ -1137,7 +1137,7 @@ namespace embree
};
template<int N, int Nx>
struct BVHNNodeIntersector1<N,Nx,BVH_TN_AN1_AN2,false>
struct BVHNNodeIntersector1<N,Nx,BVH_TN_AN1_AN2,false>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx>& ray, const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist, size_t& mask)
{
@@ -1149,7 +1149,7 @@ namespace embree
};
template<int N, int Nx>
struct BVHNNodeIntersector1<N,Nx,BVH_QN1,false>
struct BVHNNodeIntersector1<N,Nx,BVH_QN1,false>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx>& ray, const vfloat<Nx>& tnear, const vfloat<Nx>& tfar, const float time, vfloat<Nx>& dist, size_t& mask)
{
@@ -1160,7 +1160,7 @@ namespace embree
};
template<int N, int Nx>
struct BVHNNodeIntersector1<N,Nx,BVH_QN1,true>
struct BVHNNodeIntersector1<N,Nx,BVH_QN1,true>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx>& ray, const vfloat<Nx>& tnear, const vfloat<Nx>& tfar, const float time, vfloat<Nx>& dist, size_t& mask)
{
@@ -1177,6 +1177,10 @@ namespace embree
template<int N, int K>
struct BVHNNodeIntersectorK<N,K,BVH_AN1,false>
{
/* vmask is both an input and an output parameter! Its initial value should be the parent node
hit mask, which is used for correctly computing the current hit mask. The parent hit mask
is actually required only for motion blur node intersections (because different rays may
have different times), so for regular nodes vmask is simply overwritten. */
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const size_t i, const Vec3vf<K>& org, const Vec3vf<K>& dir, const Vec3vf<K>& rdir, const Vec3vf<K>& org_rdir,
const vfloat<K>& tnear, const vfloat<K>& tfar, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
{
@@ -1186,7 +1190,7 @@ namespace embree
};
template<int N, int K>
struct BVHNNodeIntersectorK<N,K,BVH_AN1,true>
struct BVHNNodeIntersectorK<N,K,BVH_AN1,true>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const size_t i, const Vec3vf<K>& org, const Vec3vf<K>& dir, const Vec3vf<K>& rdir, const Vec3vf<K>& org_rdir,
const vfloat<K>& tnear, const vfloat<K>& tfar, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
@@ -1219,7 +1223,7 @@ namespace embree
};
template<int N, int K>
struct BVHNNodeIntersectorK<N,K,BVH_AN1_UN1,false>
struct BVHNNodeIntersectorK<N,K,BVH_AN1_UN1,false>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const size_t i,
const Vec3vf<K>& org, const Vec3vf<K>& dir, const Vec3vf<K>& rdir, const Vec3vf<K>& org_rdir,
@@ -1232,7 +1236,7 @@ namespace embree
};
template<int N, int K>
struct BVHNNodeIntersectorK<N,K,BVH_AN2_UN2,false>
struct BVHNNodeIntersectorK<N,K,BVH_AN2_UN2,false>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const size_t i,
const Vec3vf<K>& org, const Vec3vf<K>& dir, const Vec3vf<K>& rdir, const Vec3vf<K>& org_rdir,
@@ -1275,10 +1279,11 @@ namespace embree
const Vec3vf<K>& org, const Vec3vf<K>& dir, const Vec3vf<K>& rdir, const Vec3vf<K>& org_rdir,
const vfloat<K>& tnear, const vfloat<K>& tfar, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
{
if (likely(node.isAlignedNodeMB() || node.isAlignedNodeMB4D()))
if (likely(node.isAlignedNodeMB() || node.isAlignedNodeMB4D())) {
vmask &= intersectNodeMB4D<N,K>(node,i,org,dir,rdir,org_rdir,tnear,tfar,time,dist);
else /*if (unlikely(node.isUnalignedNodeMB()))*/ {
assert(node.isUnalignedNodeMB()); vmask &= intersectNode<N,K>(node.unalignedNodeMB(),i,org,dir,rdir,org_rdir,tnear,tfar,time,dist);
} else /*if (unlikely(node.isUnalignedNodeMB()))*/ {
assert(node.isUnalignedNodeMB());
vmask &= intersectNode<N,K>(node.unalignedNodeMB(),i,org,dir,rdir,org_rdir,tnear,tfar,time,dist);
}
return true;
}
+166 -2
View File
@@ -153,16 +153,180 @@ namespace embree
RayK<K>** inputPackets, size_t numOctantRays, IntersectContext* context)
{
BVH* __restrict__ bvh = (BVH*) This->ptr;
__aligned(64) StackItemMaskCoherent stack[stackSizeSingle]; //!< stack of nodes
assert(numOctantRays <= MAX_INTERNAL_STREAM_SIZE);
/* inactive rays should have been filtered out before */
#if 1
__aligned(64) Packet<K,false> packet[MAX_INTERNAL_STREAM_SIZE/K];
assert(numOctantRays <= 32);
const size_t numPackets = (numOctantRays+K-1)/K;
size_t m_active = 0;
for (size_t i = 0; i < numPackets; i++)
{
const vfloat<K> tnear = inputPackets[i]->tnear;
const vfloat<K> tfar = inputPackets[i]->tfar;
vbool<K> m_valid = (tnear <= tfar) & (tnear >= 0.0f);
m_active |= (size_t)movemask(m_valid) << (K*i);
const Vec3vf<K>& org = inputPackets[i]->org;
const Vec3vf<K>& dir = inputPackets[i]->dir;
vfloat<K> packet_min_dist = max(tnear, 0.0f);
vfloat<K> packet_max_dist = select(m_valid, tfar, neg_inf);
new (&packet[i]) Packet<K,false>(org,dir,packet_min_dist,packet_max_dist);
}
const int shiftTable[32] = {
(int)1 << 0, (int)1 << 1, (int)1 << 2, (int)1 << 3, (int)1 << 4, (int)1 << 5, (int)1 << 6, (int)1 << 7,
(int)1 << 8, (int)1 << 9, (int)1 << 10, (int)1 << 11, (int)1 << 12, (int)1 << 13, (int)1 << 14, (int)1 << 15,
(int)1 << 16, (int)1 << 17, (int)1 << 18, (int)1 << 19, (int)1 << 20, (int)1 << 21, (int)1 << 22, (int)1 << 23,
(int)1 << 24, (int)1 << 25, (int)1 << 26, (int)1 << 27, (int)1 << 28, (int)1 << 29, (int)1 << 30, (int)1 << 31
};
StackItemT<NodeRef> stack[stackSizeSingle]; //!< stack of nodes
StackItemT<NodeRef>* stackPtr = stack + 1; //!< current stack pointer
stack[0].ptr = bvh->root;
stack[0].dist = m_active;
size_t terminated = ~m_active;
while (1) pop:
{
if (unlikely(stackPtr == stack)) break;
STAT3(shadow.trav_stack_pop,1,1,1);
stackPtr--;
NodeRef cur = NodeRef(stackPtr->ptr);
size_t cur_mask = (size_t)stackPtr->dist & (~terminated);
if (unlikely(cur_mask == 0)) continue;
while (true)
{
/*! stop if we found a leaf node */
if (unlikely(cur.isLeaf())) break;
const AlignedNode* __restrict__ const node = cur.alignedNode();
const vfloat<Nx> bminX = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x));
const vfloat<Nx> bmaxX = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->upper_x));
const vfloat<Nx> bminY = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_y));
const vfloat<Nx> bmaxY = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->upper_y));
const vfloat<Nx> bminZ = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_z));
const vfloat<Nx> bmaxZ = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->upper_z));
size_t bits = cur_mask;
#if defined(__AVX__)
//STAT3(shadow.trav_hit_boxes[__popcnt(cur_mask)],1,1,1);
#endif
assert(bits);
vint<Nx> vmask(zero);
do
{
STAT3(shadow.trav_nodes,1,1,1);
const size_t rayID = __bscf(bits);
assert(rayID < MAX_INTERNAL_STREAM_SIZE);
assert(rayID /K < numPackets);
Packet<K,false> &p = packet[rayID /K];
const size_t i = rayID % K;
const vint<Nx> bitmask(shiftTable[rayID]);
const vfloat<Nx> tNearX = msub(bminX, p.rdir.x[i], p.org_rdir.x[i]);
const vfloat<Nx> tNearY = msub(bminY, p.rdir.y[i], p.org_rdir.y[i]);
const vfloat<Nx> tNearZ = msub(bminZ, p.rdir.z[i], p.org_rdir.z[i]);
const vfloat<Nx> tFarX = msub(bmaxX, p.rdir.x[i], p.org_rdir.x[i]);
const vfloat<Nx> tFarY = msub(bmaxY, p.rdir.y[i], p.org_rdir.y[i]);
const vfloat<Nx> tFarZ = msub(bmaxZ, p.rdir.z[i], p.org_rdir.z[i]);
const vfloat<Nx> tNear = maxi(mini(tNearX,tFarX), mini(tNearY,tFarY), mini(tNearZ,tFarZ), vfloat<Nx>(p.min_dist[i]));
const vfloat<Nx> tFar = mini(maxi(tNearX,tFarX), maxi(tNearY,tFarY), maxi(tNearZ,tFarZ), vfloat<Nx>(p.max_dist[i]));
const vbool<Nx> hit_mask = tNear <= tFar;
#if defined(__AVX2__)
vmask = vmask | (bitmask & vint<Nx>(hit_mask));
#else
vmask = select(hit_mask, vmask | bitmask, vmask);
#endif
} while(bits);
const vbool<Nx> valid_children = bminX <= bmaxX;
size_t mask = movemask( (vmask != vint<Nx>(zero)) & valid_children);
if (unlikely(mask == 0)) goto pop;
__aligned(64) unsigned int child_mask[Nx];
vint<Nx>::storeu(child_mask,vmask); // this explicit store here causes much better code generation
/* select next child and push other children */
//const BaseNode* node = cur.baseNode(types);
/*! one child is hit, continue with that child */
size_t r = __bscf(mask);
assert(r < N);
cur = node->child(r);
cur.prefetch(types);
cur_mask = child_mask[r];
/* simple in order sequence */
assert(cur != BVH::emptyNode);
if (likely(mask == 0)) continue;
stackPtr->ptr = cur;
stackPtr->dist = cur_mask;
stackPtr++;
for (; ;)
{
r = __bscf(mask);
assert(r < N);
cur = node->child(r);
cur.prefetch(types);
cur_mask = child_mask[r];
assert(cur != BVH::emptyNode);
if (likely(mask == 0)) break;
stackPtr->ptr = cur;
stackPtr->dist = cur_mask;
stackPtr++;
}
}
/*! this is a leaf node */
assert(cur != BVH::emptyNode);
STAT3(shadow.trav_leaves,1,1,1);
size_t num; Primitive* prim = (Primitive*) cur.leaf(num);
size_t bits = cur_mask;
size_t lazy_node = 0;
for (; bits!=0; )
{
const size_t rayID = __bscf(bits);
RayK<K> &ray = *inputPackets[rayID / K];
const size_t k = rayID % K;
if (PrimitiveIntersector::occluded(ray,k,context,prim,num,lazy_node)) {
ray.geomID[k] = 0;
terminated |= (size_t)1 << rayID;
}
/* lazy node */
if (unlikely(lazy_node)) {
stackPtr->ptr = lazy_node;
stackPtr->dist = cur_mask;
stackPtr++;
}
}
if (unlikely(terminated == (size_t)-1)) { break; }
}
#else
__aligned(64) Packet<K,robust> packet[MAX_INTERNAL_STREAM_SIZE/K];
__aligned(64) StackItemMaskCoherent stack[stackSizeSingle]; //!< stack of nodes
__aligned(64) Frustum<N,Nx,K,robust> frusta;
bool commonOctant = true;
size_t m_active = initPacketsAndFrusta<true>(inputPackets, numOctantRays, packet, frusta, commonOctant);
/* valid rays */
if (unlikely(m_active == 0)) return;
@@ -250,8 +414,8 @@ namespace embree
inputPackets[i]->geomID = select(m_hit & m_valid, vint<K>(zero), inputPackets[i]->geomID);
m_active &= ~((size_t)movemask(m_hit) << (i*K));
}
} // traversal + intersection
#endif
}
////////////////////////////////////////////////////////////////////////////////
+15 -6
View File
@@ -17,6 +17,8 @@
#include "bvh_intersector_stream_filters.h"
#include "bvh_intersector_stream.h"
#define FORCE_STREAM_OCCLUSION_KERNEL 1
namespace embree
{
namespace isa
@@ -28,7 +30,11 @@ namespace embree
RayStreamAOS rayN(_rayN);
/* use fast path for coherent ray mode */
if (unlikely(isCoherent(context->user->flags)))
#if FORCE_STREAM_OCCLUSION_KERNEL == 1
if (1)
#else
if (unlikely(isCoherent(context->user->flags)))
#endif
{
__aligned(64) RayK<VSIZEX> rays[MAX_PACKET_STREAM_SIZE];
__aligned(64) RayK<VSIZEX>* rayPtrs[MAX_PACKET_STREAM_SIZE];
@@ -72,23 +78,26 @@ namespace embree
}
else
{
/* fallback to packets */
static const size_t MAX_RAYS_PER_OCTANT = VSIZEX;
/* fallback to packets */
for (size_t i=0; i<N; i+=VSIZEX)
{
const vintx vi = vintx(int(i)) + vintx(step);
vboolx valid = vi < vintx(int(N));
const vintx offset = vi * int(stride);
RayK<VSIZEX> ray = rayN.getRayByOffset(valid, offset);
valid &= ray.tnear <= ray.tfar;
if (intersect)
scene->intersectors.intersect(valid, ray, context);
else
else
scene->intersectors.occluded(valid, ray, context);
rayN.setHitByOffset(valid, offset, ray, intersect);
}
}
}
+1 -2
View File
@@ -20,7 +20,7 @@
namespace embree
{
#if defined(__X86_64__)
#if defined(__X86_64__) && 0
static const size_t MAX_INTERNAL_STREAM_SIZE = 64;
#else
static const size_t MAX_INTERNAL_STREAM_SIZE = 32;
@@ -974,7 +974,6 @@ namespace embree
__forceinline Ray8 RayStreamAOS::getRayByOffset(const vint8& offset)
{
Ray8 ray;
/* gather: instID */
ray.instID = vint8::gather<1>((int*)&ptr->instID, offset);
+10 -2
View File
@@ -22,7 +22,7 @@ namespace embree
{
/*! An item on the stack holds the node ID and distance of that node. */
template<typename T>
struct __aligned(16) StackItemT
struct __aligned(16) StackItemT
{
/*! assert that the xchg function works */
static_assert(sizeof(T) <= 12, "sizeof(T) <= 12 failed");
@@ -79,7 +79,15 @@ namespace embree
}
public:
T ptr;
T ptr;
unsigned dist;
};
/*! An item on the stack holds the node ID and active ray mask. */
template<typename T>
struct __aligned(16) StackItemMaskT
{
T ptr;
unsigned mask;
};
}
+10
View File
@@ -124,6 +124,16 @@ namespace embree
return !valid0;
}
static __forceinline bool occluded(RayK<K>& ray, size_t k, IntersectContext* context, const PrimitiveK* prim, size_t num, size_t& lazy_node)
{
PrecalculationsK pre(vbool<K>(true),ray); // FIXME: might cause trouble
for (size_t i=0; i<num; i++) {
if (IntersectorK::occluded(pre,ray,k,context,prim[i]))
return true;
}
return false;
}
};
}
}
@@ -26,7 +26,7 @@ namespace embree {
//#define rtcOccluded rtcIntersect
//#define rtcOccluded1M rtcIntersect1M
#define SIMPLE_SHADING 1
#define SIMPLE_SHADING 0
extern "C" ISPCScene* g_ispc_scene;
@@ -24,7 +24,7 @@
//#define rtcOccluded rtcIntersect
//#define rtcOccludedVM rtcIntersectVM
#define SIMPLE_SHADING 1
#define SIMPLE_SHADING 0
extern uniform ISPCScene* uniform g_ispc_scene;