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