accelset.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. // ======================================================================== //
  2. // Copyright 2009-2017 Intel Corporation //
  3. // //
  4. // Licensed under the Apache License, Version 2.0 (the "License"); //
  5. // you may not use this file except in compliance with the License. //
  6. // You may obtain a copy of the License at //
  7. // //
  8. // http://www.apache.org/licenses/LICENSE-2.0 //
  9. // //
  10. // Unless required by applicable law or agreed to in writing, software //
  11. // distributed under the License is distributed on an "AS IS" BASIS, //
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
  13. // See the License for the specific language governing permissions and //
  14. // limitations under the License. //
  15. // ======================================================================== //
  16. #pragma once
  17. #include "default.h"
  18. #include "builder.h"
  19. #include "geometry.h"
  20. #include "ray.h"
  21. namespace embree
  22. {
  23. /*! Base class for set of acceleration structures. */
  24. class AccelSet : public Geometry
  25. {
  26. ALIGNED_CLASS;
  27. public:
  28. /*! type of this geometry */
  29. static const Geometry::Type geom_type = Geometry::USER_GEOMETRY;
  30. typedef RTCIntersectFunc IntersectFunc;
  31. typedef RTCIntersectFunc4 IntersectFunc4;
  32. typedef RTCIntersectFunc8 IntersectFunc8;
  33. typedef RTCIntersectFunc16 IntersectFunc16;
  34. typedef RTCIntersectFunc1Mp IntersectFunc1M;
  35. typedef RTCIntersectFuncN IntersectFuncN;
  36. typedef RTCOccludedFunc OccludedFunc;
  37. typedef RTCOccludedFunc4 OccludedFunc4;
  38. typedef RTCOccludedFunc8 OccludedFunc8;
  39. typedef RTCOccludedFunc16 OccludedFunc16;
  40. typedef RTCOccludedFunc1Mp OccludedFunc1M;
  41. typedef RTCOccludedFuncN OccludedFuncN;
  42. #if defined(__SSE__)
  43. typedef void (*ISPCIntersectFunc4)(void* ptr, RTCRay4& ray, size_t item, __m128i valid);
  44. typedef void (*ISPCOccludedFunc4 )(void* ptr, RTCRay4& ray, size_t item, __m128i valid);
  45. #endif
  46. #if defined(__AVX__)
  47. typedef void (*ISPCIntersectFunc8)(void* ptr, RTCRay8& ray, size_t item, __m256i valid);
  48. typedef void (*ISPCOccludedFunc8 )(void* ptr, RTCRay8& ray, size_t item, __m256i valid);
  49. #endif
  50. #if defined(__AVX512F__)
  51. typedef void (*ISPCIntersectFunc16)(void* ptr, RTCRay16& ray, size_t item, __m128i valid); // mask gets passed as 16 bytes
  52. typedef void (*ISPCOccludedFunc16 )(void* ptr, RTCRay16& ray, size_t item, __m128i valid); // mask gets passed as 16 bytes
  53. #endif
  54. typedef void (*ErrorFunc) ();
  55. struct Intersector1
  56. {
  57. Intersector1 (ErrorFunc error = nullptr);
  58. Intersector1 (IntersectFunc intersect, OccludedFunc occluded, const char* name);
  59. operator bool() const { return name; }
  60. public:
  61. static const char* type;
  62. IntersectFunc intersect;
  63. OccludedFunc occluded;
  64. const char* name;
  65. };
  66. struct Intersector4
  67. {
  68. Intersector4 (ErrorFunc error = nullptr);
  69. Intersector4 (void* intersect, void* occluded, const char* name, bool ispc);
  70. operator bool() const { return name; }
  71. public:
  72. static const char* type;
  73. void* intersect;
  74. void* occluded;
  75. const char* name;
  76. bool ispc;
  77. };
  78. struct Intersector8
  79. {
  80. Intersector8 (ErrorFunc error = nullptr);
  81. Intersector8 (void* intersect, void* occluded, const char* name, bool ispc);
  82. operator bool() const { return name; }
  83. public:
  84. static const char* type;
  85. void* intersect;
  86. void* occluded;
  87. const char* name;
  88. bool ispc;
  89. };
  90. struct Intersector16
  91. {
  92. Intersector16 (ErrorFunc error = nullptr);
  93. Intersector16 (void* intersect, void* occluded, const char* name, bool ispc);
  94. operator bool() const { return name; }
  95. public:
  96. static const char* type;
  97. void* intersect;
  98. void* occluded;
  99. const char* name;
  100. bool ispc;
  101. };
  102. struct Intersector1M
  103. {
  104. Intersector1M (ErrorFunc error = nullptr);
  105. Intersector1M (IntersectFunc1M intersect, OccludedFunc1M occluded, const char* name);
  106. operator bool() const { return name; }
  107. public:
  108. static const char* type;
  109. IntersectFunc1M intersect;
  110. OccludedFunc1M occluded;
  111. const char* name;
  112. };
  113. struct IntersectorN
  114. {
  115. IntersectorN (ErrorFunc error = nullptr) ;
  116. IntersectorN (IntersectFuncN intersect, OccludedFuncN occluded, const char* name);
  117. operator bool() const { return name; }
  118. public:
  119. static const char* type;
  120. IntersectFuncN intersect;
  121. OccludedFuncN occluded;
  122. const char* name;
  123. };
  124. public:
  125. /*! construction */
  126. AccelSet (Scene* parent, RTCGeometryFlags gflags, size_t items, size_t numTimeSteps);
  127. /*! makes the acceleration structure immutable */
  128. virtual void immutable () {}
  129. /*! build accel */
  130. virtual void build () = 0;
  131. /*! Calculates the bounds of an item */
  132. __forceinline BBox3fa bounds(size_t i, size_t itime = 0) const
  133. {
  134. BBox3fa box[2]; // have to always use 2 boxes as the geometry might have motion blur
  135. assert(i < size());
  136. if (likely(boundsFunc3)) boundsFunc3(boundsFuncUserPtr,intersectors.ptr,i,itime,(RTCBounds&)box[0]);
  137. else if (likely(boundsFunc2)) boundsFunc2(boundsFuncUserPtr,intersectors.ptr,i,(RTCBounds*)box);
  138. else boundsFunc (intersectors.ptr,i,(RTCBounds&)box[0]);
  139. return box[0];
  140. }
  141. /*! calculates the linear bounds of the i'th item at the itime'th time segment */
  142. __forceinline LBBox3fa linearBounds(size_t i, size_t itime) const
  143. {
  144. BBox3fa box[2];
  145. assert(i < size());
  146. if (likely(boundsFunc3)) {
  147. boundsFunc3(boundsFuncUserPtr,intersectors.ptr,i,itime+0,(RTCBounds&)box[0]);
  148. boundsFunc3(boundsFuncUserPtr,intersectors.ptr,i,itime+1,(RTCBounds&)box[1]);
  149. }
  150. else if (likely(boundsFunc2))
  151. boundsFunc2(boundsFuncUserPtr,intersectors.ptr,i,(RTCBounds*)box);
  152. else
  153. boundsFunc(intersectors.ptr,i,(RTCBounds&)box[0]);
  154. return LBBox3fa(box[0],box[1]);
  155. }
  156. /*! calculates the linear bounds of the i'th item at the itimeGlobal'th time segment */
  157. __forceinline LBBox3fa linearBounds(size_t i, size_t itimeGlobal, size_t numTimeStepsGlobal) const
  158. {
  159. return Geometry::linearBounds([&] (size_t itime) { return bounds(i, itime); },
  160. itimeGlobal, numTimeStepsGlobal, numTimeSteps);
  161. }
  162. /*! calculates the build bounds of the i'th item, if it's valid */
  163. __forceinline bool buildBounds(size_t i, BBox3fa* bbox = nullptr) const
  164. {
  165. const BBox3fa b = bounds(i);
  166. if (bbox) *bbox = b;
  167. return isvalid(b);
  168. }
  169. /*! calculates the build bounds of the i'th item at the itime'th time segment, if it's valid */
  170. __forceinline bool buildBounds(size_t i, size_t itime, BBox3fa& bbox) const
  171. {
  172. const BBox3fa bounds0 = bounds(i,itime+0);
  173. const BBox3fa bounds1 = bounds(i,itime+1);
  174. bbox = bounds0; // use bounding box of first timestep to build BVH
  175. return isvalid(bounds0) && isvalid(bounds1);
  176. }
  177. /*! calculates the build bounds of the i'th item at the itimeGlobal'th time segment, if it's valid */
  178. __forceinline bool buildBounds(size_t i, size_t itimeGlobal, size_t numTimeStepsGlobal, BBox3fa& bbox) const
  179. {
  180. return Geometry::buildBounds([&] (size_t itime, BBox3fa& bbox) -> bool
  181. {
  182. bbox = bounds(i, itime);
  183. return isvalid(bbox);
  184. },
  185. itimeGlobal, numTimeStepsGlobal, numTimeSteps, bbox);
  186. }
  187. void enabling ();
  188. void disabling();
  189. public:
  190. /*! Intersects a single ray with the scene. */
  191. __forceinline void intersect (Ray& ray, size_t item, IntersectContext* context)
  192. {
  193. assert(item < size());
  194. if (likely(intersectors.intersector1.intersect)) { // old code for compatibility
  195. intersectors.intersector1.intersect(intersectors.ptr,(RTCRay&)ray,item);
  196. } else if (likely(intersectors.intersector1M.intersect)) {
  197. RTCRay* pray = (RTCRay*)&ray;
  198. intersectors.intersector1M.intersect(intersectors.ptr,context->user,&pray,1,item);
  199. } else {
  200. int mask = -1;
  201. assert(intersectors.intersectorN.intersect);
  202. intersectors.intersectorN.intersect((int*)&mask,intersectors.ptr,context->user,(RTCRayN*)&ray,1,item);
  203. }
  204. }
  205. /*! Intersects a packet of 4 rays with the scene. */
  206. #if defined(__SSE__)
  207. __forceinline void intersect (const vbool4& valid, Ray4& ray, size_t item, IntersectContext* context)
  208. {
  209. assert(item < size());
  210. if (likely(intersectors.intersector4.intersect)) { // old code for compatibility
  211. if (intersectors.intersector4.ispc) {
  212. ((ISPCIntersectFunc4)intersectors.intersector4.intersect)(intersectors.ptr,(RTCRay4&)ray,item,valid.mask32());
  213. } else {
  214. vint4 mask = valid.mask32();
  215. ((IntersectFunc4)intersectors.intersector4.intersect)(&mask,intersectors.ptr,(RTCRay4&)ray,item);
  216. }
  217. } else {
  218. vint4 mask = valid.mask32();
  219. assert(intersectors.intersectorN.intersect);
  220. intersectors.intersectorN.intersect((int*)&mask,intersectors.ptr,context->user,(RTCRayN*)&ray,4,item);
  221. }
  222. }
  223. #endif
  224. #if defined(__AVX__)
  225. /*! Intersects a packet of 8 rays with the scene. */
  226. __forceinline void intersect (const vbool8& valid, Ray8& ray, size_t item, IntersectContext* context)
  227. {
  228. assert(item < size());
  229. if (likely(intersectors.intersector8.intersect)) { // old code for compatibility
  230. if (intersectors.intersector8.ispc) {
  231. ((ISPCIntersectFunc8)intersectors.intersector8.intersect)(intersectors.ptr,(RTCRay8&)ray,item,valid.mask32());
  232. } else {
  233. vint8 mask = valid.mask32();
  234. ((IntersectFunc8)intersectors.intersector8.intersect)(&mask,intersectors.ptr,(RTCRay8&)ray,item);
  235. }
  236. } else {
  237. vint8 mask = valid.mask32();
  238. assert(intersectors.intersectorN.intersect);
  239. intersectors.intersectorN.intersect((int*)&mask,intersectors.ptr,context->user,(RTCRayN*)&ray,8,item);
  240. }
  241. }
  242. #endif
  243. /*! Intersects a packet of 16 rays with the scene. */
  244. #if defined(__AVX512F__)
  245. __forceinline void intersect (const vbool16& valid, Ray16& ray, size_t item, IntersectContext* context)
  246. {
  247. assert(item < size());
  248. if (likely(intersectors.intersector16.intersect)) { // old code for compatibility
  249. if (intersectors.intersector16.ispc) {
  250. ((ISPCIntersectFunc16)intersectors.intersector16.intersect)(intersectors.ptr,(RTCRay16&)ray,item,valid.mask8());
  251. } else {
  252. vint16 mask = valid.mask32();
  253. ((IntersectFunc16)intersectors.intersector16.intersect)(&mask,intersectors.ptr,(RTCRay16&)ray,item);
  254. }
  255. } else {
  256. vint16 mask = valid.mask32();
  257. assert(intersectors.intersectorN.intersect);
  258. intersectors.intersectorN.intersect((int*)&mask,intersectors.ptr,context->user,(RTCRayN*)&ray,16,item);
  259. }
  260. }
  261. #endif
  262. /*! Intersects a stream of rays with the scene. */
  263. __forceinline void intersect1M (Ray** rays, size_t N, size_t item, IntersectContext* context)
  264. {
  265. assert(item < size());
  266. if (intersectors.intersector1M.intersect) { // Intersect1N callback is optional
  267. intersectors.intersector1M.intersect(intersectors.ptr,context->user,(RTCRay**)rays,N,item);
  268. }
  269. else if (N == 1) {
  270. int mask = -1;
  271. assert(intersectors.intersectorN.intersect);
  272. intersectors.intersectorN.intersect((int*)&mask,intersectors.ptr,context->user,(RTCRayN*)rays[0],1,item);
  273. }
  274. else
  275. {
  276. int mask[MAX_INTERNAL_STREAM_SIZE];
  277. StackRayPacket<MAX_INTERNAL_STREAM_SIZE> packet(N);
  278. for (size_t i=0; i<N; i++) packet.writeRay(i,mask,*rays[i]);
  279. assert(intersectors.intersectorN.intersect);
  280. intersectors.intersectorN.intersect(mask,intersectors.ptr,context->user,(RTCRayN*)packet.data,N,item);
  281. for (size_t i=0; i<N; i++) packet.readHit(i,*rays[i]);
  282. }
  283. }
  284. /*! Tests if single ray is occluded by the scene. */
  285. __forceinline void occluded (Ray& ray, size_t item, IntersectContext* context)
  286. {
  287. if (likely(intersectors.intersector1.occluded)) { // old code for compatibility
  288. intersectors.intersector1.occluded(intersectors.ptr,(RTCRay&)ray,item);
  289. } else if (likely(intersectors.intersector1M.occluded)) {
  290. RTCRay* pray = (RTCRay*)&ray;
  291. intersectors.intersector1M.occluded(intersectors.ptr,context->user,&pray,1,item);
  292. } else {
  293. int mask = -1;
  294. assert(intersectors.intersectorN.occluded);
  295. intersectors.intersectorN.occluded((int*)&mask,intersectors.ptr,context->user,(RTCRayN*)&ray,1,item);
  296. }
  297. }
  298. /*! Tests if a packet of 4 rays is occluded by the scene. */
  299. #if defined(__SSE__)
  300. __forceinline void occluded (const vbool4& valid, Ray4& ray, size_t item, IntersectContext* context)
  301. {
  302. assert(item < size());
  303. if (likely(intersectors.intersector4.occluded)) { // old code for compatibility
  304. if (intersectors.intersector4.ispc) {
  305. ((ISPCOccludedFunc4)intersectors.intersector4.occluded)(intersectors.ptr,(RTCRay4&)ray,item,valid.mask32());
  306. } else {
  307. vint4 mask = valid.mask32();
  308. ((OccludedFunc4)intersectors.intersector4.occluded)(&mask,intersectors.ptr,(RTCRay4&)ray,item);
  309. }
  310. } else {
  311. vint4 mask = valid.mask32();
  312. assert(intersectors.intersectorN.occluded);
  313. intersectors.intersectorN.occluded((int*)&mask,intersectors.ptr,context->user,(RTCRayN*)&ray,4,item);
  314. }
  315. }
  316. #endif
  317. /*! Tests if a packet of 8 rays is occluded by the scene. */
  318. #if defined(__AVX__)
  319. __forceinline void occluded (const vbool8& valid, Ray8& ray, size_t item, IntersectContext* context)
  320. {
  321. assert(item < size());
  322. if (likely(intersectors.intersector8.occluded)) { // old code for compatibility
  323. if (intersectors.intersector8.ispc) {
  324. ((ISPCOccludedFunc8)intersectors.intersector8.occluded)(intersectors.ptr,(RTCRay8&)ray,item,valid.mask32());
  325. } else {
  326. vint8 mask = valid.mask32();
  327. ((OccludedFunc8)intersectors.intersector8.occluded)(&mask,intersectors.ptr,(RTCRay8&)ray,item);
  328. }
  329. } else {
  330. vint8 mask = valid.mask32();
  331. assert(intersectors.intersectorN.occluded);
  332. intersectors.intersectorN.occluded((int*)&mask,intersectors.ptr,context->user,(RTCRayN*)&ray,8,item);
  333. }
  334. }
  335. #endif
  336. /*! Tests if a packet of 16 rays is occluded by the scene. */
  337. #if defined(__AVX512F__)
  338. __forceinline void occluded (const vbool16& valid, Ray16& ray, size_t item, IntersectContext* context)
  339. {
  340. assert(item < size());
  341. if (likely(intersectors.intersector16.occluded)) { // old code for compatibility
  342. if (intersectors.intersector16.ispc) {
  343. ((ISPCOccludedFunc16)intersectors.intersector16.occluded)(intersectors.ptr,(RTCRay16&)ray,item,valid.mask8());
  344. }
  345. else {
  346. vint16 mask = valid.mask32();
  347. ((OccludedFunc16)intersectors.intersector16.occluded)(&mask,intersectors.ptr,(RTCRay16&)ray,item);
  348. }
  349. } else {
  350. vint16 mask = valid.mask32();
  351. assert(intersectors.intersectorN.occluded);
  352. intersectors.intersectorN.occluded((int*)&mask,intersectors.ptr,context->user,(RTCRayN*)&ray,16,item);
  353. }
  354. }
  355. #endif
  356. /*! Tests if a stream of rays is occluded by the scene. */
  357. __forceinline void occluded1M (Ray** rays, size_t N, size_t item, IntersectContext* context)
  358. {
  359. if (likely(intersectors.intersector1M.occluded)) { // Occluded1N callback is optional
  360. intersectors.intersector1M.occluded(intersectors.ptr,context->user,(RTCRay**)rays,N,item);
  361. }
  362. else if (N == 1) {
  363. int mask = -1;
  364. assert(intersectors.intersectorN.occluded);
  365. intersectors.intersectorN.occluded((int*)&mask,intersectors.ptr,context->user,(RTCRayN*)rays[0],1,item);
  366. }
  367. else
  368. {
  369. int mask[MAX_INTERNAL_STREAM_SIZE];
  370. StackRayPacket<MAX_INTERNAL_STREAM_SIZE> packet(N);
  371. for (size_t i=0; i<N; i++) packet.writeRay(i,mask,*rays[i]);
  372. assert(intersectors.intersectorN.occluded);
  373. intersectors.intersectorN.occluded(mask,intersectors.ptr,context->user,(RTCRayN*)packet.data,N,item);
  374. for (size_t i=0; i<N; i++) packet.readOcclusion(i,*rays[i]);
  375. }
  376. }
  377. public:
  378. RTCBoundsFunc boundsFunc;
  379. RTCBoundsFunc2 boundsFunc2;
  380. RTCBoundsFunc3 boundsFunc3;
  381. void* boundsFuncUserPtr;
  382. struct Intersectors
  383. {
  384. Intersectors() : ptr(nullptr) {}
  385. public:
  386. void* ptr;
  387. Intersector1 intersector1;
  388. Intersector4 intersector4;
  389. Intersector8 intersector8;
  390. Intersector16 intersector16;
  391. Intersector1M intersector1M;
  392. IntersectorN intersectorN;
  393. } intersectors;
  394. };
  395. #define DEFINE_SET_INTERSECTOR1(symbol,intersector) \
  396. AccelSet::Intersector1 symbol() { \
  397. return AccelSet::Intersector1((AccelSet::IntersectFunc)intersector::intersect, \
  398. (AccelSet::OccludedFunc )intersector::occluded, \
  399. TOSTRING(isa) "::" TOSTRING(symbol)); \
  400. }
  401. #define DEFINE_SET_INTERSECTOR4(symbol,intersector) \
  402. AccelSet::Intersector4 symbol() { \
  403. return AccelSet::Intersector4((void*)intersector::intersect, \
  404. (void*)intersector::occluded, \
  405. TOSTRING(isa) "::" TOSTRING(symbol), \
  406. false); \
  407. }
  408. #define DEFINE_SET_INTERSECTOR8(symbol,intersector) \
  409. AccelSet::Intersector8 symbol() { \
  410. return AccelSet::Intersector8((void*)intersector::intersect, \
  411. (void*)intersector::occluded, \
  412. TOSTRING(isa) "::" TOSTRING(symbol), \
  413. false); \
  414. }
  415. #define DEFINE_SET_INTERSECTOR16(symbol,intersector) \
  416. AccelSet::Intersector16 symbol() { \
  417. return AccelSet::Intersector16((void*)intersector::intersect, \
  418. (void*)intersector::occluded, \
  419. TOSTRING(isa) "::" TOSTRING(symbol), \
  420. false); \
  421. }
  422. #define DEFINE_SET_INTERSECTOR1M(symbol,intersector) \
  423. AccelSet::Intersector1M symbol() { \
  424. return AccelSet::Intersector1M((AccelSet::IntersectFunc1M)intersector::intersect, \
  425. (AccelSet::OccludedFunc1M )intersector::occluded, \
  426. TOSTRING(isa) "::" TOSTRING(symbol)); \
  427. }
  428. #define DEFINE_SET_INTERSECTORN(symbol,intersector) \
  429. AccelSet::IntersectorN symbol() { \
  430. return AccelSet::IntersectorN((AccelSet::IntersectFuncN)intersector::intersect, \
  431. (AccelSet::OccludedFuncN)intersector::occluded, \
  432. TOSTRING(isa) "::" TOSTRING(symbol)); \
  433. }
  434. }