1// Copyright 2009-2021 Intel Corporation
2// SPDX-License-Identifier: Apache-2.0
3
4#pragma once
5
6#include "default.h"
7#include "ray.h"
8#include "point_query.h"
9#include "context.h"
10
11namespace embree
12{
13 class Scene;
14
15 /*! Base class for the acceleration structure data. */
16 class AccelData : public RefCount
17 {
18 ALIGNED_CLASS_(16);
19 public:
20 enum Type { TY_UNKNOWN = 0, TY_ACCELN = 1, TY_ACCEL_INSTANCE = 2, TY_BVH4 = 3, TY_BVH8 = 4 };
21
22 public:
23 AccelData (const Type type)
24 : bounds(empty), type(type) {}
25
26 /*! notifies the acceleration structure about the deletion of some geometry */
27 virtual void deleteGeometry(size_t geomID) {};
28
29 /*! clears the acceleration structure data */
30 virtual void clear() = 0;
31
32 /*! returns normal bounds */
33 __forceinline BBox3fa getBounds() const {
34 return bounds.bounds();
35 }
36
37 /*! returns bounds for some time */
38 __forceinline BBox3fa getBounds(float t) const {
39 return bounds.interpolate(t);
40 }
41
42 /*! returns linear bounds */
43 __forceinline LBBox3fa getLinearBounds() const {
44 return bounds;
45 }
46
47 /*! checks if acceleration structure is empty */
48 __forceinline bool isEmpty() const {
49 return bounds.bounds0.lower.x == float(pos_inf);
50 }
51
52 public:
53 LBBox3fa bounds; // linear bounds
54 Type type;
55 };
56
57 /*! Base class for all intersectable and buildable acceleration structures. */
58 class Accel : public AccelData
59 {
60 ALIGNED_CLASS_(16);
61 public:
62
63 struct Intersectors;
64
65 /*! Type of collide function */
66 typedef void (*CollideFunc)(void* bvh0, void* bvh1, RTCCollideFunc callback, void* userPtr);
67
68 /*! Type of point query function */
69 typedef bool(*PointQueryFunc)(Intersectors* This, /*!< this pointer to accel */
70 PointQuery* query, /*!< point query for lookup */
71 PointQueryContext* context); /*!< point query context */
72
73 /*! Type of intersect function pointer for single rays. */
74 typedef void (*IntersectFunc)(Intersectors* This, /*!< this pointer to accel */
75 RTCRayHit& ray, /*!< ray to intersect */
76 IntersectContext* context);
77
78 /*! Type of intersect function pointer for ray packets of size 4. */
79 typedef void (*IntersectFunc4)(const void* valid, /*!< pointer to valid mask */
80 Intersectors* This, /*!< this pointer to accel */
81 RTCRayHit4& ray, /*!< ray packet to intersect */
82 IntersectContext* context);
83
84 /*! Type of intersect function pointer for ray packets of size 8. */
85 typedef void (*IntersectFunc8)(const void* valid, /*!< pointer to valid mask */
86 Intersectors* This, /*!< this pointer to accel */
87 RTCRayHit8& ray, /*!< ray packet to intersect */
88 IntersectContext* context);
89
90 /*! Type of intersect function pointer for ray packets of size 16. */
91 typedef void (*IntersectFunc16)(const void* valid, /*!< pointer to valid mask */
92 Intersectors* This, /*!< this pointer to accel */
93 RTCRayHit16& ray, /*!< ray packet to intersect */
94 IntersectContext* context);
95
96 /*! Type of intersect function pointer for ray packets of size N. */
97 typedef void (*IntersectFuncN)(Intersectors* This, /*!< this pointer to accel */
98 RTCRayHitN** ray, /*!< ray stream to intersect */
99 const size_t N, /*!< number of rays in stream */
100 IntersectContext* context /*!< layout flags */);
101
102
103 /*! Type of occlusion function pointer for single rays. */
104 typedef void (*OccludedFunc) (Intersectors* This, /*!< this pointer to accel */
105 RTCRay& ray, /*!< ray to test occlusion */
106 IntersectContext* context);
107
108 /*! Type of occlusion function pointer for ray packets of size 4. */
109 typedef void (*OccludedFunc4) (const void* valid, /*!< pointer to valid mask */
110 Intersectors* This, /*!< this pointer to accel */
111 RTCRay4& ray, /*!< ray packet to test occlusion. */
112 IntersectContext* context);
113
114 /*! Type of occlusion function pointer for ray packets of size 8. */
115 typedef void (*OccludedFunc8) (const void* valid, /*!< pointer to valid mask */
116 Intersectors* This, /*!< this pointer to accel */
117 RTCRay8& ray, /*!< ray packet to test occlusion. */
118 IntersectContext* context);
119
120 /*! Type of occlusion function pointer for ray packets of size 16. */
121 typedef void (*OccludedFunc16) (const void* valid, /*!< pointer to valid mask */
122 Intersectors* This, /*!< this pointer to accel */
123 RTCRay16& ray, /*!< ray packet to test occlusion. */
124 IntersectContext* context);
125
126 /*! Type of intersect function pointer for ray packets of size N. */
127 typedef void (*OccludedFuncN)(Intersectors* This, /*!< this pointer to accel */
128 RTCRayN** ray, /*!< ray stream to test occlusion */
129 const size_t N, /*!< number of rays in stream */
130 IntersectContext* context /*!< layout flags */);
131 typedef void (*ErrorFunc) ();
132
133 struct Collider
134 {
135 Collider (ErrorFunc error = nullptr)
136 : collide((CollideFunc)error), name(nullptr) {}
137
138 Collider (CollideFunc collide, const char* name)
139 : collide(collide), name(name) {}
140
141 operator bool() const { return name; }
142
143 public:
144 CollideFunc collide;
145 const char* name;
146 };
147
148 struct Intersector1
149 {
150 Intersector1 (ErrorFunc error = nullptr)
151 : intersect((IntersectFunc)error), occluded((OccludedFunc)error), name(nullptr) {}
152
153 Intersector1 (IntersectFunc intersect, OccludedFunc occluded, const char* name)
154 : intersect(intersect), occluded(occluded), pointQuery(nullptr), name(name) {}
155
156 Intersector1 (IntersectFunc intersect, OccludedFunc occluded, PointQueryFunc pointQuery, const char* name)
157 : intersect(intersect), occluded(occluded), pointQuery(pointQuery), name(name) {}
158
159 operator bool() const { return name; }
160
161 public:
162 static const char* type;
163 IntersectFunc intersect;
164 OccludedFunc occluded;
165 PointQueryFunc pointQuery;
166 const char* name;
167 };
168
169 struct Intersector4
170 {
171 Intersector4 (ErrorFunc error = nullptr)
172 : intersect((IntersectFunc4)error), occluded((OccludedFunc4)error), name(nullptr) {}
173
174 Intersector4 (IntersectFunc4 intersect, OccludedFunc4 occluded, const char* name)
175 : intersect(intersect), occluded(occluded), name(name) {}
176
177 operator bool() const { return name; }
178
179 public:
180 static const char* type;
181 IntersectFunc4 intersect;
182 OccludedFunc4 occluded;
183 const char* name;
184 };
185
186 struct Intersector8
187 {
188 Intersector8 (ErrorFunc error = nullptr)
189 : intersect((IntersectFunc8)error), occluded((OccludedFunc8)error), name(nullptr) {}
190
191 Intersector8 (IntersectFunc8 intersect, OccludedFunc8 occluded, const char* name)
192 : intersect(intersect), occluded(occluded), name(name) {}
193
194 operator bool() const { return name; }
195
196 public:
197 static const char* type;
198 IntersectFunc8 intersect;
199 OccludedFunc8 occluded;
200 const char* name;
201 };
202
203 struct Intersector16
204 {
205 Intersector16 (ErrorFunc error = nullptr)
206 : intersect((IntersectFunc16)error), occluded((OccludedFunc16)error), name(nullptr) {}
207
208 Intersector16 (IntersectFunc16 intersect, OccludedFunc16 occluded, const char* name)
209 : intersect(intersect), occluded(occluded), name(name) {}
210
211 operator bool() const { return name; }
212
213 public:
214 static const char* type;
215 IntersectFunc16 intersect;
216 OccludedFunc16 occluded;
217 const char* name;
218 };
219
220 struct IntersectorN
221 {
222 IntersectorN (ErrorFunc error = nullptr)
223 : intersect((IntersectFuncN)error), occluded((OccludedFuncN)error), name(nullptr) {}
224
225 IntersectorN (IntersectFuncN intersect, OccludedFuncN occluded, const char* name)
226 : intersect(intersect), occluded(occluded), name(name) {}
227
228 operator bool() const { return name; }
229
230 public:
231 static const char* type;
232 IntersectFuncN intersect;
233 OccludedFuncN occluded;
234 const char* name;
235 };
236
237 struct Intersectors
238 {
239 Intersectors()
240 : ptr(nullptr), leafIntersector(nullptr), collider(nullptr), intersector1(nullptr), intersector4(nullptr), intersector8(nullptr), intersector16(nullptr), intersectorN(nullptr) {}
241
242 Intersectors (ErrorFunc error)
243 : ptr(nullptr), leafIntersector(nullptr), collider(error), intersector1(error), intersector4(error), intersector8(error), intersector16(error), intersectorN(error) {}
244
245 void print(size_t ident)
246 {
247 if (collider.name) {
248 for (size_t i=0; i<ident; i++) std::cout << " ";
249 std::cout << "collider = " << collider.name << std::endl;
250 }
251 if (intersector1.name) {
252 for (size_t i=0; i<ident; i++) std::cout << " ";
253 std::cout << "intersector1 = " << intersector1.name << std::endl;
254 }
255 if (intersector4.name) {
256 for (size_t i=0; i<ident; i++) std::cout << " ";
257 std::cout << "intersector4 = " << intersector4.name << std::endl;
258 }
259 if (intersector8.name) {
260 for (size_t i=0; i<ident; i++) std::cout << " ";
261 std::cout << "intersector8 = " << intersector8.name << std::endl;
262 }
263 if (intersector16.name) {
264 for (size_t i=0; i<ident; i++) std::cout << " ";
265 std::cout << "intersector16 = " << intersector16.name << std::endl;
266 }
267 if (intersectorN.name) {
268 for (size_t i=0; i<ident; i++) std::cout << " ";
269 std::cout << "intersectorN = " << intersectorN.name << std::endl;
270 }
271 }
272
273 void select(bool filter)
274 {
275 if (intersector4_filter) {
276 if (filter) intersector4 = intersector4_filter;
277 else intersector4 = intersector4_nofilter;
278 }
279 if (intersector8_filter) {
280 if (filter) intersector8 = intersector8_filter;
281 else intersector8 = intersector8_nofilter;
282 }
283 if (intersector16_filter) {
284 if (filter) intersector16 = intersector16_filter;
285 else intersector16 = intersector16_nofilter;
286 }
287 if (intersectorN_filter) {
288 if (filter) intersectorN = intersectorN_filter;
289 else intersectorN = intersectorN_nofilter;
290 }
291 }
292
293 __forceinline bool pointQuery (PointQuery* query, PointQueryContext* context) {
294 assert(intersector1.pointQuery);
295 return intersector1.pointQuery(this,query,context);
296 }
297
298 /*! collides two scenes */
299 __forceinline void collide (Accel* scene0, Accel* scene1, RTCCollideFunc callback, void* userPtr) {
300 assert(collider.collide);
301 collider.collide(scene0->intersectors.ptr,scene1->intersectors.ptr,callback,userPtr);
302 }
303
304 /*! Intersects a single ray with the scene. */
305 __forceinline void intersect (RTCRayHit& ray, IntersectContext* context) {
306 assert(intersector1.intersect);
307 intersector1.intersect(this,ray,context);
308 }
309
310 /*! Intersects a packet of 4 rays with the scene. */
311 __forceinline void intersect4 (const void* valid, RTCRayHit4& ray, IntersectContext* context) {
312 assert(intersector4.intersect);
313 intersector4.intersect(valid,this,ray,context);
314 }
315
316 /*! Intersects a packet of 8 rays with the scene. */
317 __forceinline void intersect8 (const void* valid, RTCRayHit8& ray, IntersectContext* context) {
318 assert(intersector8.intersect);
319 intersector8.intersect(valid,this,ray,context);
320 }
321
322 /*! Intersects a packet of 16 rays with the scene. */
323 __forceinline void intersect16 (const void* valid, RTCRayHit16& ray, IntersectContext* context) {
324 assert(intersector16.intersect);
325 intersector16.intersect(valid,this,ray,context);
326 }
327
328 /*! Intersects a stream of N rays in SOA layout with the scene. */
329 __forceinline void intersectN (RTCRayHitN** rayN, const size_t N, IntersectContext* context)
330 {
331 assert(intersectorN.intersect);
332 intersectorN.intersect(this,rayN,N,context);
333 }
334
335#if defined(__SSE__) || defined(__ARM_NEON)
336 __forceinline void intersect(const vbool4& valid, RayHitK<4>& ray, IntersectContext* context) {
337 const vint<4> mask = valid.mask32();
338 intersect4(&mask,(RTCRayHit4&)ray,context);
339 }
340#endif
341#if defined(__AVX__)
342 __forceinline void intersect(const vbool8& valid, RayHitK<8>& ray, IntersectContext* context) {
343 const vint<8> mask = valid.mask32();
344 intersect8(&mask,(RTCRayHit8&)ray,context);
345 }
346#endif
347#if defined(__AVX512F__)
348 __forceinline void intersect(const vbool16& valid, RayHitK<16>& ray, IntersectContext* context) {
349 const vint<16> mask = valid.mask32();
350 intersect16(&mask,(RTCRayHit16&)ray,context);
351 }
352#endif
353
354 template<int K>
355 __forceinline void intersectN (RayHitK<K>** rayN, const size_t N, IntersectContext* context)
356 {
357 intersectN((RTCRayHitN**)rayN,N,context);
358 }
359
360 /*! Tests if single ray is occluded by the scene. */
361 __forceinline void occluded (RTCRay& ray, IntersectContext* context) {
362 assert(intersector1.occluded);
363 intersector1.occluded(this,ray,context);
364 }
365
366 /*! Tests if a packet of 4 rays is occluded by the scene. */
367 __forceinline void occluded4 (const void* valid, RTCRay4& ray, IntersectContext* context) {
368 assert(intersector4.occluded);
369 intersector4.occluded(valid,this,ray,context);
370 }
371
372 /*! Tests if a packet of 8 rays is occluded by the scene. */
373 __forceinline void occluded8 (const void* valid, RTCRay8& ray, IntersectContext* context) {
374 assert(intersector8.occluded);
375 intersector8.occluded(valid,this,ray,context);
376 }
377
378 /*! Tests if a packet of 16 rays is occluded by the scene. */
379 __forceinline void occluded16 (const void* valid, RTCRay16& ray, IntersectContext* context) {
380 assert(intersector16.occluded);
381 intersector16.occluded(valid,this,ray,context);
382 }
383
384 /*! Tests if a stream of N rays in SOA layout is occluded by the scene. */
385 __forceinline void occludedN (RTCRayN** rayN, const size_t N, IntersectContext* context)
386 {
387 assert(intersectorN.occluded);
388 intersectorN.occluded(this,rayN,N,context);
389 }
390
391#if defined(__SSE__) || defined(__ARM_NEON)
392 __forceinline void occluded(const vbool4& valid, RayK<4>& ray, IntersectContext* context) {
393 const vint<4> mask = valid.mask32();
394 occluded4(&mask,(RTCRay4&)ray,context);
395 }
396#endif
397#if defined(__AVX__)
398 __forceinline void occluded(const vbool8& valid, RayK<8>& ray, IntersectContext* context) {
399 const vint<8> mask = valid.mask32();
400 occluded8(&mask,(RTCRay8&)ray,context);
401 }
402#endif
403#if defined(__AVX512F__)
404 __forceinline void occluded(const vbool16& valid, RayK<16>& ray, IntersectContext* context) {
405 const vint<16> mask = valid.mask32();
406 occluded16(&mask,(RTCRay16&)ray,context);
407 }
408#endif
409
410 template<int K>
411 __forceinline void occludedN (RayK<K>** rayN, const size_t N, IntersectContext* context)
412 {
413 occludedN((RTCRayN**)rayN,N,context);
414 }
415
416 /*! Tests if single ray is occluded by the scene. */
417 __forceinline void intersect(RTCRay& ray, IntersectContext* context) {
418 occluded(ray, context);
419 }
420
421 /*! Tests if a packet of K rays is occluded by the scene. */
422 template<int K>
423 __forceinline void intersect(const vbool<K>& valid, RayK<K>& ray, IntersectContext* context) {
424 occluded(valid, ray, context);
425 }
426
427 /*! Tests if a packet of N rays in SOA layout is occluded by the scene. */
428 template<int K>
429 __forceinline void intersectN(RayK<K>** rayN, const size_t N, IntersectContext* context) {
430 occludedN(rayN, N, context);
431 }
432
433 public:
434 AccelData* ptr;
435 void* leafIntersector;
436 Collider collider;
437 Intersector1 intersector1;
438 Intersector4 intersector4;
439 Intersector4 intersector4_filter;
440 Intersector4 intersector4_nofilter;
441 Intersector8 intersector8;
442 Intersector8 intersector8_filter;
443 Intersector8 intersector8_nofilter;
444 Intersector16 intersector16;
445 Intersector16 intersector16_filter;
446 Intersector16 intersector16_nofilter;
447 IntersectorN intersectorN;
448 IntersectorN intersectorN_filter;
449 IntersectorN intersectorN_nofilter;
450 };
451
452 public:
453
454 /*! Construction */
455 Accel (const AccelData::Type type)
456 : AccelData(type) {}
457
458 /*! Construction */
459 Accel (const AccelData::Type type, const Intersectors& intersectors)
460 : AccelData(type), intersectors(intersectors) {}
461
462 /*! Virtual destructor */
463 virtual ~Accel() {}
464
465 /*! makes the acceleration structure immutable */
466 virtual void immutable () {}
467
468 /*! build acceleration structure */
469 virtual void build () = 0;
470
471 public:
472 Intersectors intersectors;
473 };
474
475#define DEFINE_COLLIDER(symbol,collider) \
476 Accel::Collider symbol() { \
477 return Accel::Collider((Accel::CollideFunc)collider::collide, \
478 TOSTRING(isa) "::" TOSTRING(symbol)); \
479 }
480
481#define DEFINE_INTERSECTOR1(symbol,intersector) \
482 Accel::Intersector1 symbol() { \
483 return Accel::Intersector1((Accel::IntersectFunc )intersector::intersect, \
484 (Accel::OccludedFunc )intersector::occluded, \
485 (Accel::PointQueryFunc)intersector::pointQuery,\
486 TOSTRING(isa) "::" TOSTRING(symbol)); \
487 }
488
489#define DEFINE_INTERSECTOR4(symbol,intersector) \
490 Accel::Intersector4 symbol() { \
491 return Accel::Intersector4((Accel::IntersectFunc4)intersector::intersect, \
492 (Accel::OccludedFunc4)intersector::occluded, \
493 TOSTRING(isa) "::" TOSTRING(symbol)); \
494 }
495
496#define DEFINE_INTERSECTOR8(symbol,intersector) \
497 Accel::Intersector8 symbol() { \
498 return Accel::Intersector8((Accel::IntersectFunc8)intersector::intersect, \
499 (Accel::OccludedFunc8)intersector::occluded, \
500 TOSTRING(isa) "::" TOSTRING(symbol)); \
501 }
502
503#define DEFINE_INTERSECTOR16(symbol,intersector) \
504 Accel::Intersector16 symbol() { \
505 return Accel::Intersector16((Accel::IntersectFunc16)intersector::intersect, \
506 (Accel::OccludedFunc16)intersector::occluded, \
507 TOSTRING(isa) "::" TOSTRING(symbol)); \
508 }
509
510#define DEFINE_INTERSECTORN(symbol,intersector) \
511 Accel::IntersectorN symbol() { \
512 return Accel::IntersectorN((Accel::IntersectFuncN)intersector::intersect, \
513 (Accel::OccludedFuncN)intersector::occluded, \
514 TOSTRING(isa) "::" TOSTRING(symbol)); \
515 }
516
517 /* ray stream filter interface */
518 typedef void (*intersectStreamAOS_func)(Scene* scene, RTCRayHit* _rayN, const size_t N, const size_t stride, IntersectContext* context);
519 typedef void (*intersectStreamAOP_func)(Scene* scene, RTCRayHit** _rayN, const size_t N, IntersectContext* context);
520 typedef void (*intersectStreamSOA_func)(Scene* scene, char* rayN, const size_t N, const size_t streams, const size_t stream_offset, IntersectContext* context);
521 typedef void (*intersectStreamSOP_func)(Scene* scene, const RTCRayHitNp* rayN, const size_t N, IntersectContext* context);
522
523 typedef void (*occludedStreamAOS_func)(Scene* scene, RTCRay* _rayN, const size_t N, const size_t stride, IntersectContext* context);
524 typedef void (*occludedStreamAOP_func)(Scene* scene, RTCRay** _rayN, const size_t N, IntersectContext* context);
525 typedef void (*occludedStreamSOA_func)(Scene* scene, char* rayN, const size_t N, const size_t streams, const size_t stream_offset, IntersectContext* context);
526 typedef void (*occludedStreamSOP_func)(Scene* scene, const RTCRayNp* rayN, const size_t N, IntersectContext* context);
527
528 struct RayStreamFilterFuncs
529 {
530 RayStreamFilterFuncs()
531 : intersectAOS(nullptr), intersectAOP(nullptr), intersectSOA(nullptr), intersectSOP(nullptr),
532 occludedAOS(nullptr), occludedAOP(nullptr), occludedSOA(nullptr), occludedSOP(nullptr) {}
533
534 RayStreamFilterFuncs(void (*ptr) ())
535 : intersectAOS((intersectStreamAOS_func) ptr), intersectAOP((intersectStreamAOP_func) ptr), intersectSOA((intersectStreamSOA_func) ptr), intersectSOP((intersectStreamSOP_func) ptr),
536 occludedAOS((occludedStreamAOS_func) ptr), occludedAOP((occludedStreamAOP_func) ptr), occludedSOA((occludedStreamSOA_func) ptr), occludedSOP((occludedStreamSOP_func) ptr) {}
537
538 RayStreamFilterFuncs(intersectStreamAOS_func intersectAOS, intersectStreamAOP_func intersectAOP, intersectStreamSOA_func intersectSOA, intersectStreamSOP_func intersectSOP,
539 occludedStreamAOS_func occludedAOS, occludedStreamAOP_func occludedAOP, occludedStreamSOA_func occludedSOA, occludedStreamSOP_func occludedSOP)
540 : intersectAOS(intersectAOS), intersectAOP(intersectAOP), intersectSOA(intersectSOA), intersectSOP(intersectSOP),
541 occludedAOS(occludedAOS), occludedAOP(occludedAOP), occludedSOA(occludedSOA), occludedSOP(occludedSOP) {}
542
543 public:
544 intersectStreamAOS_func intersectAOS;
545 intersectStreamAOP_func intersectAOP;
546 intersectStreamSOA_func intersectSOA;
547 intersectStreamSOP_func intersectSOP;
548
549 occludedStreamAOS_func occludedAOS;
550 occludedStreamAOP_func occludedAOP;
551 occludedStreamSOA_func occludedSOA;
552 occludedStreamSOP_func occludedSOP;
553 };
554
555 typedef RayStreamFilterFuncs (*RayStreamFilterFuncsType)();
556}
557