1 | // Copyright 2009-2021 Intel Corporation |
2 | // SPDX-License-Identifier: Apache-2.0 |
3 | |
4 | #pragma once |
5 | |
6 | #include "curveNi.h" |
7 | |
8 | namespace embree |
9 | { |
10 | namespace isa |
11 | { |
12 | template<int M> |
13 | struct CurveNiIntersector1 |
14 | { |
15 | typedef CurveNi<M> Primitive; |
16 | typedef Vec3vf<M> Vec3vfM; |
17 | typedef LinearSpace3<Vec3vfM>LinearSpace3vfM; |
18 | typedef CurvePrecalculations1 Precalculations; |
19 | |
20 | static __forceinline vbool<M> intersect(Ray& ray, const Primitive& prim, vfloat<M>& tNear_o) |
21 | { |
22 | const size_t N = prim.N; |
23 | const vfloat4 offset_scale = vfloat4::loadu(prim.offset(N)); |
24 | const Vec3fa offset = Vec3fa(offset_scale); |
25 | const Vec3fa scale = Vec3fa(shuffle<3,3,3,3>(v: offset_scale)); |
26 | const Vec3fa org1 = (ray.org-offset)*scale; |
27 | const Vec3fa dir1 = ray.dir*scale; |
28 | |
29 | const LinearSpace3vfM space(vfloat<M>::load(prim.bounds_vx_x(N)), vfloat<M>::load(prim.bounds_vx_y(N)), vfloat<M>::load(prim.bounds_vx_z(N)), |
30 | vfloat<M>::load(prim.bounds_vy_x(N)), vfloat<M>::load(prim.bounds_vy_y(N)), vfloat<M>::load(prim.bounds_vy_z(N)), |
31 | vfloat<M>::load(prim.bounds_vz_x(N)), vfloat<M>::load(prim.bounds_vz_y(N)), vfloat<M>::load(prim.bounds_vz_z(N))); |
32 | |
33 | const Vec3vfM dir2 = xfmVector(space,Vec3vfM(dir1)); |
34 | const Vec3vfM org2 = xfmPoint (space,Vec3vfM(org1)); |
35 | const Vec3vfM rcp_dir2 = rcp_safe(dir2); |
36 | |
37 | const vfloat<M> t_lower_x = (vfloat<M>::load(prim.bounds_vx_lower(N))-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x); |
38 | const vfloat<M> t_upper_x = (vfloat<M>::load(prim.bounds_vx_upper(N))-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x); |
39 | const vfloat<M> t_lower_y = (vfloat<M>::load(prim.bounds_vy_lower(N))-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y); |
40 | const vfloat<M> t_upper_y = (vfloat<M>::load(prim.bounds_vy_upper(N))-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y); |
41 | const vfloat<M> t_lower_z = (vfloat<M>::load(prim.bounds_vz_lower(N))-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z); |
42 | const vfloat<M> t_upper_z = (vfloat<M>::load(prim.bounds_vz_upper(N))-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z); |
43 | |
44 | const vfloat<M> round_up (1.0f+3.0f*float(ulp)); |
45 | const vfloat<M> round_down(1.0f-3.0f*float(ulp)); |
46 | const vfloat<M> tNear = round_down*max(mini(t_lower_x,t_upper_x),mini(t_lower_y,t_upper_y),mini(t_lower_z,t_upper_z),vfloat<M>(ray.tnear())); |
47 | const vfloat<M> tFar = round_up *min(maxi(t_lower_x,t_upper_x),maxi(t_lower_y,t_upper_y),maxi(t_lower_z,t_upper_z),vfloat<M>(ray.tfar)); |
48 | tNear_o = tNear; |
49 | return (vint<M>(step) < vint<M>(prim.N)) & (tNear <= tFar); |
50 | } |
51 | |
52 | template<typename Intersector, typename Epilog> |
53 | static __forceinline void intersect_t(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim) |
54 | { |
55 | vfloat<M> tNear; |
56 | vbool<M> valid = intersect(ray,prim,tNear_o&: tNear); |
57 | |
58 | const size_t N = prim.N; |
59 | size_t mask = movemask(valid); |
60 | while (mask) |
61 | { |
62 | const size_t i = bscf(v&: mask); |
63 | STAT3(normal.trav_prims,1,1,1); |
64 | const unsigned int geomID = prim.geomID(N); |
65 | const unsigned int primID = prim.primID(N)[i]; |
66 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
67 | Vec3ff a0,a1,a2,a3; geom->gather(p0&: a0,p1&: a1,p2&: a2,p3&: a3,i: geom->curve(i: primID)); |
68 | |
69 | size_t mask1 = mask; |
70 | const size_t i1 = bscf(v&: mask1); |
71 | if (mask) { |
72 | const unsigned int primID1 = prim.primID(N)[i1]; |
73 | geom->prefetchL1_vertices(i: geom->curve(i: primID1)); |
74 | if (mask1) { |
75 | const size_t i2 = bsf(v: mask1); |
76 | const unsigned int primID2 = prim.primID(N)[i2]; |
77 | geom->prefetchL2_vertices(i: geom->curve(i: primID2)); |
78 | } |
79 | } |
80 | |
81 | Intersector().intersect(pre,ray,context,geom,primID,a0,a1,a2,a3,Epilog(ray,context,geomID,primID)); |
82 | mask &= movemask(tNear <= vfloat<M>(ray.tfar)); |
83 | } |
84 | } |
85 | |
86 | template<typename Intersector, typename Epilog> |
87 | static __forceinline bool occluded_t(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim) |
88 | { |
89 | vfloat<M> tNear; |
90 | vbool<M> valid = intersect(ray,prim,tNear_o&: tNear); |
91 | |
92 | const size_t N = prim.N; |
93 | size_t mask = movemask(valid); |
94 | while (mask) |
95 | { |
96 | const size_t i = bscf(v&: mask); |
97 | STAT3(shadow.trav_prims,1,1,1); |
98 | const unsigned int geomID = prim.geomID(N); |
99 | const unsigned int primID = prim.primID(N)[i]; |
100 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
101 | Vec3ff a0,a1,a2,a3; geom->gather(p0&: a0,p1&: a1,p2&: a2,p3&: a3,i: geom->curve(i: primID)); |
102 | |
103 | size_t mask1 = mask; |
104 | const size_t i1 = bscf(v&: mask1); |
105 | if (mask) { |
106 | const unsigned int primID1 = prim.primID(N)[i1]; |
107 | geom->prefetchL1_vertices(i: geom->curve(i: primID1)); |
108 | if (mask1) { |
109 | const size_t i2 = bsf(v: mask1); |
110 | const unsigned int primID2 = prim.primID(N)[i2]; |
111 | geom->prefetchL2_vertices(i: geom->curve(i: primID2)); |
112 | } |
113 | } |
114 | |
115 | if (Intersector().intersect(pre,ray,context,geom,primID,a0,a1,a2,a3,Epilog(ray,context,geomID,primID))) |
116 | return true; |
117 | |
118 | mask &= movemask(tNear <= vfloat<M>(ray.tfar)); |
119 | } |
120 | return false; |
121 | } |
122 | |
123 | template<typename Intersector, typename Epilog> |
124 | static __forceinline void intersect_n(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim) |
125 | { |
126 | vfloat<M> tNear; |
127 | vbool<M> valid = intersect(ray,prim,tNear_o&: tNear); |
128 | |
129 | const size_t N = prim.N; |
130 | size_t mask = movemask(valid); |
131 | while (mask) |
132 | { |
133 | const size_t i = bscf(v&: mask); |
134 | STAT3(normal.trav_prims,1,1,1); |
135 | const unsigned int geomID = prim.geomID(N); |
136 | const unsigned int primID = prim.primID(N)[i]; |
137 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
138 | |
139 | unsigned int vertexID = geom->curve(i: primID); |
140 | Vec3ff a0,a1,a2,a3; Vec3fa n0,n1,n2,n3; geom->gather(p0&: a0,p1&: a1,p2&: a2,p3&: a3,n0,n1,n2,n3,i: vertexID); |
141 | |
142 | size_t mask1 = mask; |
143 | const size_t i1 = bscf(v&: mask1); |
144 | if (mask) { |
145 | const unsigned int primID1 = prim.primID(N)[i1]; |
146 | geom->prefetchL1_vertices(i: geom->curve(i: primID1)); |
147 | if (mask1) { |
148 | const size_t i2 = bsf(v: mask1); |
149 | const unsigned int primID2 = prim.primID(N)[i2]; |
150 | geom->prefetchL2_vertices(i: geom->curve(i: primID2)); |
151 | } |
152 | } |
153 | |
154 | Intersector().intersect(pre,ray,context,geom,primID,a0,a1,a2,a3,n0,n1,n2,n3,Epilog(ray,context,geomID,primID)); |
155 | mask &= movemask(tNear <= vfloat<M>(ray.tfar)); |
156 | } |
157 | } |
158 | |
159 | template<typename Intersector, typename Epilog> |
160 | static __forceinline bool occluded_n(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim) |
161 | { |
162 | vfloat<M> tNear; |
163 | vbool<M> valid = intersect(ray,prim,tNear_o&: tNear); |
164 | |
165 | const size_t N = prim.N; |
166 | size_t mask = movemask(valid); |
167 | while (mask) |
168 | { |
169 | const size_t i = bscf(v&: mask); |
170 | STAT3(shadow.trav_prims,1,1,1); |
171 | const unsigned int geomID = prim.geomID(N); |
172 | const unsigned int primID = prim.primID(N)[i]; |
173 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
174 | |
175 | unsigned int vertexID = geom->curve(i: primID); |
176 | Vec3ff a0,a1,a2,a3; Vec3fa n0,n1,n2,n3; geom->gather(p0&: a0,p1&: a1,p2&: a2,p3&: a3,n0,n1,n2,n3,i: vertexID); |
177 | |
178 | size_t mask1 = mask; |
179 | const size_t i1 = bscf(v&: mask1); |
180 | if (mask) { |
181 | const unsigned int primID1 = prim.primID(N)[i1]; |
182 | geom->prefetchL1_vertices(i: geom->curve(i: primID1)); |
183 | if (mask1) { |
184 | const size_t i2 = bsf(v: mask1); |
185 | const unsigned int primID2 = prim.primID(N)[i2]; |
186 | geom->prefetchL2_vertices(i: geom->curve(i: primID2)); |
187 | } |
188 | } |
189 | |
190 | if (Intersector().intersect(pre,ray,context,geom,primID,a0,a1,a2,a3,n0,n1,n2,n3,Epilog(ray,context,geomID,primID))) |
191 | return true; |
192 | |
193 | mask &= movemask(tNear <= vfloat<M>(ray.tfar)); |
194 | } |
195 | return false; |
196 | } |
197 | |
198 | template<typename Intersector, typename Epilog> |
199 | static __forceinline void intersect_h(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim) |
200 | { |
201 | vfloat<M> tNear; |
202 | vbool<M> valid = intersect(ray,prim,tNear_o&: tNear); |
203 | |
204 | const size_t N = prim.N; |
205 | size_t mask = movemask(valid); |
206 | while (mask) |
207 | { |
208 | const size_t i = bscf(v&: mask); |
209 | STAT3(normal.trav_prims,1,1,1); |
210 | const unsigned int geomID = prim.geomID(N); |
211 | const unsigned int primID = prim.primID(N)[i]; |
212 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
213 | Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,i: geom->curve(i: primID)); |
214 | Intersector().intersect(pre,ray,context,geom,primID,p0,t0,p1,t1,Epilog(ray,context,geomID,primID)); |
215 | mask &= movemask(tNear <= vfloat<M>(ray.tfar)); |
216 | } |
217 | } |
218 | |
219 | template<typename Intersector, typename Epilog> |
220 | static __forceinline bool occluded_h(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim) |
221 | { |
222 | vfloat<M> tNear; |
223 | vbool<M> valid = intersect(ray,prim,tNear_o&: tNear); |
224 | |
225 | const size_t N = prim.N; |
226 | size_t mask = movemask(valid); |
227 | while (mask) |
228 | { |
229 | const size_t i = bscf(v&: mask); |
230 | STAT3(shadow.trav_prims,1,1,1); |
231 | const unsigned int geomID = prim.geomID(N); |
232 | const unsigned int primID = prim.primID(N)[i]; |
233 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
234 | Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,i: geom->curve(i: primID)); |
235 | if (Intersector().intersect(pre,ray,context,geom,primID,p0,t0,p1,t1,Epilog(ray,context,geomID,primID))) |
236 | return true; |
237 | |
238 | mask &= movemask(tNear <= vfloat<M>(ray.tfar)); |
239 | } |
240 | return false; |
241 | } |
242 | |
243 | template<typename Intersector, typename Epilog> |
244 | static __forceinline void intersect_hn(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& prim) |
245 | { |
246 | vfloat<M> tNear; |
247 | vbool<M> valid = intersect(ray,prim,tNear_o&: tNear); |
248 | |
249 | const size_t N = prim.N; |
250 | size_t mask = movemask(valid); |
251 | while (mask) |
252 | { |
253 | const size_t i = bscf(v&: mask); |
254 | STAT3(normal.trav_prims,1,1,1); |
255 | const unsigned int geomID = prim.geomID(N); |
256 | const unsigned int primID = prim.primID(N)[i]; |
257 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
258 | Vec3ff p0,t0,p1,t1; Vec3fa n0,dn0,n1,dn1; geom->gather_hermite(p0,t0,n0,dn0,p1,t1,n1,dn1,i: geom->curve(i: primID)); |
259 | Intersector().intersect(pre,ray,context,geom,primID,p0,t0,p1,t1,n0,dn0,n1,dn1,Epilog(ray,context,geomID,primID)); |
260 | mask &= movemask(tNear <= vfloat<M>(ray.tfar)); |
261 | } |
262 | } |
263 | |
264 | template<typename Intersector, typename Epilog> |
265 | static __forceinline bool occluded_hn(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim) |
266 | { |
267 | vfloat<M> tNear; |
268 | vbool<M> valid = intersect(ray,prim,tNear_o&: tNear); |
269 | |
270 | const size_t N = prim.N; |
271 | size_t mask = movemask(valid); |
272 | while (mask) |
273 | { |
274 | const size_t i = bscf(v&: mask); |
275 | STAT3(shadow.trav_prims,1,1,1); |
276 | const unsigned int geomID = prim.geomID(N); |
277 | const unsigned int primID = prim.primID(N)[i]; |
278 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
279 | Vec3ff p0,t0,p1,t1; Vec3fa n0,dn0,n1,dn1; geom->gather_hermite(p0,t0,n0,dn0,p1,t1,n1,dn1,i: geom->curve(i: primID)); |
280 | if (Intersector().intersect(pre,ray,context,geom,primID,p0,t0,p1,t1,n0,dn0,n1,dn1,Epilog(ray,context,geomID,primID))) |
281 | return true; |
282 | |
283 | mask &= movemask(tNear <= vfloat<M>(ray.tfar)); |
284 | } |
285 | return false; |
286 | } |
287 | }; |
288 | |
289 | template<int M, int K> |
290 | struct CurveNiIntersectorK |
291 | { |
292 | typedef CurveNi<M> Primitive; |
293 | typedef Vec3vf<M> Vec3vfM; |
294 | typedef LinearSpace3<Vec3vfM>LinearSpace3vfM; |
295 | typedef CurvePrecalculationsK<K> Precalculations; |
296 | |
297 | static __forceinline vbool<M> intersect(RayK<K>& ray, const size_t k, const Primitive& prim, vfloat<M>& tNear_o) |
298 | { |
299 | const size_t N = prim.N; |
300 | const vfloat4 offset_scale = vfloat4::loadu(prim.offset(N)); |
301 | const Vec3fa offset = Vec3fa(offset_scale); |
302 | const Vec3fa scale = Vec3fa(shuffle<3,3,3,3>(v: offset_scale)); |
303 | |
304 | const Vec3fa ray_org(ray.org.x[k],ray.org.y[k],ray.org.z[k]); |
305 | const Vec3fa ray_dir(ray.dir.x[k],ray.dir.y[k],ray.dir.z[k]); |
306 | const Vec3fa org1 = (ray_org-offset)*scale; |
307 | const Vec3fa dir1 = ray_dir*scale; |
308 | |
309 | const LinearSpace3vfM space(vfloat<M>::load(prim.bounds_vx_x(N)), vfloat<M>::load(prim.bounds_vx_y(N)), vfloat<M>::load(prim.bounds_vx_z(N)), |
310 | vfloat<M>::load(prim.bounds_vy_x(N)), vfloat<M>::load(prim.bounds_vy_y(N)), vfloat<M>::load(prim.bounds_vy_z(N)), |
311 | vfloat<M>::load(prim.bounds_vz_x(N)), vfloat<M>::load(prim.bounds_vz_y(N)), vfloat<M>::load(prim.bounds_vz_z(N))); |
312 | |
313 | const Vec3vfM dir2 = xfmVector(space,Vec3vfM(dir1)); |
314 | const Vec3vfM org2 = xfmPoint (space,Vec3vfM(org1)); |
315 | const Vec3vfM rcp_dir2 = rcp_safe(dir2); |
316 | |
317 | const vfloat<M> t_lower_x = (vfloat<M>::load(prim.bounds_vx_lower(N))-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x); |
318 | const vfloat<M> t_upper_x = (vfloat<M>::load(prim.bounds_vx_upper(N))-vfloat<M>(org2.x))*vfloat<M>(rcp_dir2.x); |
319 | const vfloat<M> t_lower_y = (vfloat<M>::load(prim.bounds_vy_lower(N))-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y); |
320 | const vfloat<M> t_upper_y = (vfloat<M>::load(prim.bounds_vy_upper(N))-vfloat<M>(org2.y))*vfloat<M>(rcp_dir2.y); |
321 | const vfloat<M> t_lower_z = (vfloat<M>::load(prim.bounds_vz_lower(N))-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z); |
322 | const vfloat<M> t_upper_z = (vfloat<M>::load(prim.bounds_vz_upper(N))-vfloat<M>(org2.z))*vfloat<M>(rcp_dir2.z); |
323 | |
324 | const vfloat<M> round_up (1.0f+3.0f*float(ulp)); |
325 | const vfloat<M> round_down(1.0f-3.0f*float(ulp)); |
326 | const vfloat<M> tNear = round_down*max(mini(t_lower_x,t_upper_x),mini(t_lower_y,t_upper_y),mini(t_lower_z,t_upper_z),vfloat<M>(ray.tnear()[k])); |
327 | const vfloat<M> tFar = round_up *min(maxi(t_lower_x,t_upper_x),maxi(t_lower_y,t_upper_y),maxi(t_lower_z,t_upper_z),vfloat<M>(ray.tfar[k])); |
328 | tNear_o = tNear; |
329 | return (vint<M>(step) < vint<M>(prim.N)) & (tNear <= tFar); |
330 | } |
331 | |
332 | template<typename Intersector, typename Epilog> |
333 | static __forceinline void intersect_t(Precalculations& pre, RayHitK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim) |
334 | { |
335 | vfloat<M> tNear; |
336 | vbool<M> valid = intersect(ray,k,prim,tNear_o&: tNear); |
337 | |
338 | const size_t N = prim.N; |
339 | size_t mask = movemask(valid); |
340 | while (mask) |
341 | { |
342 | const size_t i = bscf(v&: mask); |
343 | STAT3(normal.trav_prims,1,1,1); |
344 | const unsigned int geomID = prim.geomID(N); |
345 | const unsigned int primID = prim.primID(N)[i]; |
346 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
347 | Vec3ff a0,a1,a2,a3; geom->gather(p0&: a0,p1&: a1,p2&: a2,p3&: a3,i: geom->curve(i: primID)); |
348 | |
349 | size_t mask1 = mask; |
350 | const size_t i1 = bscf(v&: mask1); |
351 | if (mask) { |
352 | const unsigned int primID1 = prim.primID(N)[i1]; |
353 | geom->prefetchL1_vertices(i: geom->curve(i: primID1)); |
354 | if (mask1) { |
355 | const size_t i2 = bsf(v: mask1); |
356 | const unsigned int primID2 = prim.primID(N)[i2]; |
357 | geom->prefetchL2_vertices(i: geom->curve(i: primID2)); |
358 | } |
359 | } |
360 | |
361 | Intersector().intersect(pre,ray,k,context,geom,primID,a0,a1,a2,a3,Epilog(ray,k,context,geomID,primID)); |
362 | mask &= movemask(tNear <= vfloat<M>(ray.tfar[k])); |
363 | } |
364 | } |
365 | |
366 | template<typename Intersector, typename Epilog> |
367 | static __forceinline bool occluded_t(Precalculations& pre, RayK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim) |
368 | { |
369 | vfloat<M> tNear; |
370 | vbool<M> valid = intersect(ray,k,prim,tNear_o&: tNear); |
371 | |
372 | const size_t N = prim.N; |
373 | size_t mask = movemask(valid); |
374 | while (mask) |
375 | { |
376 | const size_t i = bscf(v&: mask); |
377 | STAT3(shadow.trav_prims,1,1,1); |
378 | const unsigned int geomID = prim.geomID(N); |
379 | const unsigned int primID = prim.primID(N)[i]; |
380 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
381 | Vec3ff a0,a1,a2,a3; geom->gather(p0&: a0,p1&: a1,p2&: a2,p3&: a3,i: geom->curve(i: primID)); |
382 | |
383 | size_t mask1 = mask; |
384 | const size_t i1 = bscf(v&: mask1); |
385 | if (mask) { |
386 | const unsigned int primID1 = prim.primID(N)[i1]; |
387 | geom->prefetchL1_vertices(i: geom->curve(i: primID1)); |
388 | if (mask1) { |
389 | const size_t i2 = bsf(v: mask1); |
390 | const unsigned int primID2 = prim.primID(N)[i2]; |
391 | geom->prefetchL2_vertices(i: geom->curve(i: primID2)); |
392 | } |
393 | } |
394 | |
395 | if (Intersector().intersect(pre,ray,k,context,geom,primID,a0,a1,a2,a3,Epilog(ray,k,context,geomID,primID))) |
396 | return true; |
397 | |
398 | mask &= movemask(tNear <= vfloat<M>(ray.tfar[k])); |
399 | } |
400 | return false; |
401 | } |
402 | |
403 | template<typename Intersector, typename Epilog> |
404 | static __forceinline void intersect_n(Precalculations& pre, RayHitK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim) |
405 | { |
406 | vfloat<M> tNear; |
407 | vbool<M> valid = intersect(ray,k,prim,tNear_o&: tNear); |
408 | |
409 | const size_t N = prim.N; |
410 | size_t mask = movemask(valid); |
411 | while (mask) |
412 | { |
413 | const size_t i = bscf(v&: mask); |
414 | STAT3(normal.trav_prims,1,1,1); |
415 | const unsigned int geomID = prim.geomID(N); |
416 | const unsigned int primID = prim.primID(N)[i]; |
417 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
418 | |
419 | unsigned int vertexID = geom->curve(i: primID); |
420 | Vec3ff a0,a1,a2,a3; Vec3fa n0,n1,n2,n3; geom->gather(p0&: a0,p1&: a1,p2&: a2,p3&: a3,n0,n1,n2,n3,i: vertexID); |
421 | |
422 | size_t mask1 = mask; |
423 | const size_t i1 = bscf(v&: mask1); |
424 | if (mask) { |
425 | const unsigned int primID1 = prim.primID(N)[i1]; |
426 | geom->prefetchL1_vertices(i: geom->curve(i: primID1)); |
427 | if (mask1) { |
428 | const size_t i2 = bsf(v: mask1); |
429 | const unsigned int primID2 = prim.primID(N)[i2]; |
430 | geom->prefetchL2_vertices(i: geom->curve(i: primID2)); |
431 | } |
432 | } |
433 | |
434 | Intersector().intersect(pre,ray,k,context,geom,primID,a0,a1,a2,a3,n0,n1,n2,n3,Epilog(ray,k,context,geomID,primID)); |
435 | mask &= movemask(tNear <= vfloat<M>(ray.tfar[k])); |
436 | } |
437 | } |
438 | |
439 | template<typename Intersector, typename Epilog> |
440 | static __forceinline bool occluded_n(Precalculations& pre, RayK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim) |
441 | { |
442 | vfloat<M> tNear; |
443 | vbool<M> valid = intersect(ray,k,prim,tNear_o&: tNear); |
444 | |
445 | const size_t N = prim.N; |
446 | size_t mask = movemask(valid); |
447 | while (mask) |
448 | { |
449 | const size_t i = bscf(v&: mask); |
450 | STAT3(shadow.trav_prims,1,1,1); |
451 | const unsigned int geomID = prim.geomID(N); |
452 | const unsigned int primID = prim.primID(N)[i]; |
453 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
454 | |
455 | unsigned int vertexID = geom->curve(i: primID); |
456 | Vec3ff a0,a1,a2,a3; Vec3fa n0,n1,n2,n3; geom->gather(p0&: a0,p1&: a1,p2&: a2,p3&: a3,n0,n1,n2,n3,i: vertexID); |
457 | |
458 | size_t mask1 = mask; |
459 | const size_t i1 = bscf(v&: mask1); |
460 | if (mask) { |
461 | const unsigned int primID1 = prim.primID(N)[i1]; |
462 | geom->prefetchL1_vertices(i: geom->curve(i: primID1)); |
463 | if (mask1) { |
464 | const size_t i2 = bsf(v: mask1); |
465 | const unsigned int primID2 = prim.primID(N)[i2]; |
466 | geom->prefetchL2_vertices(i: geom->curve(i: primID2)); |
467 | } |
468 | } |
469 | |
470 | if (Intersector().intersect(pre,ray,k,context,geom,primID,a0,a1,a2,a3,n0,n1,n2,n3,Epilog(ray,k,context,geomID,primID))) |
471 | return true; |
472 | |
473 | mask &= movemask(tNear <= vfloat<M>(ray.tfar[k])); |
474 | } |
475 | return false; |
476 | } |
477 | |
478 | template<typename Intersector, typename Epilog> |
479 | static __forceinline void intersect_h(Precalculations& pre, RayHitK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim) |
480 | { |
481 | vfloat<M> tNear; |
482 | vbool<M> valid = intersect(ray,k,prim,tNear_o&: tNear); |
483 | |
484 | const size_t N = prim.N; |
485 | size_t mask = movemask(valid); |
486 | while (mask) |
487 | { |
488 | const size_t i = bscf(v&: mask); |
489 | STAT3(normal.trav_prims,1,1,1); |
490 | const unsigned int geomID = prim.geomID(N); |
491 | const unsigned int primID = prim.primID(N)[i]; |
492 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
493 | Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,i: geom->curve(i: primID)); |
494 | Intersector().intersect(pre,ray,k,context,geom,primID,p0,t0,p1,t1,Epilog(ray,k,context,geomID,primID)); |
495 | mask &= movemask(tNear <= vfloat<M>(ray.tfar[k])); |
496 | } |
497 | } |
498 | |
499 | template<typename Intersector, typename Epilog> |
500 | static __forceinline bool occluded_h(Precalculations& pre, RayK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim) |
501 | { |
502 | vfloat<M> tNear; |
503 | vbool<M> valid = intersect(ray,k,prim,tNear_o&: tNear); |
504 | |
505 | const size_t N = prim.N; |
506 | size_t mask = movemask(valid); |
507 | while (mask) |
508 | { |
509 | const size_t i = bscf(v&: mask); |
510 | STAT3(shadow.trav_prims,1,1,1); |
511 | const unsigned int geomID = prim.geomID(N); |
512 | const unsigned int primID = prim.primID(N)[i]; |
513 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
514 | Vec3ff p0,t0,p1,t1; geom->gather_hermite(p0,t0,p1,t1,i: geom->curve(i: primID)); |
515 | if (Intersector().intersect(pre,ray,k,context,geom,primID,p0,t0,p1,t1,Epilog(ray,k,context,geomID,primID))) |
516 | return true; |
517 | |
518 | mask &= movemask(tNear <= vfloat<M>(ray.tfar[k])); |
519 | } |
520 | return false; |
521 | } |
522 | |
523 | template<typename Intersector, typename Epilog> |
524 | static __forceinline void intersect_hn(Precalculations& pre, RayHitK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim) |
525 | { |
526 | vfloat<M> tNear; |
527 | vbool<M> valid = intersect(ray,k,prim,tNear_o&: tNear); |
528 | |
529 | const size_t N = prim.N; |
530 | size_t mask = movemask(valid); |
531 | while (mask) |
532 | { |
533 | const size_t i = bscf(v&: mask); |
534 | STAT3(normal.trav_prims,1,1,1); |
535 | const unsigned int geomID = prim.geomID(N); |
536 | const unsigned int primID = prim.primID(N)[i]; |
537 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
538 | Vec3ff p0,t0,p1,t1; Vec3fa n0,dn0,n1,dn1; geom->gather_hermite(p0,t0,n0,dn0,p1,t1,n1,dn1,i: geom->curve(i: primID)); |
539 | Intersector().intersect(pre,ray,k,context,geom,primID,p0,t0,p1,t1,n0,dn0,n1,dn1,Epilog(ray,k,context,geomID,primID)); |
540 | mask &= movemask(tNear <= vfloat<M>(ray.tfar[k])); |
541 | } |
542 | } |
543 | |
544 | template<typename Intersector, typename Epilog> |
545 | static __forceinline bool occluded_hn(Precalculations& pre, RayK<K>& ray, const size_t k, IntersectContext* context, const Primitive& prim) |
546 | { |
547 | vfloat<M> tNear; |
548 | vbool<M> valid = intersect(ray,k,prim,tNear_o&: tNear); |
549 | |
550 | const size_t N = prim.N; |
551 | size_t mask = movemask(valid); |
552 | while (mask) |
553 | { |
554 | const size_t i = bscf(v&: mask); |
555 | STAT3(shadow.trav_prims,1,1,1); |
556 | const unsigned int geomID = prim.geomID(N); |
557 | const unsigned int primID = prim.primID(N)[i]; |
558 | const CurveGeometry* geom = context->scene->get<CurveGeometry>(i: geomID); |
559 | Vec3ff p0,t0,p1,t1; Vec3fa n0,dn0,n1,dn1; geom->gather_hermite(p0,t0,n0,dn0,p1,t1,n1,dn1,i: geom->curve(i: primID)); |
560 | if (Intersector().intersect(pre,ray,k,context,geom,primID,p0,t0,p1,t1,n0,dn0,n1,dn1,Epilog(ray,k,context,geomID,primID))) |
561 | return true; |
562 | |
563 | mask &= movemask(tNear <= vfloat<M>(ray.tfar[k])); |
564 | } |
565 | return false; |
566 | } |
567 | }; |
568 | } |
569 | } |
570 | |