1// Copyright 2009-2021 Intel Corporation
2// SPDX-License-Identifier: Apache-2.0
3
4#pragma once
5
6#include "bvh.h"
7#include "../common/ray.h"
8#include "../common/stack_item.h"
9
10namespace embree
11{
12 namespace isa
13 {
14 template<int N, int types>
15 class BVHNNodeTraverserStreamHitCoherent
16 {
17 typedef BVHN<N> BVH;
18 typedef typename BVH::NodeRef NodeRef;
19 typedef typename BVH::BaseNode BaseNode;
20
21 public:
22 template<class T>
23 static __forceinline void traverseClosestHit(NodeRef& cur,
24 size_t& m_trav_active,
25 const vbool<N>& vmask,
26 const vfloat<N>& tNear,
27 const T* const tMask,
28 StackItemMaskCoherent*& stackPtr)
29 {
30 const NodeRef parent = cur;
31 size_t mask = movemask(vmask);
32 assert(mask != 0);
33 const BaseNode* node = cur.baseNode();
34
35 /*! one child is hit, continue with that child */
36 const size_t r0 = bscf(mask);
37 assert(r0 < 8);
38 cur = node->child(r0);
39 BVHN<N>::prefetch(cur,types);
40 m_trav_active = tMask[r0];
41 assert(cur != BVH::emptyNode);
42 if (unlikely(mask == 0)) return;
43
44 const unsigned int* const tNear_i = (unsigned int*)&tNear;
45
46 /*! two children are hit, push far child, and continue with closer child */
47 NodeRef c0 = cur;
48 unsigned int d0 = tNear_i[r0];
49 const size_t r1 = bscf(mask);
50 assert(r1 < 8);
51 NodeRef c1 = node->child(r1);
52 BVHN<N>::prefetch(c1,types);
53 unsigned int d1 = tNear_i[r1];
54
55 assert(c0 != BVH::emptyNode);
56 assert(c1 != BVH::emptyNode);
57 if (likely(mask == 0)) {
58 if (d0 < d1) {
59 assert(tNear[r1] >= 0.0f);
60 stackPtr->mask = tMask[r1];
61 stackPtr->parent = parent;
62 stackPtr->child = c1;
63 stackPtr++;
64 cur = c0;
65 m_trav_active = tMask[r0];
66 return;
67 }
68 else {
69 assert(tNear[r0] >= 0.0f);
70 stackPtr->mask = tMask[r0];
71 stackPtr->parent = parent;
72 stackPtr->child = c0;
73 stackPtr++;
74 cur = c1;
75 m_trav_active = tMask[r1];
76 return;
77 }
78 }
79
80 /*! slow path for more than two hits */
81 size_t hits = movemask(vmask);
82 const vint<N> dist_i = select(vmask, (asInt(tNear) & 0xfffffff8) | vint<N>(step), 0);
83 const vint<N> dist_i_sorted = usort_descending(dist_i);
84 const vint<N> sorted_index = dist_i_sorted & 7;
85
86 size_t i = 0;
87 for (;;)
88 {
89 const unsigned int index = sorted_index[i];
90 assert(index < 8);
91 cur = node->child(index);
92 m_trav_active = tMask[index];
93 assert(m_trav_active);
94 BVHN<N>::prefetch(cur,types);
95 bscf(hits);
96 if (unlikely(hits==0)) break;
97 i++;
98 assert(cur != BVH::emptyNode);
99 assert(tNear[index] >= 0.0f);
100 stackPtr->mask = m_trav_active;
101 stackPtr->parent = parent;
102 stackPtr->child = cur;
103 stackPtr++;
104 }
105 }
106
107 template<class T>
108 static __forceinline void traverseAnyHit(NodeRef& cur,
109 size_t& m_trav_active,
110 const vbool<N>& vmask,
111 const T* const tMask,
112 StackItemMaskCoherent*& stackPtr)
113 {
114 const NodeRef parent = cur;
115 size_t mask = movemask(vmask);
116 assert(mask != 0);
117 const BaseNode* node = cur.baseNode();
118
119 /*! one child is hit, continue with that child */
120 size_t r = bscf(mask);
121 cur = node->child(r);
122 BVHN<N>::prefetch(cur,types);
123 m_trav_active = tMask[r];
124
125 /* simple in order sequence */
126 assert(cur != BVH::emptyNode);
127 if (likely(mask == 0)) return;
128 stackPtr->mask = m_trav_active;
129 stackPtr->parent = parent;
130 stackPtr->child = cur;
131 stackPtr++;
132
133 for (; ;)
134 {
135 r = bscf(mask);
136 cur = node->child(r);
137 BVHN<N>::prefetch(cur,types);
138 m_trav_active = tMask[r];
139 assert(cur != BVH::emptyNode);
140 if (likely(mask == 0)) return;
141 stackPtr->mask = m_trav_active;
142 stackPtr->parent = parent;
143 stackPtr->child = cur;
144 stackPtr++;
145 }
146 }
147 };
148 }
149}
150