Compare commits
14
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c0d1b3a74a | ||
|
|
7c539db74c | ||
|
|
68f0344542 | ||
|
|
4f0de63859 | ||
|
|
c8ea4294ae | ||
|
|
4243db227a | ||
|
|
dc961964ee | ||
|
|
cb1fb07edf | ||
|
|
d7ce521c89 | ||
|
|
3bf2e5d694 | ||
|
|
f3aa55fa73 | ||
|
|
d93226eedf | ||
|
|
2d780d85fb | ||
|
|
e8aa112afa |
Executable → Regular
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user