150 lines
4.6 KiB
C++
150 lines
4.6 KiB
C++
// Copyright 2009-2021 Intel Corporation
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
#pragma once
|
|
|
|
#include "bvh.h"
|
|
#include "../common/ray.h"
|
|
#include "../common/stack_item.h"
|
|
|
|
namespace embree
|
|
{
|
|
namespace isa
|
|
{
|
|
template<int N, int types>
|
|
class BVHNNodeTraverserStreamHitCoherent
|
|
{
|
|
typedef BVHN<N> BVH;
|
|
typedef typename BVH::NodeRef NodeRef;
|
|
typedef typename BVH::BaseNode BaseNode;
|
|
|
|
public:
|
|
template<class T>
|
|
static __forceinline void traverseClosestHit(NodeRef& cur,
|
|
size_t& m_trav_active,
|
|
const vbool<N>& vmask,
|
|
const vfloat<N>& tNear,
|
|
const T* const tMask,
|
|
StackItemMaskCoherent*& stackPtr)
|
|
{
|
|
const NodeRef parent = cur;
|
|
size_t mask = movemask(vmask);
|
|
assert(mask != 0);
|
|
const BaseNode* node = cur.baseNode();
|
|
|
|
/*! one child is hit, continue with that child */
|
|
const size_t r0 = bscf(mask);
|
|
assert(r0 < 8);
|
|
cur = node->child(r0);
|
|
BVHN<N>::prefetch(cur,types);
|
|
m_trav_active = tMask[r0];
|
|
assert(cur != BVH::emptyNode);
|
|
if (unlikely(mask == 0)) return;
|
|
|
|
const unsigned int* const tNear_i = (unsigned int*)&tNear;
|
|
|
|
/*! two children are hit, push far child, and continue with closer child */
|
|
NodeRef c0 = cur;
|
|
unsigned int d0 = tNear_i[r0];
|
|
const size_t r1 = bscf(mask);
|
|
assert(r1 < 8);
|
|
NodeRef c1 = node->child(r1);
|
|
BVHN<N>::prefetch(c1,types);
|
|
unsigned int d1 = tNear_i[r1];
|
|
|
|
assert(c0 != BVH::emptyNode);
|
|
assert(c1 != BVH::emptyNode);
|
|
if (likely(mask == 0)) {
|
|
if (d0 < d1) {
|
|
assert(tNear[r1] >= 0.0f);
|
|
stackPtr->mask = tMask[r1];
|
|
stackPtr->parent = parent;
|
|
stackPtr->child = c1;
|
|
stackPtr++;
|
|
cur = c0;
|
|
m_trav_active = tMask[r0];
|
|
return;
|
|
}
|
|
else {
|
|
assert(tNear[r0] >= 0.0f);
|
|
stackPtr->mask = tMask[r0];
|
|
stackPtr->parent = parent;
|
|
stackPtr->child = c0;
|
|
stackPtr++;
|
|
cur = c1;
|
|
m_trav_active = tMask[r1];
|
|
return;
|
|
}
|
|
}
|
|
|
|
/*! slow path for more than two hits */
|
|
size_t hits = movemask(vmask);
|
|
const vint<N> dist_i = select(vmask, (asInt(tNear) & 0xfffffff8) | vint<N>(step), 0);
|
|
const vint<N> dist_i_sorted = usort_descending(dist_i);
|
|
const vint<N> sorted_index = dist_i_sorted & 7;
|
|
|
|
size_t i = 0;
|
|
for (;;)
|
|
{
|
|
const unsigned int index = sorted_index[i];
|
|
assert(index < 8);
|
|
cur = node->child(index);
|
|
m_trav_active = tMask[index];
|
|
assert(m_trav_active);
|
|
BVHN<N>::prefetch(cur,types);
|
|
bscf(hits);
|
|
if (unlikely(hits==0)) break;
|
|
i++;
|
|
assert(cur != BVH::emptyNode);
|
|
assert(tNear[index] >= 0.0f);
|
|
stackPtr->mask = m_trav_active;
|
|
stackPtr->parent = parent;
|
|
stackPtr->child = cur;
|
|
stackPtr++;
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
static __forceinline void traverseAnyHit(NodeRef& cur,
|
|
size_t& m_trav_active,
|
|
const vbool<N>& vmask,
|
|
const T* const tMask,
|
|
StackItemMaskCoherent*& stackPtr)
|
|
{
|
|
const NodeRef parent = cur;
|
|
size_t mask = movemask(vmask);
|
|
assert(mask != 0);
|
|
const BaseNode* node = cur.baseNode();
|
|
|
|
/*! one child is hit, continue with that child */
|
|
size_t r = bscf(mask);
|
|
cur = node->child(r);
|
|
BVHN<N>::prefetch(cur,types);
|
|
m_trav_active = tMask[r];
|
|
|
|
/* simple in order sequence */
|
|
assert(cur != BVH::emptyNode);
|
|
if (likely(mask == 0)) return;
|
|
stackPtr->mask = m_trav_active;
|
|
stackPtr->parent = parent;
|
|
stackPtr->child = cur;
|
|
stackPtr++;
|
|
|
|
for (; ;)
|
|
{
|
|
r = bscf(mask);
|
|
cur = node->child(r);
|
|
BVHN<N>::prefetch(cur,types);
|
|
m_trav_active = tMask[r];
|
|
assert(cur != BVH::emptyNode);
|
|
if (likely(mask == 0)) return;
|
|
stackPtr->mask = m_trav_active;
|
|
stackPtr->parent = parent;
|
|
stackPtr->child = cur;
|
|
stackPtr++;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
}
|