intersector_epilog.h 34 KB

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