Revision control

++ // 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++;
++ }
++ }
++ };
++ }
++ }