intersector_epilog.h 33 KB

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