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 | |
10 | namespace 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 | |