primrefgen.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. // Copyright 2009-2021 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #include "primrefgen.h"
  4. #include "primrefgen_presplit.h"
  5. #include "../../common/algorithms/parallel_for_for.h"
  6. #include "../../common/algorithms/parallel_for_for_prefix_sum.h"
  7. namespace embree
  8. {
  9. namespace isa
  10. {
  11. PrimInfo createPrimRefArray(Geometry* geometry, unsigned int geomID, const size_t numPrimRefs, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor)
  12. {
  13. ParallelPrefixSumState<PrimInfo> pstate;
  14. /* first try */
  15. progressMonitor(0);
  16. PrimInfo pinfo = parallel_prefix_sum( pstate, size_t(0), geometry->size(), size_t(1024), PrimInfo(empty), [&](const range<size_t>& r, const PrimInfo& base) -> PrimInfo {
  17. return geometry->createPrimRefArray(prims,r,r.begin(),geomID);
  18. }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
  19. /* if we need to filter out geometry, run again */
  20. if (pinfo.size() != numPrimRefs)
  21. {
  22. progressMonitor(0);
  23. pinfo = parallel_prefix_sum( pstate, size_t(0), geometry->size(), size_t(1024), PrimInfo(empty), [&](const range<size_t>& r, const PrimInfo& base) -> PrimInfo {
  24. return geometry->createPrimRefArray(prims,r,base.size(),geomID);
  25. }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
  26. }
  27. return pinfo;
  28. }
  29. PrimInfo createPrimRefArray(Scene* scene, Geometry::GTypeMask types, bool mblur, const size_t numPrimRefs, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor)
  30. {
  31. ParallelForForPrefixSumState<PrimInfo> pstate;
  32. Scene::Iterator2 iter(scene,types,mblur);
  33. /* first try */
  34. progressMonitor(0);
  35. pstate.init(iter,size_t(1024));
  36. PrimInfo pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfo {
  37. return mesh->createPrimRefArray(prims,r,k,(unsigned)geomID);
  38. }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
  39. /* if we need to filter out geometry, run again */
  40. if (pinfo.size() != numPrimRefs)
  41. {
  42. progressMonitor(0);
  43. pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfo& base) -> PrimInfo {
  44. return mesh->createPrimRefArray(prims,r,base.size(),(unsigned)geomID);
  45. }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
  46. }
  47. return pinfo;
  48. }
  49. PrimInfo createPrimRefArray(Scene* scene, Geometry::GTypeMask types, bool mblur, const size_t numPrimRefs, mvector<PrimRef>& prims, mvector<SubGridBuildData>& sgrids, BuildProgressMonitor& progressMonitor)
  50. {
  51. ParallelForForPrefixSumState<PrimInfo> pstate;
  52. Scene::Iterator2 iter(scene,types,mblur);
  53. /* first try */
  54. progressMonitor(0);
  55. pstate.init(iter,size_t(1024));
  56. PrimInfo pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfo {
  57. return mesh->createPrimRefArray(prims,sgrids,r,k,(unsigned)geomID);
  58. }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
  59. /* if we need to filter out geometry, run again */
  60. if (pinfo.size() != numPrimRefs)
  61. {
  62. progressMonitor(0);
  63. pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfo& base) -> PrimInfo {
  64. return mesh->createPrimRefArray(prims,sgrids,r,base.size(),(unsigned)geomID);
  65. }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
  66. }
  67. return pinfo;
  68. }
  69. PrimInfo createPrimRefArrayMBlur(Scene* scene, Geometry::GTypeMask types, const size_t numPrimRefs, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor, size_t itime)
  70. {
  71. ParallelForForPrefixSumState<PrimInfo> pstate;
  72. Scene::Iterator2 iter(scene,types,true);
  73. /* first try */
  74. progressMonitor(0);
  75. pstate.init(iter,size_t(1024));
  76. PrimInfo pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfo {
  77. return mesh->createPrimRefArrayMB(prims,itime,r,k,(unsigned)geomID);
  78. }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
  79. /* if we need to filter out geometry, run again */
  80. if (pinfo.size() != numPrimRefs)
  81. {
  82. progressMonitor(0);
  83. pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfo& base) -> PrimInfo {
  84. return mesh->createPrimRefArrayMB(prims,itime,r,base.size(),(unsigned)geomID);
  85. }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
  86. }
  87. return pinfo;
  88. }
  89. PrimInfoMB createPrimRefArrayMSMBlur(Scene* scene, Geometry::GTypeMask types, const size_t numPrimRefs, mvector<PrimRefMB>& prims, BuildProgressMonitor& progressMonitor, BBox1f t0t1)
  90. {
  91. ParallelForForPrefixSumState<PrimInfoMB> pstate;
  92. Scene::Iterator2 iter(scene,types,true);
  93. /* first try */
  94. progressMonitor(0);
  95. pstate.init(iter,size_t(1024));
  96. PrimInfoMB pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfoMB(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfoMB {
  97. return mesh->createPrimRefMBArray(prims,t0t1,r,k,(unsigned)geomID);
  98. }, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });
  99. /* if we need to filter out geometry, run again */
  100. if (pinfo.size() != numPrimRefs)
  101. {
  102. progressMonitor(0);
  103. pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfoMB(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfoMB& base) -> PrimInfoMB {
  104. return mesh->createPrimRefMBArray(prims,t0t1,r,base.size(),(unsigned)geomID);
  105. }, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });
  106. }
  107. /* the BVH starts with that time range, even though primitives might have smaller/larger time range */
  108. pinfo.time_range = t0t1;
  109. return pinfo;
  110. }
  111. PrimInfoMB createPrimRefArrayMSMBlur(Scene* scene, Geometry::GTypeMask types, const size_t numPrimRefs, mvector<PrimRefMB>& prims, mvector<SubGridBuildData>& sgrids, BuildProgressMonitor& progressMonitor, BBox1f t0t1)
  112. {
  113. ParallelForForPrefixSumState<PrimInfoMB> pstate;
  114. Scene::Iterator2 iter(scene,types,true);
  115. /* first try */
  116. progressMonitor(0);
  117. pstate.init(iter,size_t(1024));
  118. PrimInfoMB pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfoMB(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfoMB {
  119. return mesh->createPrimRefMBArray(prims,sgrids,t0t1,r,k,(unsigned)geomID);
  120. }, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });
  121. /* if we need to filter out geometry, run again */
  122. if (pinfo.size() != numPrimRefs)
  123. {
  124. progressMonitor(0);
  125. pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfoMB(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfoMB& base) -> PrimInfoMB {
  126. return mesh->createPrimRefMBArray(prims,sgrids,t0t1,r,base.size(),(unsigned)geomID);
  127. }, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });
  128. }
  129. /* the BVH starts with that time range, even though primitives might have smaller/larger time range */
  130. pinfo.time_range = t0t1;
  131. return pinfo;
  132. }
  133. template<typename Mesh>
  134. size_t createMortonCodeArray(Mesh* mesh, mvector<BVHBuilderMorton::BuildPrim>& morton, BuildProgressMonitor& progressMonitor)
  135. {
  136. size_t numPrimitives = morton.size();
  137. /* compute scene bounds */
  138. std::pair<size_t,BBox3fa> cb_empty(0,empty);
  139. auto cb = parallel_reduce
  140. ( size_t(0), numPrimitives, size_t(1024), cb_empty, [&](const range<size_t>& r) -> std::pair<size_t,BBox3fa>
  141. {
  142. size_t num = 0;
  143. BBox3fa bounds = empty;
  144. for (size_t j=r.begin(); j<r.end(); j++)
  145. {
  146. BBox3fa prim_bounds = empty;
  147. if (unlikely(!mesh->buildBounds(j,&prim_bounds))) continue;
  148. bounds.extend(center2(prim_bounds));
  149. num++;
  150. }
  151. return std::make_pair(num,bounds);
  152. }, [] (const std::pair<size_t,BBox3fa>& a, const std::pair<size_t,BBox3fa>& b) {
  153. return std::make_pair(a.first + b.first,merge(a.second,b.second));
  154. });
  155. size_t numPrimitivesGen = cb.first;
  156. const BBox3fa centBounds = cb.second;
  157. /* compute morton codes */
  158. if (likely(numPrimitivesGen == numPrimitives))
  159. {
  160. /* fast path if all primitives were valid */
  161. BVHBuilderMorton::MortonCodeMapping mapping(centBounds);
  162. parallel_for( size_t(0), numPrimitives, size_t(1024), [&](const range<size_t>& r) -> void {
  163. BVHBuilderMorton::MortonCodeGenerator generator(mapping,&morton.data()[r.begin()]);
  164. for (size_t j=r.begin(); j<r.end(); j++)
  165. generator(mesh->bounds(j),unsigned(j));
  166. });
  167. }
  168. else
  169. {
  170. /* slow path, fallback in case some primitives were invalid */
  171. ParallelPrefixSumState<size_t> pstate;
  172. BVHBuilderMorton::MortonCodeMapping mapping(centBounds);
  173. parallel_prefix_sum( pstate, size_t(0), numPrimitives, size_t(1024), size_t(0), [&](const range<size_t>& r, const size_t base) -> size_t {
  174. size_t num = 0;
  175. BVHBuilderMorton::MortonCodeGenerator generator(mapping,&morton.data()[r.begin()]);
  176. for (size_t j=r.begin(); j<r.end(); j++)
  177. {
  178. BBox3fa bounds = empty;
  179. if (unlikely(!mesh->buildBounds(j,&bounds))) continue;
  180. generator(bounds,unsigned(j));
  181. num++;
  182. }
  183. return num;
  184. }, std::plus<size_t>());
  185. parallel_prefix_sum( pstate, size_t(0), numPrimitives, size_t(1024), size_t(0), [&](const range<size_t>& r, const size_t base) -> size_t {
  186. size_t num = 0;
  187. BVHBuilderMorton::MortonCodeGenerator generator(mapping,&morton.data()[base]);
  188. for (size_t j=r.begin(); j<r.end(); j++)
  189. {
  190. BBox3fa bounds = empty;
  191. if (!mesh->buildBounds(j,&bounds)) continue;
  192. generator(bounds,unsigned(j));
  193. num++;
  194. }
  195. return num;
  196. }, std::plus<size_t>());
  197. }
  198. return numPrimitivesGen;
  199. }
  200. // ====================================================================================================
  201. // ====================================================================================================
  202. // ====================================================================================================
  203. // special variants for grid meshes
  204. #if defined(EMBREE_GEOMETRY_GRID)
  205. PrimInfo createPrimRefArrayGrids(Scene* scene, mvector<PrimRef>& prims, mvector<SubGridBuildData>& sgrids)
  206. {
  207. PrimInfo pinfo(empty);
  208. size_t numPrimitives = 0;
  209. /* first run to get #primitives */
  210. ParallelForForPrefixSumState<PrimInfo> pstate;
  211. Scene::Iterator<GridMesh,false> iter(scene);
  212. pstate.init(iter,size_t(1024));
  213. /* iterate over all meshes in the scene */
  214. pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfo {
  215. PrimInfo pinfo(empty);
  216. for (size_t j=r.begin(); j<r.end(); j++)
  217. {
  218. if (!mesh->valid(j)) continue;
  219. BBox3fa bounds = empty;
  220. const PrimRef prim(bounds,(unsigned)geomID,(unsigned)j);
  221. if (!mesh->valid(j)) continue;
  222. pinfo.add_center2(prim,mesh->getNumSubGrids(j));
  223. }
  224. return pinfo;
  225. }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
  226. numPrimitives = pinfo.size();
  227. /* resize arrays */
  228. sgrids.resize(numPrimitives);
  229. prims.resize(numPrimitives);
  230. /* second run to fill primrefs and SubGridBuildData arrays */
  231. pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfo& base) -> PrimInfo {
  232. return mesh->createPrimRefArray(prims,sgrids,r,base.size(),geomID);
  233. }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
  234. assert(pinfo.size() == numPrimitives);
  235. return pinfo;
  236. }
  237. PrimInfo createPrimRefArrayGrids(GridMesh* mesh, mvector<PrimRef>& prims, mvector<SubGridBuildData>& sgrids)
  238. {
  239. unsigned int geomID_ = std::numeric_limits<unsigned int>::max ();
  240. PrimInfo pinfo(empty);
  241. size_t numPrimitives = 0;
  242. ParallelPrefixSumState<PrimInfo> pstate;
  243. /* iterate over all grids in a single mesh */
  244. pinfo = parallel_prefix_sum( pstate, size_t(0), mesh->size(), size_t(1024), PrimInfo(empty), [&](const range<size_t>& r, const PrimInfo& base) -> PrimInfo
  245. {
  246. PrimInfo pinfo(empty);
  247. for (size_t j=r.begin(); j<r.end(); j++)
  248. {
  249. if (!mesh->valid(j)) continue;
  250. BBox3fa bounds = empty;
  251. const PrimRef prim(bounds,geomID_,unsigned(j));
  252. pinfo.add_center2(prim,mesh->getNumSubGrids(j));
  253. }
  254. return pinfo;
  255. }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
  256. numPrimitives = pinfo.size();
  257. /* resize arrays */
  258. sgrids.resize(numPrimitives);
  259. prims.resize(numPrimitives);
  260. /* second run to fill primrefs and SubGridBuildData arrays */
  261. pinfo = parallel_prefix_sum( pstate, size_t(0), mesh->size(), size_t(1024), PrimInfo(empty), [&](const range<size_t>& r, const PrimInfo& base) -> PrimInfo {
  262. return mesh->createPrimRefArray(prims,sgrids,r,base.size(),geomID_);
  263. }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
  264. return pinfo;
  265. }
  266. PrimInfoMB createPrimRefArrayMSMBlurGrid(Scene* scene, mvector<PrimRefMB>& prims, mvector<SubGridBuildData>& sgrids, BuildProgressMonitor& progressMonitor, BBox1f t0t1)
  267. {
  268. /* first run to get #primitives */
  269. ParallelForForPrefixSumState<PrimInfoMB> pstate;
  270. Scene::Iterator<GridMesh,true> iter(scene);
  271. pstate.init(iter,size_t(1024));
  272. /* iterate over all meshes in the scene */
  273. PrimInfoMB pinfoMB = parallel_for_for_prefix_sum0( pstate, iter, PrimInfoMB(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t /*geomID*/) -> PrimInfoMB {
  274. PrimInfoMB pinfoMB(empty);
  275. for (size_t j=r.begin(); j<r.end(); j++)
  276. {
  277. if (!mesh->valid(j, mesh->timeSegmentRange(t0t1))) continue;
  278. LBBox3fa bounds(empty);
  279. PrimInfoMB gridMB(0,mesh->getNumSubGrids(j));
  280. pinfoMB.merge(gridMB);
  281. }
  282. return pinfoMB;
  283. }, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });
  284. size_t numPrimitives = pinfoMB.size();
  285. if (numPrimitives == 0) return pinfoMB;
  286. /* resize arrays */
  287. sgrids.resize(numPrimitives);
  288. prims.resize(numPrimitives);
  289. /* second run to fill primrefs and SubGridBuildData arrays */
  290. pinfoMB = parallel_for_for_prefix_sum1( pstate, iter, PrimInfoMB(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfoMB& base) -> PrimInfoMB {
  291. return mesh->createPrimRefMBArray(prims,sgrids,t0t1,r,base.size(),(unsigned)geomID);
  292. }, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });
  293. assert(pinfoMB.size() == numPrimitives);
  294. pinfoMB.time_range = t0t1;
  295. return pinfoMB;
  296. }
  297. #endif
  298. // ====================================================================================================
  299. // ====================================================================================================
  300. // ====================================================================================================
  301. IF_ENABLED_TRIS (template size_t createMortonCodeArray<TriangleMesh>(TriangleMesh* mesh COMMA mvector<BVHBuilderMorton::BuildPrim>& morton COMMA BuildProgressMonitor& progressMonitor));
  302. IF_ENABLED_QUADS(template size_t createMortonCodeArray<QuadMesh>(QuadMesh* mesh COMMA mvector<BVHBuilderMorton::BuildPrim>& morton COMMA BuildProgressMonitor& progressMonitor));
  303. IF_ENABLED_USER (template size_t createMortonCodeArray<UserGeometry>(UserGeometry* mesh COMMA mvector<BVHBuilderMorton::BuildPrim>& morton COMMA BuildProgressMonitor& progressMonitor));
  304. IF_ENABLED_INSTANCE (template size_t createMortonCodeArray<Instance>(Instance* mesh COMMA mvector<BVHBuilderMorton::BuildPrim>& morton COMMA BuildProgressMonitor& progressMonitor));
  305. IF_ENABLED_INSTANCE_ARRAY (template size_t createMortonCodeArray<InstanceArray>(InstanceArray* mesh COMMA mvector<BVHBuilderMorton::BuildPrim>& morton COMMA BuildProgressMonitor& progressMonitor));
  306. }
  307. }