1 // Copyright 2009-2021 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 
4 #pragma once
5 
6 #include "rtcore.h"
7 
8 namespace embree {
9 namespace instance_id_stack {
10 
11 static_assert(RTC_MAX_INSTANCE_LEVEL_COUNT > 0,
12               "RTC_MAX_INSTANCE_LEVEL_COUNT must be greater than 0.");
13 
14 /*******************************************************************************
15  * Instance ID stack manipulation.
16  * This is used from the instance intersector.
17  ******************************************************************************/
18 
19 /*
20  * Push an instance to the stack.
21  */
push(RTCIntersectContext * context,unsigned instanceId)22 RTC_FORCEINLINE bool push(RTCIntersectContext* context,
23                           unsigned instanceId)
24 {
25 #if RTC_MAX_INSTANCE_LEVEL_COUNT > 1
26   const bool spaceAvailable = context->instStackSize < RTC_MAX_INSTANCE_LEVEL_COUNT;
27   /* We assert here because instances are silently dropped when the stack is full.
28      This might be quite hard to find in production. */
29   assert(spaceAvailable);
30   if (likely(spaceAvailable))
31     context->instID[context->instStackSize++] = instanceId;
32   return spaceAvailable;
33 #else
34   const bool spaceAvailable = (context->instID[0] == RTC_INVALID_GEOMETRY_ID);
35   assert(spaceAvailable);
36   if (likely(spaceAvailable))
37     context->instID[0] = instanceId;
38   return spaceAvailable;
39 #endif
40 }
41 
42 
43 /*
44  * Pop the last instance pushed to the stack.
45  * Do not call on an empty stack.
46  */
pop(RTCIntersectContext * context)47 RTC_FORCEINLINE void pop(RTCIntersectContext* context)
48 {
49   assert(context);
50 #if RTC_MAX_INSTANCE_LEVEL_COUNT > 1
51   assert(context->instStackSize > 0);
52   context->instID[--context->instStackSize] = RTC_INVALID_GEOMETRY_ID;
53 #else
54   assert(context->instID[0] != RTC_INVALID_GEOMETRY_ID);
55   context->instID[0] = RTC_INVALID_GEOMETRY_ID;
56 #endif
57 }
58 
59 /*
60  * Optimized instance id stack copy.
61  * The copy() functions will either copy full
62  * stacks or copy only until the last valid element has been copied, depending
63  * on RTC_MAX_INSTANCE_LEVEL_COUNT.
64  */
copy_UU(const unsigned * src,unsigned * tgt)65 RTC_FORCEINLINE void copy_UU(const unsigned* src, unsigned* tgt)
66 {
67 #if (RTC_MAX_INSTANCE_LEVEL_COUNT == 1)
68   tgt[0] = src[0];
69 
70 #else
71   for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l) {
72     tgt[l] = src[l];
73     if (RTC_MAX_INSTANCE_LEVEL_COUNT > 4)
74       if (src[l] == RTC_INVALID_GEOMETRY_ID)
75         break;
76   }
77 #endif
78 }
79 
80 template <int K>
copy_UV(const unsigned * src,vuint<K> * tgt)81 RTC_FORCEINLINE void copy_UV(const unsigned* src, vuint<K>* tgt)
82 {
83 #if (RTC_MAX_INSTANCE_LEVEL_COUNT == 1)
84   tgt[0] = src[0];
85 
86 #else
87   for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l) {
88     tgt[l] = src[l];
89     if (RTC_MAX_INSTANCE_LEVEL_COUNT > 4)
90       if (src[l] == RTC_INVALID_GEOMETRY_ID)
91         break;
92   }
93 #endif
94 }
95 
96 template <int K>
copy_UV(const unsigned * src,vuint<K> * tgt,size_t j)97 RTC_FORCEINLINE void copy_UV(const unsigned* src, vuint<K>* tgt, size_t j)
98 {
99 #if (RTC_MAX_INSTANCE_LEVEL_COUNT == 1)
100   tgt[0][j] = src[0];
101 
102 #else
103   for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l) {
104     tgt[l][j] = src[l];
105     if (RTC_MAX_INSTANCE_LEVEL_COUNT > 4)
106       if (src[l] == RTC_INVALID_GEOMETRY_ID)
107         break;
108   }
109 #endif
110 }
111 
112 template <int K>
copy_UV(const unsigned * src,vuint<K> * tgt,const vbool<K> & mask)113 RTC_FORCEINLINE void copy_UV(const unsigned* src, vuint<K>* tgt, const vbool<K>& mask)
114 {
115 #if (RTC_MAX_INSTANCE_LEVEL_COUNT == 1)
116   vuint<K>::store(mask, tgt, src[0]);
117 
118 #else
119   for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l) {
120     vuint<K>::store(mask, tgt + l, src[l]);
121     if (RTC_MAX_INSTANCE_LEVEL_COUNT > 4)
122       if (src[l] == RTC_INVALID_GEOMETRY_ID)
123         break;
124   }
125 #endif
126 }
127 
128 template <int K>
copy_VU(const vuint<K> * src,unsigned * tgt,size_t i)129 RTC_FORCEINLINE void copy_VU(const vuint<K>* src, unsigned* tgt, size_t i)
130 {
131 #if (RTC_MAX_INSTANCE_LEVEL_COUNT == 1)
132   tgt[0] = src[0][i];
133 
134 #else
135   for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l) {
136     tgt[l] = src[l][i];
137     if (RTC_MAX_INSTANCE_LEVEL_COUNT > 4)
138       if (src[l][i] == RTC_INVALID_GEOMETRY_ID)
139         break;
140   }
141 #endif
142 }
143 
144 template <int K>
copy_VV(const vuint<K> * src,vuint<K> * tgt,size_t i,size_t j)145 RTC_FORCEINLINE void copy_VV(const vuint<K>* src, vuint<K>* tgt, size_t i, size_t j)
146 {
147 #if (RTC_MAX_INSTANCE_LEVEL_COUNT == 1)
148   tgt[0][j] = src[0][i];
149 
150 #else
151   for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l) {
152     tgt[l][j] = src[l][i];
153     if (RTC_MAX_INSTANCE_LEVEL_COUNT > 4)
154       if (src[l][i] == RTC_INVALID_GEOMETRY_ID)
155         break;
156   }
157 #endif
158 }
159 
160 template <int K>
copy_VV(const vuint<K> * src,vuint<K> * tgt,const vbool<K> & mask)161 RTC_FORCEINLINE void copy_VV(const vuint<K>* src, vuint<K>* tgt, const vbool<K>& mask)
162 {
163 #if (RTC_MAX_INSTANCE_LEVEL_COUNT == 1)
164   vuint<K>::store(mask, tgt, src[0]);
165 
166 #else
167   vbool<K> done = !mask;
168   for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l) {
169     vuint<K>::store(mask, tgt + l, src[l]);
170     if (RTC_MAX_INSTANCE_LEVEL_COUNT > 4) {
171       done |= src[l] == RTC_INVALID_GEOMETRY_ID;
172       if (all(done)) break;
173     }
174   }
175 #endif
176 }
177 
178 } // namespace instance_id_stack
179 } // namespace embree
180