intersector_epilog.h 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
  1. // Copyright 2009-2021 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #pragma once
  4. #include "../common/ray.h"
  5. #include "../common/context.h"
  6. #include "filter.h"
  7. namespace embree
  8. {
  9. namespace isa
  10. {
  11. template<int M>
  12. struct UVIdentity {
  13. __forceinline void operator() (vfloat<M>& u, vfloat<M>& v, Vec3vf<M>& Ng) const {}
  14. };
  15. template<bool filter>
  16. struct Intersect1Epilog1
  17. {
  18. RayHit& ray;
  19. IntersectContext* context;
  20. const unsigned int geomID;
  21. const unsigned int primID;
  22. __forceinline Intersect1Epilog1(RayHit& ray,
  23. IntersectContext* context,
  24. const unsigned int geomID,
  25. const unsigned int primID)
  26. : ray(ray), context(context), geomID(geomID), primID(primID) {}
  27. template<typename Hit>
  28. __forceinline bool operator() (Hit& hit) const
  29. {
  30. /* ray mask test */
  31. Scene* scene MAYBE_UNUSED = context->scene;
  32. Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
  33. #if defined(EMBREE_RAY_MASK)
  34. if ((geometry->mask & ray.mask) == 0) return false;
  35. #endif
  36. hit.finalize();
  37. /* intersection filter test */
  38. #if defined(EMBREE_FILTER_FUNCTION)
  39. if (filter) {
  40. if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
  41. HitK<1> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng);
  42. const float old_t = ray.tfar;
  43. ray.tfar = hit.t;
  44. bool found = runIntersectionFilter1(geometry,ray,context,h);
  45. if (!found) ray.tfar = old_t;
  46. return found;
  47. }
  48. }
  49. #endif
  50. /* update hit information */
  51. ray.tfar = hit.t;
  52. ray.Ng = hit.Ng;
  53. ray.u = hit.u;
  54. ray.v = hit.v;
  55. ray.primID = primID;
  56. ray.geomID = geomID;
  57. instance_id_stack::copy_UU(context->user->instID, ray.instID);
  58. return true;
  59. }
  60. };
  61. template<bool filter>
  62. struct Occluded1Epilog1
  63. {
  64. Ray& ray;
  65. IntersectContext* context;
  66. const unsigned int geomID;
  67. const unsigned int primID;
  68. __forceinline Occluded1Epilog1(Ray& ray,
  69. IntersectContext* context,
  70. const unsigned int geomID,
  71. const unsigned int primID)
  72. : ray(ray), context(context), geomID(geomID), primID(primID) {}
  73. template<typename Hit>
  74. __forceinline bool operator() (Hit& hit) const
  75. {
  76. /* ray mask test */
  77. Scene* scene MAYBE_UNUSED = context->scene;
  78. Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
  79. #if defined(EMBREE_RAY_MASK)
  80. if ((geometry->mask & ray.mask) == 0) return false;
  81. #endif
  82. hit.finalize();
  83. /* intersection filter test */
  84. #if defined(EMBREE_FILTER_FUNCTION)
  85. if (filter) {
  86. if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter())) {
  87. HitK<1> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng);
  88. const float old_t = ray.tfar;
  89. ray.tfar = hit.t;
  90. const bool found = runOcclusionFilter1(geometry,ray,context,h);
  91. if (!found) ray.tfar = old_t;
  92. return found;
  93. }
  94. }
  95. #endif
  96. return true;
  97. }
  98. };
  99. template<int K, bool filter>
  100. struct Intersect1KEpilog1
  101. {
  102. RayHitK<K>& ray;
  103. size_t k;
  104. IntersectContext* context;
  105. const unsigned int geomID;
  106. const unsigned int primID;
  107. __forceinline Intersect1KEpilog1(RayHitK<K>& ray, size_t k,
  108. IntersectContext* context,
  109. const unsigned int geomID,
  110. const unsigned int primID)
  111. : ray(ray), k(k), context(context), geomID(geomID), primID(primID) {}
  112. template<typename Hit>
  113. __forceinline bool operator() (Hit& hit) const
  114. {
  115. /* ray mask test */
  116. Scene* scene MAYBE_UNUSED = context->scene;
  117. Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
  118. #if defined(EMBREE_RAY_MASK)
  119. if ((geometry->mask & ray.mask[k]) == 0)
  120. return false;
  121. #endif
  122. hit.finalize();
  123. /* intersection filter test */
  124. #if defined(EMBREE_FILTER_FUNCTION)
  125. if (filter) {
  126. if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
  127. HitK<K> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng);
  128. const float old_t = ray.tfar[k];
  129. ray.tfar[k] = hit.t;
  130. const bool found = any(runIntersectionFilter(vbool<K>(1<<k),geometry,ray,context,h));
  131. if (!found) ray.tfar[k] = old_t;
  132. return found;
  133. }
  134. }
  135. #endif
  136. /* update hit information */
  137. ray.tfar[k] = hit.t;
  138. ray.Ng.x[k] = hit.Ng.x;
  139. ray.Ng.y[k] = hit.Ng.y;
  140. ray.Ng.z[k] = hit.Ng.z;
  141. ray.u[k] = hit.u;
  142. ray.v[k] = hit.v;
  143. ray.primID[k] = primID;
  144. ray.geomID[k] = geomID;
  145. instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, k);
  146. return true;
  147. }
  148. };
  149. template<int K, bool filter>
  150. struct Occluded1KEpilog1
  151. {
  152. RayK<K>& ray;
  153. size_t k;
  154. IntersectContext* context;
  155. const unsigned int geomID;
  156. const unsigned int primID;
  157. __forceinline Occluded1KEpilog1(RayK<K>& ray, size_t k,
  158. IntersectContext* context,
  159. const unsigned int geomID,
  160. const unsigned int primID)
  161. : ray(ray), k(k), context(context), geomID(geomID), primID(primID) {}
  162. template<typename Hit>
  163. __forceinline bool operator() (Hit& hit) const
  164. {
  165. /* ray mask test */
  166. Scene* scene MAYBE_UNUSED = context->scene;
  167. Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
  168. #if defined(EMBREE_RAY_MASK)
  169. if ((geometry->mask & ray.mask[k]) == 0)
  170. return false;
  171. #endif
  172. /* intersection filter test */
  173. #if defined(EMBREE_FILTER_FUNCTION)
  174. if (filter) {
  175. if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter())) {
  176. hit.finalize();
  177. HitK<K> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng);
  178. const float old_t = ray.tfar[k];
  179. ray.tfar[k] = hit.t;
  180. const bool found = any(runOcclusionFilter(vbool<K>(1<<k),geometry,ray,context,h));
  181. if (!found) ray.tfar[k] = old_t;
  182. return found;
  183. }
  184. }
  185. #endif
  186. return true;
  187. }
  188. };
  189. template<int M, bool filter>
  190. struct Intersect1EpilogM
  191. {
  192. RayHit& ray;
  193. IntersectContext* context;
  194. const vuint<M>& geomIDs;
  195. const vuint<M>& primIDs;
  196. __forceinline Intersect1EpilogM(RayHit& ray,
  197. IntersectContext* context,
  198. const vuint<M>& geomIDs,
  199. const vuint<M>& primIDs)
  200. : ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs) {}
  201. template<typename Hit>
  202. __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
  203. {
  204. Scene* scene MAYBE_UNUSED = context->scene;
  205. vbool<M> valid = valid_i;
  206. hit.finalize();
  207. size_t i = select_min(valid,hit.vt);
  208. unsigned int geomID = geomIDs[i];
  209. /* intersection filter test */
  210. #if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)
  211. bool foundhit = false;
  212. goto entry;
  213. while (true)
  214. {
  215. if (unlikely(none(valid))) return foundhit;
  216. i = select_min(valid,hit.vt);
  217. geomID = geomIDs[i];
  218. entry:
  219. Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
  220. #if defined(EMBREE_RAY_MASK)
  221. /* goto next hit if mask test fails */
  222. if ((geometry->mask & ray.mask) == 0) {
  223. clear(valid,i);
  224. continue;
  225. }
  226. #endif
  227. #if defined(EMBREE_FILTER_FUNCTION)
  228. /* call intersection filter function */
  229. if (filter) {
  230. if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
  231. const Vec2f uv = hit.uv(i);
  232. HitK<1> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i));
  233. const float old_t = ray.tfar;
  234. ray.tfar = hit.t(i);
  235. const bool found = runIntersectionFilter1(geometry,ray,context,h);
  236. if (!found) ray.tfar = old_t;
  237. foundhit |= found;
  238. clear(valid,i);
  239. valid &= hit.vt <= ray.tfar; // intersection filters may modify tfar value
  240. continue;
  241. }
  242. }
  243. #endif
  244. break;
  245. }
  246. #endif
  247. /* update hit information */
  248. const Vec2f uv = hit.uv(i);
  249. ray.tfar = hit.vt[i];
  250. ray.Ng.x = hit.vNg.x[i];
  251. ray.Ng.y = hit.vNg.y[i];
  252. ray.Ng.z = hit.vNg.z[i];
  253. ray.u = uv.x;
  254. ray.v = uv.y;
  255. ray.primID = primIDs[i];
  256. ray.geomID = geomID;
  257. instance_id_stack::copy_UU(context->user->instID, ray.instID);
  258. return true;
  259. }
  260. };
  261. template<int M, bool filter>
  262. struct Occluded1EpilogM
  263. {
  264. Ray& ray;
  265. IntersectContext* context;
  266. const vuint<M>& geomIDs;
  267. const vuint<M>& primIDs;
  268. __forceinline Occluded1EpilogM(Ray& ray,
  269. IntersectContext* context,
  270. const vuint<M>& geomIDs,
  271. const vuint<M>& primIDs)
  272. : ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs) {}
  273. template<typename Hit>
  274. __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
  275. {
  276. Scene* scene MAYBE_UNUSED = context->scene;
  277. /* intersection filter test */
  278. #if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)
  279. if (unlikely(filter))
  280. hit.finalize(); /* called only once */
  281. vbool<M> valid = valid_i;
  282. size_t m=movemask(valid);
  283. goto entry;
  284. while (true)
  285. {
  286. if (unlikely(m == 0)) return false;
  287. entry:
  288. size_t i=bsf(m);
  289. const unsigned int geomID = geomIDs[i];
  290. Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
  291. #if defined(EMBREE_RAY_MASK)
  292. /* goto next hit if mask test fails */
  293. if ((geometry->mask & ray.mask) == 0) {
  294. m=btc(m,i);
  295. continue;
  296. }
  297. #endif
  298. #if defined(EMBREE_FILTER_FUNCTION)
  299. /* if we have no filter then the test passed */
  300. if (filter) {
  301. if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
  302. {
  303. const Vec2f uv = hit.uv(i);
  304. HitK<1> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i));
  305. const float old_t = ray.tfar;
  306. ray.tfar = hit.t(i);
  307. if (runOcclusionFilter1(geometry,ray,context,h)) return true;
  308. ray.tfar = old_t;
  309. m=btc(m,i);
  310. continue;
  311. }
  312. }
  313. #endif
  314. break;
  315. }
  316. #endif
  317. return true;
  318. }
  319. };
  320. template<int M, bool filter>
  321. struct Intersect1EpilogMU
  322. {
  323. RayHit& ray;
  324. IntersectContext* context;
  325. const unsigned int geomID;
  326. const unsigned int primID;
  327. __forceinline Intersect1EpilogMU(RayHit& ray,
  328. IntersectContext* context,
  329. const unsigned int geomID,
  330. const unsigned int primID)
  331. : ray(ray), context(context), geomID(geomID), primID(primID) {}
  332. template<typename Hit>
  333. __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
  334. {
  335. /* ray mask test */
  336. Scene* scene MAYBE_UNUSED = context->scene;
  337. Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
  338. #if defined(EMBREE_RAY_MASK)
  339. if ((geometry->mask & ray.mask) == 0) return false;
  340. #endif
  341. vbool<M> valid = valid_i;
  342. hit.finalize();
  343. size_t i = select_min(valid,hit.vt);
  344. /* intersection filter test */
  345. #if defined(EMBREE_FILTER_FUNCTION)
  346. if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter()))
  347. {
  348. bool foundhit = false;
  349. while (true)
  350. {
  351. /* call intersection filter function */
  352. Vec2f uv = hit.uv(i);
  353. const float old_t = ray.tfar;
  354. ray.tfar = hit.t(i);
  355. HitK<1> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i));
  356. const bool found = runIntersectionFilter1(geometry,ray,context,h);
  357. if (!found) ray.tfar = old_t;
  358. foundhit |= found;
  359. clear(valid,i);
  360. valid &= hit.vt <= ray.tfar; // intersection filters may modify tfar value
  361. if (unlikely(none(valid))) break;
  362. i = select_min(valid,hit.vt);
  363. }
  364. return foundhit;
  365. }
  366. #endif
  367. /* update hit information */
  368. const Vec2f uv = hit.uv(i);
  369. const Vec3fa Ng = hit.Ng(i);
  370. ray.tfar = hit.t(i);
  371. ray.Ng.x = Ng.x;
  372. ray.Ng.y = Ng.y;
  373. ray.Ng.z = Ng.z;
  374. ray.u = uv.x;
  375. ray.v = uv.y;
  376. ray.primID = primID;
  377. ray.geomID = geomID;
  378. instance_id_stack::copy_UU(context->user->instID, ray.instID);
  379. return true;
  380. }
  381. };
  382. template<int M, bool filter>
  383. struct Occluded1EpilogMU
  384. {
  385. Ray& ray;
  386. IntersectContext* context;
  387. const unsigned int geomID;
  388. const unsigned int primID;
  389. __forceinline Occluded1EpilogMU(Ray& ray,
  390. IntersectContext* context,
  391. const unsigned int geomID,
  392. const unsigned int primID)
  393. : ray(ray), context(context), geomID(geomID), primID(primID) {}
  394. template<typename Hit>
  395. __forceinline bool operator() (const vbool<M>& valid, Hit& hit) const
  396. {
  397. /* ray mask test */
  398. Scene* scene MAYBE_UNUSED = context->scene;
  399. Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
  400. #if defined(EMBREE_RAY_MASK)
  401. if ((geometry->mask & ray.mask) == 0) return false;
  402. #endif
  403. /* intersection filter test */
  404. #if defined(EMBREE_FILTER_FUNCTION)
  405. if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
  406. {
  407. hit.finalize();
  408. for (size_t m=movemask(valid), i=bsf(m); m!=0; m=btc(m,i), i=bsf(m))
  409. {
  410. const Vec2f uv = hit.uv(i);
  411. const float old_t = ray.tfar;
  412. ray.tfar = hit.t(i);
  413. HitK<1> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i));
  414. if (runOcclusionFilter1(geometry,ray,context,h)) return true;
  415. ray.tfar = old_t;
  416. }
  417. return false;
  418. }
  419. #endif
  420. return true;
  421. }
  422. };
  423. template<int M, int K, bool filter>
  424. struct IntersectKEpilogM
  425. {
  426. RayHitK<K>& ray;
  427. IntersectContext* context;
  428. const vuint<M>& geomIDs;
  429. const vuint<M>& primIDs;
  430. const size_t i;
  431. __forceinline IntersectKEpilogM(RayHitK<K>& ray,
  432. IntersectContext* context,
  433. const vuint<M>& geomIDs,
  434. const vuint<M>& primIDs,
  435. size_t i)
  436. : ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs), i(i) {}
  437. template<typename Hit>
  438. __forceinline vbool<K> operator() (const vbool<K>& valid_i, const Hit& hit) const
  439. {
  440. Scene* scene MAYBE_UNUSED = context->scene;
  441. vfloat<K> u, v, t;
  442. Vec3vf<K> Ng;
  443. vbool<K> valid = valid_i;
  444. std::tie(u,v,t,Ng) = hit();
  445. const unsigned int geomID = geomIDs[i];
  446. const unsigned int primID = primIDs[i];
  447. Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
  448. /* ray masking test */
  449. #if defined(EMBREE_RAY_MASK)
  450. valid &= (geometry->mask & ray.mask) != 0;
  451. if (unlikely(none(valid))) return false;
  452. #endif
  453. /* occlusion filter test */
  454. #if defined(EMBREE_FILTER_FUNCTION)
  455. if (filter) {
  456. if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
  457. HitK<K> h(context->user,geomID,primID,u,v,Ng);
  458. const vfloat<K> old_t = ray.tfar;
  459. ray.tfar = select(valid,t,ray.tfar);
  460. const vbool<K> m_accept = runIntersectionFilter(valid,geometry,ray,context,h);
  461. ray.tfar = select(m_accept,ray.tfar,old_t);
  462. return m_accept;
  463. }
  464. }
  465. #endif
  466. /* update hit information */
  467. vfloat<K>::store(valid,&ray.tfar,t);
  468. vfloat<K>::store(valid,&ray.Ng.x,Ng.x);
  469. vfloat<K>::store(valid,&ray.Ng.y,Ng.y);
  470. vfloat<K>::store(valid,&ray.Ng.z,Ng.z);
  471. vfloat<K>::store(valid,&ray.u,u);
  472. vfloat<K>::store(valid,&ray.v,v);
  473. vuint<K>::store(valid,&ray.primID,primID);
  474. vuint<K>::store(valid,&ray.geomID,geomID);
  475. instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, valid);
  476. return valid;
  477. }
  478. };
  479. template<int M, int K, bool filter>
  480. struct OccludedKEpilogM
  481. {
  482. vbool<K>& valid0;
  483. RayK<K>& ray;
  484. IntersectContext* context;
  485. const vuint<M>& geomIDs;
  486. const vuint<M>& primIDs;
  487. const size_t i;
  488. __forceinline OccludedKEpilogM(vbool<K>& valid0,
  489. RayK<K>& ray,
  490. IntersectContext* context,
  491. const vuint<M>& geomIDs,
  492. const vuint<M>& primIDs,
  493. size_t i)
  494. : valid0(valid0), ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs), i(i) {}
  495. template<typename Hit>
  496. __forceinline vbool<K> operator() (const vbool<K>& valid_i, const Hit& hit) const
  497. {
  498. vbool<K> valid = valid_i;
  499. /* ray masking test */
  500. Scene* scene MAYBE_UNUSED = context->scene;
  501. const unsigned int geomID MAYBE_UNUSED = geomIDs[i];
  502. const unsigned int primID MAYBE_UNUSED = primIDs[i];
  503. Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
  504. #if defined(EMBREE_RAY_MASK)
  505. valid &= (geometry->mask & ray.mask) != 0;
  506. if (unlikely(none(valid))) return valid;
  507. #endif
  508. /* intersection filter test */
  509. #if defined(EMBREE_FILTER_FUNCTION)
  510. if (filter) {
  511. if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
  512. {
  513. vfloat<K> u, v, t;
  514. Vec3vf<K> Ng;
  515. std::tie(u,v,t,Ng) = hit();
  516. HitK<K> h(context->user,geomID,primID,u,v,Ng);
  517. const vfloat<K> old_t = ray.tfar;
  518. ray.tfar = select(valid,t,ray.tfar);
  519. valid = runOcclusionFilter(valid,geometry,ray,context,h);
  520. ray.tfar = select(valid,ray.tfar,old_t);
  521. }
  522. }
  523. #endif
  524. /* update occlusion */
  525. valid0 = valid0 & !valid;
  526. return valid;
  527. }
  528. };
  529. template<int M, int K, bool filter>
  530. struct IntersectKEpilogMU
  531. {
  532. RayHitK<K>& ray;
  533. IntersectContext* context;
  534. const unsigned int geomID;
  535. const unsigned int primID;
  536. __forceinline IntersectKEpilogMU(RayHitK<K>& ray,
  537. IntersectContext* context,
  538. const unsigned int geomID,
  539. const unsigned int primID)
  540. : ray(ray), context(context), geomID(geomID), primID(primID) {}
  541. template<typename Hit>
  542. __forceinline vbool<K> operator() (const vbool<K>& valid_org, const Hit& hit) const
  543. {
  544. vbool<K> valid = valid_org;
  545. vfloat<K> u, v, t;
  546. Vec3vf<K> Ng;
  547. std::tie(u,v,t,Ng) = hit();
  548. Scene* scene MAYBE_UNUSED = context->scene;
  549. Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
  550. /* ray masking test */
  551. #if defined(EMBREE_RAY_MASK)
  552. valid &= (geometry->mask & ray.mask) != 0;
  553. if (unlikely(none(valid))) return false;
  554. #endif
  555. /* intersection filter test */
  556. #if defined(EMBREE_FILTER_FUNCTION)
  557. if (filter) {
  558. if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
  559. HitK<K> h(context->user,geomID,primID,u,v,Ng);
  560. const vfloat<K> old_t = ray.tfar;
  561. ray.tfar = select(valid,t,ray.tfar);
  562. const vbool<K> m_accept = runIntersectionFilter(valid,geometry,ray,context,h);
  563. ray.tfar = select(m_accept,ray.tfar,old_t);
  564. return m_accept;
  565. }
  566. }
  567. #endif
  568. /* update hit information */
  569. vfloat<K>::store(valid,&ray.tfar,t);
  570. vfloat<K>::store(valid,&ray.Ng.x,Ng.x);
  571. vfloat<K>::store(valid,&ray.Ng.y,Ng.y);
  572. vfloat<K>::store(valid,&ray.Ng.z,Ng.z);
  573. vfloat<K>::store(valid,&ray.u,u);
  574. vfloat<K>::store(valid,&ray.v,v);
  575. vuint<K>::store(valid,&ray.primID,primID);
  576. vuint<K>::store(valid,&ray.geomID,geomID);
  577. instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, valid);
  578. return valid;
  579. }
  580. };
  581. template<int M, int K, bool filter>
  582. struct OccludedKEpilogMU
  583. {
  584. vbool<K>& valid0;
  585. RayK<K>& ray;
  586. IntersectContext* context;
  587. const unsigned int geomID;
  588. const unsigned int primID;
  589. __forceinline OccludedKEpilogMU(vbool<K>& valid0,
  590. RayK<K>& ray,
  591. IntersectContext* context,
  592. const unsigned int geomID,
  593. const unsigned int primID)
  594. : valid0(valid0), ray(ray), context(context), geomID(geomID), primID(primID) {}
  595. template<typename Hit>
  596. __forceinline vbool<K> operator() (const vbool<K>& valid_i, const Hit& hit) const
  597. {
  598. vbool<K> valid = valid_i;
  599. Scene* scene MAYBE_UNUSED = context->scene;
  600. Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
  601. #if defined(EMBREE_RAY_MASK)
  602. valid &= (geometry->mask & ray.mask) != 0;
  603. if (unlikely(none(valid))) return false;
  604. #endif
  605. /* occlusion filter test */
  606. #if defined(EMBREE_FILTER_FUNCTION)
  607. if (filter) {
  608. if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
  609. {
  610. vfloat<K> u, v, t;
  611. Vec3vf<K> Ng;
  612. std::tie(u,v,t,Ng) = hit();
  613. HitK<K> h(context->user,geomID,primID,u,v,Ng);
  614. const vfloat<K> old_t = ray.tfar;
  615. ray.tfar = select(valid,t,ray.tfar);
  616. valid = runOcclusionFilter(valid,geometry,ray,context,h);
  617. ray.tfar = select(valid,ray.tfar,old_t);
  618. }
  619. }
  620. #endif
  621. /* update occlusion */
  622. valid0 = valid0 & !valid;
  623. return valid;
  624. }
  625. };
  626. template<int M, int K, bool filter>
  627. struct Intersect1KEpilogM
  628. {
  629. RayHitK<K>& ray;
  630. size_t k;
  631. IntersectContext* context;
  632. const vuint<M>& geomIDs;
  633. const vuint<M>& primIDs;
  634. __forceinline Intersect1KEpilogM(RayHitK<K>& ray, size_t k,
  635. IntersectContext* context,
  636. const vuint<M>& geomIDs,
  637. const vuint<M>& primIDs)
  638. : ray(ray), k(k), context(context), geomIDs(geomIDs), primIDs(primIDs) {}
  639. template<typename Hit>
  640. __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
  641. {
  642. Scene* scene MAYBE_UNUSED = context->scene;
  643. vbool<M> valid = valid_i;
  644. hit.finalize();
  645. size_t i = select_min(valid,hit.vt);
  646. assert(i<M);
  647. unsigned int geomID = geomIDs[i];
  648. /* intersection filter test */
  649. #if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)
  650. bool foundhit = false;
  651. goto entry;
  652. while (true)
  653. {
  654. if (unlikely(none(valid))) return foundhit;
  655. i = select_min(valid,hit.vt);
  656. assert(i<M);
  657. geomID = geomIDs[i];
  658. entry:
  659. Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
  660. #if defined(EMBREE_RAY_MASK)
  661. /* goto next hit if mask test fails */
  662. if ((geometry->mask & ray.mask[k]) == 0) {
  663. clear(valid,i);
  664. continue;
  665. }
  666. #endif
  667. #if defined(EMBREE_FILTER_FUNCTION)
  668. /* call intersection filter function */
  669. if (filter) {
  670. if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
  671. assert(i<M);
  672. const Vec2f uv = hit.uv(i);
  673. HitK<K> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i));
  674. const float old_t = ray.tfar[k];
  675. ray.tfar[k] = hit.t(i);
  676. const bool found = any(runIntersectionFilter(vbool<K>(1<<k),geometry,ray,context,h));
  677. if (!found) ray.tfar[k] = old_t;
  678. foundhit = foundhit | found;
  679. clear(valid,i);
  680. valid &= hit.vt <= ray.tfar[k]; // intersection filters may modify tfar value
  681. continue;
  682. }
  683. }
  684. #endif
  685. break;
  686. }
  687. #endif
  688. assert(i<M);
  689. /* update hit information */
  690. const Vec2f uv = hit.uv(i);
  691. ray.tfar[k] = hit.t(i);
  692. ray.Ng.x[k] = hit.vNg.x[i];
  693. ray.Ng.y[k] = hit.vNg.y[i];
  694. ray.Ng.z[k] = hit.vNg.z[i];
  695. ray.u[k] = uv.x;
  696. ray.v[k] = uv.y;
  697. ray.primID[k] = primIDs[i];
  698. ray.geomID[k] = geomID;
  699. instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, k);
  700. return true;
  701. }
  702. };
  703. template<int M, int K, bool filter>
  704. struct Occluded1KEpilogM
  705. {
  706. RayK<K>& ray;
  707. size_t k;
  708. IntersectContext* context;
  709. const vuint<M>& geomIDs;
  710. const vuint<M>& primIDs;
  711. __forceinline Occluded1KEpilogM(RayK<K>& ray, size_t k,
  712. IntersectContext* context,
  713. const vuint<M>& geomIDs,
  714. const vuint<M>& primIDs)
  715. : ray(ray), k(k), context(context), geomIDs(geomIDs), primIDs(primIDs) {}
  716. template<typename Hit>
  717. __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
  718. {
  719. Scene* scene MAYBE_UNUSED = context->scene;
  720. /* intersection filter test */
  721. #if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)
  722. if (unlikely(filter))
  723. hit.finalize(); /* called only once */
  724. vbool<M> valid = valid_i;
  725. size_t m=movemask(valid);
  726. goto entry;
  727. while (true)
  728. {
  729. if (unlikely(m == 0)) return false;
  730. entry:
  731. size_t i=bsf(m);
  732. const unsigned int geomID = geomIDs[i];
  733. Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
  734. #if defined(EMBREE_RAY_MASK)
  735. /* goto next hit if mask test fails */
  736. if ((geometry->mask & ray.mask[k]) == 0) {
  737. m=btc(m,i);
  738. continue;
  739. }
  740. #endif
  741. #if defined(EMBREE_FILTER_FUNCTION)
  742. /* execute occlusion filer */
  743. if (filter) {
  744. if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
  745. {
  746. const Vec2f uv = hit.uv(i);
  747. const float old_t = ray.tfar[k];
  748. ray.tfar[k] = hit.t(i);
  749. HitK<K> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i));
  750. if (any(runOcclusionFilter(vbool<K>(1<<k),geometry,ray,context,h))) return true;
  751. ray.tfar[k] = old_t;
  752. m=btc(m,i);
  753. continue;
  754. }
  755. }
  756. #endif
  757. break;
  758. }
  759. #endif
  760. return true;
  761. }
  762. };
  763. template<int M, int K, bool filter>
  764. struct Intersect1KEpilogMU
  765. {
  766. RayHitK<K>& ray;
  767. size_t k;
  768. IntersectContext* context;
  769. const unsigned int geomID;
  770. const unsigned int primID;
  771. __forceinline Intersect1KEpilogMU(RayHitK<K>& ray, size_t k,
  772. IntersectContext* context,
  773. const unsigned int geomID,
  774. const unsigned int primID)
  775. : ray(ray), k(k), context(context), geomID(geomID), primID(primID) {}
  776. template<typename Hit>
  777. __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
  778. {
  779. Scene* scene MAYBE_UNUSED = context->scene;
  780. Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
  781. #if defined(EMBREE_RAY_MASK)
  782. /* ray mask test */
  783. if ((geometry->mask & ray.mask[k]) == 0)
  784. return false;
  785. #endif
  786. /* finalize hit calculation */
  787. vbool<M> valid = valid_i;
  788. hit.finalize();
  789. size_t i = select_min(valid,hit.vt);
  790. /* intersection filter test */
  791. #if defined(EMBREE_FILTER_FUNCTION)
  792. if (filter) {
  793. if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter()))
  794. {
  795. bool foundhit = false;
  796. while (true)
  797. {
  798. const Vec2f uv = hit.uv(i);
  799. const float old_t = ray.tfar[k];
  800. ray.tfar[k] = hit.t(i);
  801. HitK<K> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i));
  802. const bool found = any(runIntersectionFilter(vbool<K>(1<<k),geometry,ray,context,h));
  803. if (!found) ray.tfar[k] = old_t;
  804. foundhit = foundhit | found;
  805. clear(valid,i);
  806. valid &= hit.vt <= ray.tfar[k]; // intersection filters may modify tfar value
  807. if (unlikely(none(valid))) break;
  808. i = select_min(valid,hit.vt);
  809. }
  810. return foundhit;
  811. }
  812. }
  813. #endif
  814. /* update hit information */
  815. const Vec2f uv = hit.uv(i);
  816. const Vec3fa Ng = hit.Ng(i);
  817. ray.tfar[k] = hit.t(i);
  818. ray.Ng.x[k] = Ng.x;
  819. ray.Ng.y[k] = Ng.y;
  820. ray.Ng.z[k] = Ng.z;
  821. ray.u[k] = uv.x;
  822. ray.v[k] = uv.y;
  823. ray.primID[k] = primID;
  824. ray.geomID[k] = geomID;
  825. instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, k);
  826. return true;
  827. }
  828. };
  829. template<int M, int K, bool filter>
  830. struct Occluded1KEpilogMU
  831. {
  832. RayK<K>& ray;
  833. size_t k;
  834. IntersectContext* context;
  835. const unsigned int geomID;
  836. const unsigned int primID;
  837. __forceinline Occluded1KEpilogMU(RayK<K>& ray, size_t k,
  838. IntersectContext* context,
  839. const unsigned int geomID,
  840. const unsigned int primID)
  841. : ray(ray), k(k), context(context), geomID(geomID), primID(primID) {}
  842. template<typename Hit>
  843. __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
  844. {
  845. Scene* scene MAYBE_UNUSED = context->scene;
  846. Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
  847. #if defined(EMBREE_RAY_MASK)
  848. /* ray mask test */
  849. if ((geometry->mask & ray.mask[k]) == 0)
  850. return false;
  851. #endif
  852. /* intersection filter test */
  853. #if defined(EMBREE_FILTER_FUNCTION)
  854. if (filter) {
  855. if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
  856. {
  857. hit.finalize();
  858. for (size_t m=movemask(valid_i), i=bsf(m); m!=0; m=btc(m,i), i=bsf(m))
  859. {
  860. const Vec2f uv = hit.uv(i);
  861. const float old_t = ray.tfar[k];
  862. ray.tfar[k] = hit.t(i);
  863. HitK<K> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i));
  864. if (any(runOcclusionFilter(vbool<K>(1<<k),geometry,ray,context,h))) return true;
  865. ray.tfar[k] = old_t;
  866. }
  867. return false;
  868. }
  869. }
  870. #endif
  871. return true;
  872. }
  873. };
  874. }
  875. }