primrefgen.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  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 createPrimRefArrayMBlur(Scene* scene, Geometry::GTypeMask types, const size_t numPrimRefs, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor, size_t itime)
  50. {
  51. ParallelForForPrefixSumState<PrimInfo> pstate;
  52. Scene::Iterator2 iter(scene,types,true);
  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->createPrimRefArrayMB(prims,itime,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->createPrimRefArrayMB(prims,itime,r,base.size(),(unsigned)geomID);
  65. }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
  66. }
  67. return pinfo;
  68. }
  69. PrimInfoMB createPrimRefArrayMSMBlur(Scene* scene, Geometry::GTypeMask types, const size_t numPrimRefs, mvector<PrimRefMB>& prims, BuildProgressMonitor& progressMonitor, BBox1f t0t1)
  70. {
  71. ParallelForForPrefixSumState<PrimInfoMB> pstate;
  72. Scene::Iterator2 iter(scene,types,true);
  73. /* first try */
  74. progressMonitor(0);
  75. pstate.init(iter,size_t(1024));
  76. 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 {
  77. return mesh->createPrimRefMBArray(prims,t0t1,r,k,(unsigned)geomID);
  78. }, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(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, PrimInfoMB(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfoMB& base) -> PrimInfoMB {
  84. return mesh->createPrimRefMBArray(prims,t0t1,r,base.size(),(unsigned)geomID);
  85. }, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });
  86. }
  87. /* the BVH starts with that time range, even though primitives might have smaller/larger time range */
  88. pinfo.time_range = t0t1;
  89. return pinfo;
  90. }
  91. template<typename Mesh>
  92. size_t createMortonCodeArray(Mesh* mesh, mvector<BVHBuilderMorton::BuildPrim>& morton, BuildProgressMonitor& progressMonitor)
  93. {
  94. size_t numPrimitives = morton.size();
  95. /* compute scene bounds */
  96. std::pair<size_t,BBox3fa> cb_empty(0,empty);
  97. auto cb = parallel_reduce
  98. ( size_t(0), numPrimitives, size_t(1024), cb_empty, [&](const range<size_t>& r) -> std::pair<size_t,BBox3fa>
  99. {
  100. size_t num = 0;
  101. BBox3fa bounds = empty;
  102. for (size_t j=r.begin(); j<r.end(); j++)
  103. {
  104. BBox3fa prim_bounds = empty;
  105. if (unlikely(!mesh->buildBounds(j,&prim_bounds))) continue;
  106. bounds.extend(center2(prim_bounds));
  107. num++;
  108. }
  109. return std::make_pair(num,bounds);
  110. }, [] (const std::pair<size_t,BBox3fa>& a, const std::pair<size_t,BBox3fa>& b) {
  111. return std::make_pair(a.first + b.first,merge(a.second,b.second));
  112. });
  113. size_t numPrimitivesGen = cb.first;
  114. const BBox3fa centBounds = cb.second;
  115. /* compute morton codes */
  116. if (likely(numPrimitivesGen == numPrimitives))
  117. {
  118. /* fast path if all primitives were valid */
  119. BVHBuilderMorton::MortonCodeMapping mapping(centBounds);
  120. parallel_for( size_t(0), numPrimitives, size_t(1024), [&](const range<size_t>& r) -> void {
  121. BVHBuilderMorton::MortonCodeGenerator generator(mapping,&morton.data()[r.begin()]);
  122. for (size_t j=r.begin(); j<r.end(); j++)
  123. generator(mesh->bounds(j),unsigned(j));
  124. });
  125. }
  126. else
  127. {
  128. /* slow path, fallback in case some primitives were invalid */
  129. ParallelPrefixSumState<size_t> pstate;
  130. BVHBuilderMorton::MortonCodeMapping mapping(centBounds);
  131. 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 {
  132. size_t num = 0;
  133. BVHBuilderMorton::MortonCodeGenerator generator(mapping,&morton.data()[r.begin()]);
  134. for (size_t j=r.begin(); j<r.end(); j++)
  135. {
  136. BBox3fa bounds = empty;
  137. if (unlikely(!mesh->buildBounds(j,&bounds))) continue;
  138. generator(bounds,unsigned(j));
  139. num++;
  140. }
  141. return num;
  142. }, std::plus<size_t>());
  143. 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 {
  144. size_t num = 0;
  145. BVHBuilderMorton::MortonCodeGenerator generator(mapping,&morton.data()[base]);
  146. for (size_t j=r.begin(); j<r.end(); j++)
  147. {
  148. BBox3fa bounds = empty;
  149. if (!mesh->buildBounds(j,&bounds)) continue;
  150. generator(bounds,unsigned(j));
  151. num++;
  152. }
  153. return num;
  154. }, std::plus<size_t>());
  155. }
  156. return numPrimitivesGen;
  157. }
  158. // ====================================================================================================
  159. // ====================================================================================================
  160. // ====================================================================================================
  161. // special variants for grid meshes
  162. #if defined(EMBREE_GEOMETRY_GRID)
  163. PrimInfo createPrimRefArrayGrids(Scene* scene, mvector<PrimRef>& prims, mvector<SubGridBuildData>& sgrids)
  164. {
  165. PrimInfo pinfo(empty);
  166. size_t numPrimitives = 0;
  167. /* first run to get #primitives */
  168. ParallelForForPrefixSumState<PrimInfo> pstate;
  169. Scene::Iterator<GridMesh,false> iter(scene);
  170. pstate.init(iter,size_t(1024));
  171. /* iterate over all meshes in the scene */
  172. pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfo {
  173. PrimInfo pinfo(empty);
  174. for (size_t j=r.begin(); j<r.end(); j++)
  175. {
  176. if (!mesh->valid(j)) continue;
  177. BBox3fa bounds = empty;
  178. const PrimRef prim(bounds,(unsigned)geomID,(unsigned)j);
  179. if (!mesh->valid(j)) continue;
  180. pinfo.add_center2(prim,mesh->getNumSubGrids(j));
  181. }
  182. return pinfo;
  183. }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
  184. numPrimitives = pinfo.size();
  185. /* resize arrays */
  186. sgrids.resize(numPrimitives);
  187. prims.resize(numPrimitives);
  188. /* second run to fill primrefs and SubGridBuildData arrays */
  189. 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 {
  190. k = base.size();
  191. size_t p_index = k;
  192. PrimInfo pinfo(empty);
  193. for (size_t j=r.begin(); j<r.end(); j++)
  194. {
  195. if (!mesh->valid(j)) continue;
  196. const GridMesh::Grid &g = mesh->grid(j);
  197. for (unsigned int y=0; y<g.resY-1u; y+=2)
  198. for (unsigned int x=0; x<g.resX-1u; x+=2)
  199. {
  200. BBox3fa bounds = empty;
  201. if (!mesh->buildBounds(g,x,y,bounds)) continue; // get bounds of subgrid
  202. const PrimRef prim(bounds,(unsigned)geomID,(unsigned)p_index);
  203. pinfo.add_center2(prim);
  204. sgrids[p_index] = SubGridBuildData(x | g.get3x3FlagsX(x), y | g.get3x3FlagsY(y), unsigned(j));
  205. prims[p_index++] = prim;
  206. }
  207. }
  208. return pinfo;
  209. }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
  210. assert(pinfo.size() == numPrimitives);
  211. return pinfo;
  212. }
  213. PrimInfo createPrimRefArrayGrids(GridMesh* mesh, mvector<PrimRef>& prims, mvector<SubGridBuildData>& sgrids)
  214. {
  215. unsigned int geomID_ = std::numeric_limits<unsigned int>::max ();
  216. PrimInfo pinfo(empty);
  217. size_t numPrimitives = 0;
  218. ParallelPrefixSumState<PrimInfo> pstate;
  219. /* iterate over all grids in a single mesh */
  220. pinfo = parallel_prefix_sum( pstate, size_t(0), mesh->size(), size_t(1024), PrimInfo(empty), [&](const range<size_t>& r, const PrimInfo& base) -> PrimInfo
  221. {
  222. PrimInfo pinfo(empty);
  223. for (size_t j=r.begin(); j<r.end(); j++)
  224. {
  225. if (!mesh->valid(j)) continue;
  226. BBox3fa bounds = empty;
  227. const PrimRef prim(bounds,geomID_,unsigned(j));
  228. pinfo.add_center2(prim,mesh->getNumSubGrids(j));
  229. }
  230. return pinfo;
  231. }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
  232. numPrimitives = pinfo.size();
  233. /* resize arrays */
  234. sgrids.resize(numPrimitives);
  235. prims.resize(numPrimitives);
  236. /* second run to fill primrefs and SubGridBuildData arrays */
  237. pinfo = parallel_prefix_sum( pstate, size_t(0), mesh->size(), size_t(1024), PrimInfo(empty), [&](const range<size_t>& r, const PrimInfo& base) -> PrimInfo
  238. {
  239. size_t p_index = base.size();
  240. PrimInfo pinfo(empty);
  241. for (size_t j=r.begin(); j<r.end(); j++)
  242. {
  243. if (!mesh->valid(j)) continue;
  244. const GridMesh::Grid &g = mesh->grid(j);
  245. for (unsigned int y=0; y<g.resY-1u; y+=2)
  246. for (unsigned int x=0; x<g.resX-1u; x+=2)
  247. {
  248. BBox3fa bounds = empty;
  249. if (!mesh->buildBounds(g,x,y,bounds)) continue; // get bounds of subgrid
  250. const PrimRef prim(bounds,geomID_,unsigned(p_index));
  251. pinfo.add_center2(prim);
  252. sgrids[p_index] = SubGridBuildData(x | g.get3x3FlagsX(x), y | g.get3x3FlagsY(y), unsigned(j));
  253. prims[p_index++] = prim;
  254. }
  255. }
  256. return pinfo;
  257. }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
  258. return pinfo;
  259. }
  260. #endif
  261. // ====================================================================================================
  262. // ====================================================================================================
  263. // ====================================================================================================
  264. IF_ENABLED_TRIS (template size_t createMortonCodeArray<TriangleMesh>(TriangleMesh* mesh COMMA mvector<BVHBuilderMorton::BuildPrim>& morton COMMA BuildProgressMonitor& progressMonitor));
  265. IF_ENABLED_QUADS(template size_t createMortonCodeArray<QuadMesh>(QuadMesh* mesh COMMA mvector<BVHBuilderMorton::BuildPrim>& morton COMMA BuildProgressMonitor& progressMonitor));
  266. IF_ENABLED_USER (template size_t createMortonCodeArray<UserGeometry>(UserGeometry* mesh COMMA mvector<BVHBuilderMorton::BuildPrim>& morton COMMA BuildProgressMonitor& progressMonitor));
  267. IF_ENABLED_INSTANCE (template size_t createMortonCodeArray<Instance>(Instance* mesh COMMA mvector<BVHBuilderMorton::BuildPrim>& morton COMMA BuildProgressMonitor& progressMonitor));
  268. }
  269. }