1 | // Copyright 2009-2021 Intel Corporation |
2 | // SPDX-License-Identifier: Apache-2.0 |
3 | |
4 | #pragma once |
5 | |
6 | #include "quadi.h" |
7 | #include "quad_intersector_moeller.h" |
8 | #include "quad_intersector_pluecker.h" |
9 | |
10 | namespace embree |
11 | { |
12 | namespace isa |
13 | { |
14 | /*! Intersects M quads with 1 ray */ |
15 | template<int M, bool filter> |
16 | struct QuadMiIntersector1Moeller |
17 | { |
18 | typedef QuadMi<M> Primitive; |
19 | typedef QuadMIntersector1MoellerTrumbore<M,filter> Precalculations; |
20 | |
21 | /*! Intersect a ray with the M quads and updates the hit. */ |
22 | static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& quad) |
23 | { |
24 | STAT3(normal.trav_prims,1,1,1); |
25 | Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene); |
26 | pre.intersect(ray,context,v0,v1,v2,v3,quad.geomID(),quad.primID()); |
27 | } |
28 | |
29 | /*! Test if the ray is occluded by one of M quads. */ |
30 | static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& quad) |
31 | { |
32 | STAT3(shadow.trav_prims,1,1,1); |
33 | Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene); |
34 | return pre.occluded(ray,context,v0,v1,v2,v3,quad.geomID(),quad.primID()); |
35 | } |
36 | |
37 | static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& quad) |
38 | { |
39 | return PrimitivePointQuery1<Primitive>::pointQuery(query, context, quad); |
40 | } |
41 | }; |
42 | |
43 | /*! Intersects M triangles with K rays. */ |
44 | template<int M, int K, bool filter> |
45 | struct QuadMiIntersectorKMoeller |
46 | { |
47 | typedef QuadMi<M> Primitive; |
48 | typedef QuadMIntersectorKMoellerTrumbore<M,K,filter> Precalculations; |
49 | |
50 | /*! Intersects K rays with M triangles. */ |
51 | static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const QuadMi<M>& quad) |
52 | { |
53 | Scene* scene = context->scene; |
54 | for (size_t i=0; i<QuadMi<M>::max_size(); i++) |
55 | { |
56 | if (!quad.valid(i)) break; |
57 | STAT3(normal.trav_prims,1,popcnt(valid_i),K); |
58 | const Vec3vf<K> p0 = quad.template getVertex<0>(i,scene); |
59 | const Vec3vf<K> p1 = quad.template getVertex<1>(i,scene); |
60 | const Vec3vf<K> p2 = quad.template getVertex<2>(i,scene); |
61 | const Vec3vf<K> p3 = quad.template getVertex<3>(i,scene); |
62 | pre.intersectK(valid_i,ray,p0,p1,p2,p3,IntersectKEpilogM<M,K,filter>(ray,context,quad.geomID(),quad.primID(),i)); |
63 | } |
64 | } |
65 | |
66 | /*! Test for K rays if they are occluded by any of the M triangles. */ |
67 | static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const QuadMi<M>& quad) |
68 | { |
69 | Scene* scene = context->scene; |
70 | vbool<K> valid0 = valid_i; |
71 | for (size_t i=0; i<QuadMi<M>::max_size(); i++) |
72 | { |
73 | if (!quad.valid(i)) break; |
74 | STAT3(shadow.trav_prims,1,popcnt(valid0),K); |
75 | const Vec3vf<K> p0 = quad.template getVertex<0>(i,scene); |
76 | const Vec3vf<K> p1 = quad.template getVertex<1>(i,scene); |
77 | const Vec3vf<K> p2 = quad.template getVertex<2>(i,scene); |
78 | const Vec3vf<K> p3 = quad.template getVertex<3>(i,scene); |
79 | if (pre.intersectK(valid0,ray,p0,p1,p2,p3,OccludedKEpilogM<M,K,filter>(valid0,ray,context,quad.geomID(),quad.primID(),i))) |
80 | break; |
81 | } |
82 | return !valid0; |
83 | } |
84 | |
85 | /*! Intersect a ray with M triangles and updates the hit. */ |
86 | static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const QuadMi<M>& quad) |
87 | { |
88 | STAT3(normal.trav_prims,1,1,1); |
89 | Vec3vf4 v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene); |
90 | pre.intersect1(ray,k,context,v0,v1,v2,v3,quad.geomID(),quad.primID()); |
91 | } |
92 | |
93 | /*! Test if the ray is occluded by one of the M triangles. */ |
94 | static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const QuadMi<M>& quad) |
95 | { |
96 | STAT3(shadow.trav_prims,1,1,1); |
97 | Vec3vf4 v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene); |
98 | return pre.occluded1(ray,k,context,v0,v1,v2,v3,quad.geomID(),quad.primID()); |
99 | } |
100 | }; |
101 | |
102 | /*! Intersects M quads with 1 ray */ |
103 | template<int M, bool filter> |
104 | struct QuadMiIntersector1Pluecker |
105 | { |
106 | typedef QuadMi<M> Primitive; |
107 | typedef QuadMIntersector1Pluecker<M,filter> Precalculations; |
108 | |
109 | /*! Intersect a ray with the M quads and updates the hit. */ |
110 | static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& quad) |
111 | { |
112 | STAT3(normal.trav_prims,1,1,1); |
113 | Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene); |
114 | pre.intersect(ray,context,v0,v1,v2,v3,quad.geomID(),quad.primID()); |
115 | } |
116 | |
117 | /*! Test if the ray is occluded by one of M quads. */ |
118 | static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& quad) |
119 | { |
120 | STAT3(shadow.trav_prims,1,1,1); |
121 | Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene); |
122 | return pre.occluded(ray,context,v0,v1,v2,v3,quad.geomID(),quad.primID()); |
123 | } |
124 | |
125 | static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& quad) |
126 | { |
127 | return PrimitivePointQuery1<Primitive>::pointQuery(query, context, quad); |
128 | } |
129 | }; |
130 | |
131 | /*! Intersects M triangles with K rays. */ |
132 | template<int M, int K, bool filter> |
133 | struct QuadMiIntersectorKPluecker |
134 | { |
135 | typedef QuadMi<M> Primitive; |
136 | typedef QuadMIntersectorKPluecker<M,K,filter> Precalculations; |
137 | |
138 | /*! Intersects K rays with M triangles. */ |
139 | static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const QuadMi<M>& quad) |
140 | { |
141 | Scene* scene = context->scene; |
142 | for (size_t i=0; i<QuadMi<M>::max_size(); i++) |
143 | { |
144 | if (!quad.valid(i)) break; |
145 | STAT3(normal.trav_prims,1,popcnt(valid_i),K); |
146 | const Vec3vf<K> p0 = quad.template getVertex<0>(i,scene); |
147 | const Vec3vf<K> p1 = quad.template getVertex<1>(i,scene); |
148 | const Vec3vf<K> p2 = quad.template getVertex<2>(i,scene); |
149 | const Vec3vf<K> p3 = quad.template getVertex<3>(i,scene); |
150 | pre.intersectK(valid_i,ray,p0,p1,p2,p3,IntersectKEpilogM<M,K,filter>(ray,context,quad.geomID(),quad.primID(),i)); |
151 | } |
152 | } |
153 | |
154 | /*! Test for K rays if they are occluded by any of the M triangles. */ |
155 | static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const QuadMi<M>& quad) |
156 | { |
157 | Scene* scene = context->scene; |
158 | vbool<K> valid0 = valid_i; |
159 | for (size_t i=0; i<QuadMi<M>::max_size(); i++) |
160 | { |
161 | if (!quad.valid(i)) break; |
162 | STAT3(shadow.trav_prims,1,popcnt(valid0),K); |
163 | const Vec3vf<K> p0 = quad.template getVertex<0>(i,scene); |
164 | const Vec3vf<K> p1 = quad.template getVertex<1>(i,scene); |
165 | const Vec3vf<K> p2 = quad.template getVertex<2>(i,scene); |
166 | const Vec3vf<K> p3 = quad.template getVertex<3>(i,scene); |
167 | if (pre.intersectK(valid0,ray,p0,p1,p2,p3,OccludedKEpilogM<M,K,filter>(valid0,ray,context,quad.geomID(),quad.primID(),i))) |
168 | break; |
169 | } |
170 | return !valid0; |
171 | } |
172 | |
173 | /*! Intersect a ray with M triangles and updates the hit. */ |
174 | static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const QuadMi<M>& quad) |
175 | { |
176 | STAT3(normal.trav_prims,1,1,1); |
177 | Vec3vf4 v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene); |
178 | pre.intersect1(ray,k,context,v0,v1,v2,v3,quad.geomID(),quad.primID()); |
179 | } |
180 | |
181 | /*! Test if the ray is occluded by one of the M triangles. */ |
182 | static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const QuadMi<M>& quad) |
183 | { |
184 | STAT3(shadow.trav_prims,1,1,1); |
185 | Vec3vf4 v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene); |
186 | return pre.occluded1(ray,k,context,v0,v1,v2,v3,quad.geomID(),quad.primID()); |
187 | } |
188 | }; |
189 | |
190 | /*! Intersects M motion blur quads with 1 ray */ |
191 | template<int M, bool filter> |
192 | struct QuadMiMBIntersector1Moeller |
193 | { |
194 | typedef QuadMi<M> Primitive; |
195 | typedef QuadMIntersector1MoellerTrumbore<M,filter> Precalculations; |
196 | |
197 | /*! Intersect a ray with the M quads and updates the hit. */ |
198 | static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& quad) |
199 | { |
200 | STAT3(normal.trav_prims,1,1,1); |
201 | Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene,ray.time()); |
202 | pre.intersect(ray,context,v0,v1,v2,v3,quad.geomID(),quad.primID()); |
203 | } |
204 | |
205 | /*! Test if the ray is occluded by one of M quads. */ |
206 | static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& quad) |
207 | { |
208 | STAT3(shadow.trav_prims,1,1,1); |
209 | Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene,ray.time()); |
210 | return pre.occluded(ray,context,v0,v1,v2,v3,quad.geomID(),quad.primID()); |
211 | } |
212 | |
213 | static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& quad) |
214 | { |
215 | return PrimitivePointQuery1<Primitive>::pointQuery(query, context, quad); |
216 | } |
217 | }; |
218 | |
219 | /*! Intersects M motion blur quads with K rays. */ |
220 | template<int M, int K, bool filter> |
221 | struct QuadMiMBIntersectorKMoeller |
222 | { |
223 | typedef QuadMi<M> Primitive; |
224 | typedef QuadMIntersectorKMoellerTrumbore<M,K,filter> Precalculations; |
225 | |
226 | /*! Intersects K rays with M quads. */ |
227 | static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const QuadMi<M>& quad) |
228 | { |
229 | for (size_t i=0; i<QuadMi<M>::max_size(); i++) |
230 | { |
231 | if (!quad.valid(i)) break; |
232 | STAT3(normal.trav_prims,1,popcnt(valid_i),K); |
233 | Vec3vf<K> v0,v1,v2,v3; quad.template gather<K>(valid_i,v0,v1,v2,v3,i,context->scene,ray.time()); |
234 | pre.intersectK(valid_i,ray,v0,v1,v2,v3,IntersectKEpilogM<M,K,filter>(ray,context,quad.geomID(),quad.primID(),i)); |
235 | } |
236 | } |
237 | |
238 | /*! Test for K rays if they are occluded by any of the M quads. */ |
239 | static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const QuadMi<M>& quad) |
240 | { |
241 | vbool<K> valid0 = valid_i; |
242 | for (size_t i=0; i<QuadMi<M>::max_size(); i++) |
243 | { |
244 | if (!quad.valid(i)) break; |
245 | STAT3(shadow.trav_prims,1,popcnt(valid0),K); |
246 | Vec3vf<K> v0,v1,v2,v3; quad.template gather<K>(valid_i,v0,v1,v2,v3,i,context->scene,ray.time()); |
247 | if (pre.intersectK(valid0,ray,v0,v1,v2,v3,OccludedKEpilogM<M,K,filter>(valid0,ray,context,quad.geomID(),quad.primID(),i))) |
248 | break; |
249 | } |
250 | return !valid0; |
251 | } |
252 | |
253 | /*! Intersect a ray with M quads and updates the hit. */ |
254 | static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const QuadMi<M>& quad) |
255 | { |
256 | STAT3(normal.trav_prims,1,1,1); |
257 | Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene,ray.time()[k]); |
258 | pre.intersect1(ray,k,context,v0,v1,v2,v3,quad.geomID(),quad.primID()); |
259 | } |
260 | |
261 | /*! Test if the ray is occluded by one of the M quads. */ |
262 | static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const QuadMi<M>& quad) |
263 | { |
264 | STAT3(shadow.trav_prims,1,1,1); |
265 | Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene,ray.time()[k]); |
266 | return pre.occluded1(ray,k,context,v0,v1,v2,v3,quad.geomID(),quad.primID()); |
267 | } |
268 | }; |
269 | |
270 | /*! Intersects M motion blur quads with 1 ray */ |
271 | template<int M, bool filter> |
272 | struct QuadMiMBIntersector1Pluecker |
273 | { |
274 | typedef QuadMi<M> Primitive; |
275 | typedef QuadMIntersector1Pluecker<M,filter> Precalculations; |
276 | |
277 | /*! Intersect a ray with the M quads and updates the hit. */ |
278 | static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& quad) |
279 | { |
280 | STAT3(normal.trav_prims,1,1,1); |
281 | Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene,ray.time()); |
282 | pre.intersect(ray,context,v0,v1,v2,v3,quad.geomID(),quad.primID()); |
283 | } |
284 | |
285 | /*! Test if the ray is occluded by one of M quads. */ |
286 | static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& quad) |
287 | { |
288 | STAT3(shadow.trav_prims,1,1,1); |
289 | Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene,ray.time()); |
290 | return pre.occluded(ray,context,v0,v1,v2,v3,quad.geomID(),quad.primID()); |
291 | } |
292 | |
293 | static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& quad) |
294 | { |
295 | return PrimitivePointQuery1<Primitive>::pointQuery(query, context, quad); |
296 | } |
297 | }; |
298 | |
299 | /*! Intersects M motion blur quads with K rays. */ |
300 | template<int M, int K, bool filter> |
301 | struct QuadMiMBIntersectorKPluecker |
302 | { |
303 | typedef QuadMi<M> Primitive; |
304 | typedef QuadMIntersectorKPluecker<M,K,filter> Precalculations; |
305 | |
306 | /*! Intersects K rays with M quads. */ |
307 | static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const QuadMi<M>& quad) |
308 | { |
309 | for (size_t i=0; i<QuadMi<M>::max_size(); i++) |
310 | { |
311 | if (!quad.valid(i)) break; |
312 | STAT3(normal.trav_prims,1,popcnt(valid_i),K); |
313 | Vec3vf<K> v0,v1,v2,v3; quad.template gather<K>(valid_i,v0,v1,v2,v3,i,context->scene,ray.time()); |
314 | pre.intersectK(valid_i,ray,v0,v1,v2,v3,IntersectKEpilogM<M,K,filter>(ray,context,quad.geomID(),quad.primID(),i)); |
315 | } |
316 | } |
317 | |
318 | /*! Test for K rays if they are occluded by any of the M quads. */ |
319 | static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const QuadMi<M>& quad) |
320 | { |
321 | vbool<K> valid0 = valid_i; |
322 | for (size_t i=0; i<QuadMi<M>::max_size(); i++) |
323 | { |
324 | if (!quad.valid(i)) break; |
325 | STAT3(shadow.trav_prims,1,popcnt(valid0),K); |
326 | Vec3vf<K> v0,v1,v2,v3; quad.template gather<K>(valid_i,v0,v1,v2,v3,i,context->scene,ray.time()); |
327 | if (pre.intersectK(valid0,ray,v0,v1,v2,v3,OccludedKEpilogM<M,K,filter>(valid0,ray,context,quad.geomID(),quad.primID(),i))) |
328 | break; |
329 | } |
330 | return !valid0; |
331 | } |
332 | |
333 | /*! Intersect a ray with M quads and updates the hit. */ |
334 | static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const QuadMi<M>& quad) |
335 | { |
336 | STAT3(normal.trav_prims,1,1,1); |
337 | Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene,ray.time()[k]); |
338 | pre.intersect1(ray,k,context,v0,v1,v2,v3,quad.geomID(),quad.primID()); |
339 | } |
340 | |
341 | /*! Test if the ray is occluded by one of the M quads. */ |
342 | static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const QuadMi<M>& quad) |
343 | { |
344 | STAT3(shadow.trav_prims,1,1,1); |
345 | Vec3vf<M> v0,v1,v2,v3; quad.gather(v0,v1,v2,v3,context->scene,ray.time()[k]); |
346 | return pre.occluded1(ray,k,context,v0,v1,v2,v3,quad.geomID(),quad.primID()); |
347 | } |
348 | }; |
349 | } |
350 | } |
351 | |