bvh_builder_sah_mb.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. // Copyright 2009-2021 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #include "bvh.h"
  4. #include "bvh_builder.h"
  5. #include "../builders/bvh_builder_msmblur.h"
  6. #include "../builders/primrefgen.h"
  7. #include "../builders/splitter.h"
  8. #include "../geometry/linei.h"
  9. #include "../geometry/triangle.h"
  10. #include "../geometry/trianglev.h"
  11. #include "../geometry/trianglev_mb.h"
  12. #include "../geometry/trianglei.h"
  13. #include "../geometry/quadv.h"
  14. #include "../geometry/quadi.h"
  15. #include "../geometry/object.h"
  16. #include "../geometry/instance.h"
  17. #include "../geometry/subgrid.h"
  18. #include "../common/state.h"
  19. // FIXME: remove after removing BVHNBuilderMBlurRootTimeSplitsSAH
  20. #include "../../common/algorithms/parallel_for_for.h"
  21. #include "../../common/algorithms/parallel_for_for_prefix_sum.h"
  22. namespace embree
  23. {
  24. namespace isa
  25. {
  26. #if 0
  27. template<int N, typename Primitive>
  28. struct CreateMBlurLeaf
  29. {
  30. typedef BVHN<N> BVH;
  31. typedef typename BVH::NodeRef NodeRef;
  32. typedef typename BVH::NodeRecordMB NodeRecordMB;
  33. __forceinline CreateMBlurLeaf (BVH* bvh, PrimRef* prims, size_t time) : bvh(bvh), prims(prims), time(time) {}
  34. __forceinline NodeRecordMB operator() (const PrimRef* prims, const range<size_t>& set, const FastAllocator::CachedAllocator& alloc) const
  35. {
  36. size_t items = Primitive::blocks(set.size());
  37. size_t start = set.begin();
  38. for (size_t i=start; i<end; i++) assert((*current.prims.prims)[start].geomID() == (*current.prims.prims)[i].geomID()); // assert that all geomIDs are identical
  39. Primitive* accel = (Primitive*) alloc.malloc1(items*sizeof(Primitive),BVH::byteAlignment);
  40. NodeRef node = bvh->encodeLeaf((char*)accel,items);
  41. LBBox3fa allBounds = empty;
  42. for (size_t i=0; i<items; i++)
  43. allBounds.extend(accel[i].fillMB(prims, start, set.end(), bvh->scene, time));
  44. return NodeRecordMB(node,allBounds);
  45. }
  46. BVH* bvh;
  47. PrimRef* prims;
  48. size_t time;
  49. };
  50. #endif
  51. template<int N, typename Mesh, typename Primitive>
  52. struct CreateMSMBlurLeaf
  53. {
  54. typedef BVHN<N> BVH;
  55. typedef typename BVH::NodeRef NodeRef;
  56. typedef typename BVH::NodeRecordMB4D NodeRecordMB4D;
  57. __forceinline CreateMSMBlurLeaf (BVH* bvh) : bvh(bvh) {}
  58. __forceinline const NodeRecordMB4D operator() (const BVHBuilderMSMBlur::BuildRecord& current, const FastAllocator::CachedAllocator& alloc) const
  59. {
  60. size_t items = Primitive::blocks(current.prims.size());
  61. size_t start = current.prims.begin();
  62. size_t end = current.prims.end();
  63. for (size_t i=start; i<end; i++) assert((*current.prims.prims)[start].geomID() == (*current.prims.prims)[i].geomID()); // assert that all geomIDs are identical
  64. Primitive* accel = (Primitive*) alloc.malloc1(items*sizeof(Primitive),BVH::byteNodeAlignment);
  65. NodeRef node = bvh->encodeLeaf((char*)accel,items);
  66. LBBox3fa allBounds = empty;
  67. for (size_t i=0; i<items; i++)
  68. allBounds.extend(accel[i].fillMB(current.prims.prims->data(), start, current.prims.end(), bvh->scene, current.prims.time_range));
  69. return NodeRecordMB4D(node,allBounds,current.prims.time_range);
  70. }
  71. BVH* bvh;
  72. };
  73. /* Motion blur BVH with 4D nodes and internal time splits */
  74. template<int N, typename Mesh, typename Primitive>
  75. struct BVHNBuilderMBlurSAH : public Builder
  76. {
  77. typedef BVHN<N> BVH;
  78. typedef typename BVHN<N>::NodeRef NodeRef;
  79. typedef typename BVHN<N>::NodeRecordMB NodeRecordMB;
  80. typedef typename BVHN<N>::AABBNodeMB AABBNodeMB;
  81. BVH* bvh;
  82. Scene* scene;
  83. const size_t sahBlockSize;
  84. const float intCost;
  85. const size_t minLeafSize;
  86. const size_t maxLeafSize;
  87. const Geometry::GTypeMask gtype_;
  88. BVHNBuilderMBlurSAH (BVH* bvh, Scene* scene, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const Geometry::GTypeMask gtype)
  89. : bvh(bvh), scene(scene), sahBlockSize(sahBlockSize), intCost(intCost), minLeafSize(minLeafSize), maxLeafSize(min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks)), gtype_(gtype) {}
  90. void build()
  91. {
  92. /* skip build for empty scene */
  93. const size_t numPrimitives = scene->getNumPrimitives(gtype_,true);
  94. if (numPrimitives == 0) { bvh->clear(); return; }
  95. double t0 = bvh->preBuild(TOSTRING(isa) "::BVH" + toString(N) + "BuilderMBlurSAH");
  96. #if PROFILE
  97. profile(2,PROFILE_RUNS,numPrimitives,[&] (ProfileTimer& timer) {
  98. #endif
  99. //const size_t numTimeSteps = scene->getNumTimeSteps<typename Mesh::type_t,true>();
  100. //const size_t numTimeSegments = numTimeSteps-1; assert(numTimeSteps > 1);
  101. /*if (numTimeSegments == 1)
  102. buildSingleSegment(numPrimitives);
  103. else*/
  104. buildMultiSegment(numPrimitives);
  105. #if PROFILE
  106. });
  107. #endif
  108. /* clear temporary data for static geometry */
  109. bvh->cleanup();
  110. bvh->postBuild(t0);
  111. }
  112. #if 0 // No longer compatible when time_ranges are present for geometries. Would have to create temporal nodes sometimes, and put only a single geometry into leaf.
  113. void buildSingleSegment(size_t numPrimitives)
  114. {
  115. /* create primref array */
  116. mvector<PrimRef> prims(scene->device,numPrimitives);
  117. const PrimInfo pinfo = createPrimRefArrayMBlur(scene,gtype_,numPrimitives,prims,bvh->scene->progressInterface,0);
  118. /* early out if no valid primitives */
  119. if (pinfo.size() == 0) { bvh->clear(); return; }
  120. /* estimate acceleration structure size */
  121. const size_t node_bytes = pinfo.size()*sizeof(AABBNodeMB)/(4*N);
  122. const size_t leaf_bytes = size_t(1.2*Primitive::blocks(pinfo.size())*sizeof(Primitive));
  123. bvh->alloc.init_estimate(node_bytes+leaf_bytes);
  124. /* settings for BVH build */
  125. GeneralBVHBuilder::Settings settings;
  126. settings.branchingFactor = N;
  127. settings.maxDepth = BVH::maxBuildDepthLeaf;
  128. settings.logBlockSize = bsr(sahBlockSize);
  129. settings.minLeafSize = min(minLeafSize,maxLeafSize);
  130. settings.maxLeafSize = maxLeafSize;
  131. settings.travCost = travCost;
  132. settings.intCost = intCost;
  133. settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes);
  134. /* build hierarchy */
  135. auto root = BVHBuilderBinnedSAH::build<NodeRecordMB>
  136. (typename BVH::CreateAlloc(bvh),typename BVH::AABBNodeMB::Create(),typename BVH::AABBNodeMB::Set(),
  137. CreateMBlurLeaf<N,Primitive>(bvh,prims.data(),0),bvh->scene->progressInterface,
  138. prims.data(),pinfo,settings);
  139. bvh->set(root.ref,root.lbounds,pinfo.size());
  140. }
  141. #endif
  142. void buildMultiSegment(size_t numPrimitives)
  143. {
  144. /* create primref array */
  145. mvector<PrimRefMB> prims(scene->device,numPrimitives);
  146. PrimInfoMB pinfo = createPrimRefArrayMSMBlur(scene,gtype_,numPrimitives,prims,bvh->scene->progressInterface);
  147. /* early out if no valid primitives */
  148. if (pinfo.size() == 0) { bvh->clear(); return; }
  149. /* estimate acceleration structure size */
  150. const size_t node_bytes = pinfo.num_time_segments*sizeof(AABBNodeMB)/(4*N);
  151. const size_t leaf_bytes = size_t(1.2*Primitive::blocks(pinfo.num_time_segments)*sizeof(Primitive));
  152. bvh->alloc.init_estimate(node_bytes+leaf_bytes);
  153. /* settings for BVH build */
  154. BVHBuilderMSMBlur::Settings settings;
  155. settings.branchingFactor = N;
  156. settings.maxDepth = BVH::maxDepth;
  157. settings.logBlockSize = bsr(sahBlockSize);
  158. settings.minLeafSize = min(minLeafSize,maxLeafSize);
  159. settings.maxLeafSize = maxLeafSize;
  160. settings.travCost = travCost;
  161. settings.intCost = intCost;
  162. settings.singleLeafTimeSegment = Primitive::singleTimeSegment;
  163. settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes);
  164. /* build hierarchy */
  165. auto root =
  166. BVHBuilderMSMBlur::build<NodeRef>(prims,pinfo,scene->device,
  167. RecalculatePrimRef<Mesh>(scene),
  168. typename BVH::CreateAlloc(bvh),
  169. typename BVH::AABBNodeMB4D::Create(),
  170. typename BVH::AABBNodeMB4D::Set(),
  171. CreateMSMBlurLeaf<N,Mesh,Primitive>(bvh),
  172. bvh->scene->progressInterface,
  173. settings);
  174. bvh->set(root.ref,root.lbounds,pinfo.num_time_segments);
  175. }
  176. void clear() {
  177. }
  178. };
  179. /************************************************************************************/
  180. /************************************************************************************/
  181. /************************************************************************************/
  182. /************************************************************************************/
  183. struct GridRecalculatePrimRef
  184. {
  185. Scene* scene;
  186. const SubGridBuildData * const sgrids;
  187. __forceinline GridRecalculatePrimRef (Scene* scene, const SubGridBuildData * const sgrids)
  188. : scene(scene), sgrids(sgrids) {}
  189. __forceinline PrimRefMB operator() (const PrimRefMB& prim, const BBox1f time_range) const
  190. {
  191. const unsigned int geomID = prim.geomID();
  192. const GridMesh* mesh = scene->get<GridMesh>(geomID);
  193. const unsigned int buildID = prim.primID();
  194. const SubGridBuildData &subgrid = sgrids[buildID];
  195. const unsigned int primID = subgrid.primID;
  196. const size_t x = subgrid.x();
  197. const size_t y = subgrid.y();
  198. const LBBox3fa lbounds = mesh->linearBounds(mesh->grid(primID),x,y,time_range);
  199. const unsigned num_time_segments = mesh->numTimeSegments();
  200. const range<int> tbounds = mesh->timeSegmentRange(time_range);
  201. return PrimRefMB (lbounds, tbounds.size(), mesh->time_range, num_time_segments, geomID, buildID);
  202. }
  203. __forceinline LBBox3fa linearBounds(const PrimRefMB& prim, const BBox1f time_range) const {
  204. const unsigned int geomID = prim.geomID();
  205. const GridMesh* mesh = scene->get<GridMesh>(geomID);
  206. const unsigned int buildID = prim.primID();
  207. const SubGridBuildData &subgrid = sgrids[buildID];
  208. const unsigned int primID = subgrid.primID;
  209. const size_t x = subgrid.x();
  210. const size_t y = subgrid.y();
  211. return mesh->linearBounds(mesh->grid(primID),x,y,time_range);
  212. }
  213. };
  214. template<int N>
  215. struct CreateMSMBlurLeafGrid
  216. {
  217. typedef BVHN<N> BVH;
  218. typedef typename BVH::NodeRef NodeRef;
  219. typedef typename BVH::NodeRecordMB4D NodeRecordMB4D;
  220. __forceinline CreateMSMBlurLeafGrid (Scene* scene, BVH* bvh, const SubGridBuildData * const sgrids) : scene(scene), bvh(bvh), sgrids(sgrids) {}
  221. __forceinline const NodeRecordMB4D operator() (const BVHBuilderMSMBlur::BuildRecord& current, const FastAllocator::CachedAllocator& alloc) const
  222. {
  223. const size_t items = current.prims.size();
  224. const size_t start = current.prims.begin();
  225. const PrimRefMB* prims = current.prims.prims->data();
  226. /* collect all subsets with unique geomIDs */
  227. assert(items <= N);
  228. unsigned int geomIDs[N];
  229. unsigned int num_geomIDs = 1;
  230. geomIDs[0] = prims[start].geomID();
  231. for (size_t i=1;i<items;i++)
  232. {
  233. bool found = false;
  234. const unsigned int new_geomID = prims[start+i].geomID();
  235. for (size_t j=0;j<num_geomIDs;j++)
  236. if (new_geomID == geomIDs[j])
  237. { found = true; break; }
  238. if (!found)
  239. geomIDs[num_geomIDs++] = new_geomID;
  240. }
  241. /* allocate all leaf memory in one single block */
  242. SubGridMBQBVHN<N>* accel = (SubGridMBQBVHN<N>*) alloc.malloc1(num_geomIDs*sizeof(SubGridMBQBVHN<N>),BVH::byteAlignment);
  243. typename BVH::NodeRef node = bvh->encodeLeaf((char*)accel,num_geomIDs);
  244. LBBox3fa allBounds = empty;
  245. for (size_t g=0;g<num_geomIDs;g++)
  246. {
  247. const GridMesh* __restrict__ const mesh = scene->get<GridMesh>(geomIDs[g]);
  248. unsigned int x[N];
  249. unsigned int y[N];
  250. unsigned int primID[N];
  251. BBox3fa bounds0[N];
  252. BBox3fa bounds1[N];
  253. unsigned int pos = 0;
  254. for (size_t i=0;i<items;i++)
  255. {
  256. if (unlikely(prims[start+i].geomID() != geomIDs[g])) continue;
  257. const SubGridBuildData &sgrid_bd = sgrids[prims[start+i].primID()];
  258. x[pos] = sgrid_bd.sx;
  259. y[pos] = sgrid_bd.sy;
  260. primID[pos] = sgrid_bd.primID;
  261. const size_t x = sgrid_bd.x();
  262. const size_t y = sgrid_bd.y();
  263. LBBox3fa newBounds = mesh->linearBounds(mesh->grid(sgrid_bd.primID),x,y,current.prims.time_range);
  264. allBounds.extend(newBounds);
  265. bounds0[pos] = newBounds.bounds0;
  266. bounds1[pos] = newBounds.bounds1;
  267. pos++;
  268. }
  269. assert(pos <= N);
  270. new (&accel[g]) SubGridMBQBVHN<N>(x,y,primID,bounds0,bounds1,geomIDs[g],current.prims.time_range.lower,1.0f/current.prims.time_range.size(),pos);
  271. }
  272. return NodeRecordMB4D(node,allBounds,current.prims.time_range);
  273. }
  274. Scene *scene;
  275. BVH* bvh;
  276. const SubGridBuildData * const sgrids;
  277. };
  278. #if 0
  279. template<int N>
  280. struct CreateLeafGridMB
  281. {
  282. typedef BVHN<N> BVH;
  283. typedef typename BVH::NodeRef NodeRef;
  284. typedef typename BVH::NodeRecordMB NodeRecordMB;
  285. __forceinline CreateLeafGridMB (Scene* scene, BVH* bvh, const SubGridBuildData * const sgrids)
  286. : scene(scene), bvh(bvh), sgrids(sgrids) {}
  287. __forceinline NodeRecordMB operator() (const PrimRef* prims, const range<size_t>& set, const FastAllocator::CachedAllocator& alloc) const
  288. {
  289. const size_t items = set.size();
  290. const size_t start = set.begin();
  291. /* collect all subsets with unique geomIDs */
  292. assert(items <= N);
  293. unsigned int geomIDs[N];
  294. unsigned int num_geomIDs = 1;
  295. geomIDs[0] = prims[start].geomID();
  296. for (size_t i=1;i<items;i++)
  297. {
  298. bool found = false;
  299. const unsigned int new_geomID = prims[start+i].geomID();
  300. for (size_t j=0;j<num_geomIDs;j++)
  301. if (new_geomID == geomIDs[j])
  302. { found = true; break; }
  303. if (!found)
  304. geomIDs[num_geomIDs++] = new_geomID;
  305. }
  306. /* allocate all leaf memory in one single block */
  307. SubGridMBQBVHN<N>* accel = (SubGridMBQBVHN<N>*) alloc.malloc1(num_geomIDs*sizeof(SubGridMBQBVHN<N>),BVH::byteAlignment);
  308. typename BVH::NodeRef node = bvh->encodeLeaf((char*)accel,num_geomIDs);
  309. LBBox3fa allBounds = empty;
  310. for (size_t g=0;g<num_geomIDs;g++)
  311. {
  312. const GridMesh* __restrict__ const mesh = scene->get<GridMesh>(geomIDs[g]);
  313. unsigned int x[N];
  314. unsigned int y[N];
  315. unsigned int primID[N];
  316. BBox3fa bounds0[N];
  317. BBox3fa bounds1[N];
  318. unsigned int pos = 0;
  319. for (size_t i=0;i<items;i++)
  320. {
  321. if (unlikely(prims[start+i].geomID() != geomIDs[g])) continue;
  322. const SubGridBuildData &sgrid_bd = sgrids[prims[start+i].primID()];
  323. x[pos] = sgrid_bd.sx;
  324. y[pos] = sgrid_bd.sy;
  325. primID[pos] = sgrid_bd.primID;
  326. const size_t x = sgrid_bd.x();
  327. const size_t y = sgrid_bd.y();
  328. bool MAYBE_UNUSED valid0 = mesh->buildBounds(mesh->grid(sgrid_bd.primID),x,y,0,bounds0[pos]);
  329. bool MAYBE_UNUSED valid1 = mesh->buildBounds(mesh->grid(sgrid_bd.primID),x,y,1,bounds1[pos]);
  330. assert(valid0);
  331. assert(valid1);
  332. allBounds.extend(LBBox3fa(bounds0[pos],bounds1[pos]));
  333. pos++;
  334. }
  335. new (&accel[g]) SubGridMBQBVHN<N>(x,y,primID,bounds0,bounds1,geomIDs[g],0.0f,1.0f,pos);
  336. }
  337. return NodeRecordMB(node,allBounds);
  338. }
  339. Scene *scene;
  340. BVH* bvh;
  341. const SubGridBuildData * const sgrids;
  342. };
  343. #endif
  344. /* Motion blur BVH with 4D nodes and internal time splits */
  345. template<int N>
  346. struct BVHNBuilderMBlurSAHGrid : public Builder
  347. {
  348. typedef BVHN<N> BVH;
  349. typedef typename BVHN<N>::NodeRef NodeRef;
  350. typedef typename BVHN<N>::NodeRecordMB NodeRecordMB;
  351. typedef typename BVHN<N>::AABBNodeMB AABBNodeMB;
  352. BVH* bvh;
  353. Scene* scene;
  354. const size_t sahBlockSize;
  355. const float intCost;
  356. const size_t minLeafSize;
  357. const size_t maxLeafSize;
  358. mvector<SubGridBuildData> sgrids;
  359. BVHNBuilderMBlurSAHGrid (BVH* bvh, Scene* scene, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize)
  360. : bvh(bvh), scene(scene), sahBlockSize(sahBlockSize), intCost(intCost), minLeafSize(minLeafSize), maxLeafSize(min(maxLeafSize,BVH::maxLeafBlocks)), sgrids(scene->device,0) {}
  361. PrimInfo createPrimRefArrayMBlurGrid(Scene* scene, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor, size_t itime)
  362. {
  363. /* first run to get #primitives */
  364. ParallelForForPrefixSumState<PrimInfo> pstate;
  365. Scene::Iterator<GridMesh,true> iter(scene);
  366. pstate.init(iter,size_t(1024));
  367. /* iterate over all meshes in the scene */
  368. PrimInfo pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfo {
  369. PrimInfo pinfo(empty);
  370. for (size_t j=r.begin(); j<r.end(); j++)
  371. {
  372. if (!mesh->valid(j,range<size_t>(0,1))) continue;
  373. BBox3fa bounds = empty;
  374. const PrimRef prim(bounds,unsigned(geomID),unsigned(j));
  375. pinfo.add_center2(prim,mesh->getNumSubGrids(j));
  376. }
  377. return pinfo;
  378. }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
  379. size_t numPrimitives = pinfo.size();
  380. if (numPrimitives == 0) return pinfo;
  381. /* resize arrays */
  382. sgrids.resize(numPrimitives);
  383. prims.resize(numPrimitives);
  384. /* second run to fill primrefs and SubGridBuildData arrays */
  385. 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 {
  386. k = base.size();
  387. size_t p_index = k;
  388. PrimInfo pinfo(empty);
  389. for (size_t j=r.begin(); j<r.end(); j++)
  390. {
  391. const GridMesh::Grid &g = mesh->grid(j);
  392. if (!mesh->valid(j,range<size_t>(0,1))) continue;
  393. for (unsigned int y=0; y<g.resY-1u; y+=2)
  394. for (unsigned int x=0; x<g.resX-1u; x+=2)
  395. {
  396. BBox3fa bounds = empty;
  397. if (!mesh->buildBounds(g,x,y,itime,bounds)) continue; // get bounds of subgrid
  398. const PrimRef prim(bounds,unsigned(geomID),unsigned(p_index));
  399. pinfo.add_center2(prim);
  400. sgrids[p_index] = SubGridBuildData(x | g.get3x3FlagsX(x), y | g.get3x3FlagsY(y), unsigned(j));
  401. prims[p_index++] = prim;
  402. }
  403. }
  404. return pinfo;
  405. }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
  406. assert(pinfo.size() == numPrimitives);
  407. return pinfo;
  408. }
  409. PrimInfoMB createPrimRefArrayMSMBlurGrid(Scene* scene, mvector<PrimRefMB>& prims, BuildProgressMonitor& progressMonitor, BBox1f t0t1 = BBox1f(0.0f,1.0f))
  410. {
  411. /* first run to get #primitives */
  412. ParallelForForPrefixSumState<PrimInfoMB> pstate;
  413. Scene::Iterator<GridMesh,true> iter(scene);
  414. pstate.init(iter,size_t(1024));
  415. /* iterate over all meshes in the scene */
  416. 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 {
  417. PrimInfoMB pinfoMB(empty);
  418. for (size_t j=r.begin(); j<r.end(); j++)
  419. {
  420. if (!mesh->valid(j, mesh->timeSegmentRange(t0t1))) continue;
  421. LBBox3fa bounds(empty);
  422. PrimInfoMB gridMB(0,mesh->getNumSubGrids(j));
  423. pinfoMB.merge(gridMB);
  424. }
  425. return pinfoMB;
  426. }, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });
  427. size_t numPrimitives = pinfoMB.size();
  428. if (numPrimitives == 0) return pinfoMB;
  429. /* resize arrays */
  430. sgrids.resize(numPrimitives);
  431. prims.resize(numPrimitives);
  432. /* second run to fill primrefs and SubGridBuildData arrays */
  433. 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 {
  434. k = base.size();
  435. size_t p_index = k;
  436. PrimInfoMB pinfoMB(empty);
  437. for (size_t j=r.begin(); j<r.end(); j++)
  438. {
  439. if (!mesh->valid(j, mesh->timeSegmentRange(t0t1))) continue;
  440. const GridMesh::Grid &g = mesh->grid(j);
  441. for (unsigned int y=0; y<g.resY-1u; y+=2)
  442. for (unsigned int x=0; x<g.resX-1u; x+=2)
  443. {
  444. const PrimRefMB prim(mesh->linearBounds(g,x,y,t0t1),mesh->numTimeSegments(),mesh->time_range,mesh->numTimeSegments(),unsigned(geomID),unsigned(p_index));
  445. pinfoMB.add_primref(prim);
  446. sgrids[p_index] = SubGridBuildData(x | g.get3x3FlagsX(x), y | g.get3x3FlagsY(y), unsigned(j));
  447. prims[p_index++] = prim;
  448. }
  449. }
  450. return pinfoMB;
  451. }, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });
  452. assert(pinfoMB.size() == numPrimitives);
  453. pinfoMB.time_range = t0t1;
  454. return pinfoMB;
  455. }
  456. void build()
  457. {
  458. /* skip build for empty scene */
  459. const size_t numPrimitives = scene->getNumPrimitives(GridMesh::geom_type,true);
  460. if (numPrimitives == 0) { bvh->clear(); return; }
  461. double t0 = bvh->preBuild(TOSTRING(isa) "::BVH" + toString(N) + "BuilderMBlurSAHGrid");
  462. //const size_t numTimeSteps = scene->getNumTimeSteps<GridMesh,true>();
  463. //const size_t numTimeSegments = numTimeSteps-1; assert(numTimeSteps > 1);
  464. //if (numTimeSegments == 1)
  465. // buildSingleSegment(numPrimitives);
  466. //else
  467. buildMultiSegment(numPrimitives);
  468. /* clear temporary data for static geometry */
  469. bvh->cleanup();
  470. bvh->postBuild(t0);
  471. }
  472. #if 0
  473. void buildSingleSegment(size_t numPrimitives)
  474. {
  475. /* create primref array */
  476. mvector<PrimRef> prims(scene->device,numPrimitives);
  477. const PrimInfo pinfo = createPrimRefArrayMBlurGrid(scene,prims,bvh->scene->progressInterface,0);
  478. /* early out if no valid primitives */
  479. if (pinfo.size() == 0) { bvh->clear(); return; }
  480. /* estimate acceleration structure size */
  481. const size_t node_bytes = pinfo.size()*sizeof(AABBNodeMB)/(4*N);
  482. //TODO: check leaf_bytes
  483. const size_t leaf_bytes = size_t(1.2*(float)numPrimitives/N * sizeof(SubGridQBVHN<N>));
  484. bvh->alloc.init_estimate(node_bytes+leaf_bytes);
  485. /* settings for BVH build */
  486. GeneralBVHBuilder::Settings settings;
  487. settings.branchingFactor = N;
  488. settings.maxDepth = BVH::maxBuildDepthLeaf;
  489. settings.logBlockSize = bsr(sahBlockSize);
  490. settings.minLeafSize = min(minLeafSize,maxLeafSize);
  491. settings.maxLeafSize = maxLeafSize;
  492. settings.travCost = travCost;
  493. settings.intCost = intCost;
  494. settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes);
  495. /* build hierarchy */
  496. auto root = BVHBuilderBinnedSAH::build<NodeRecordMB>
  497. (typename BVH::CreateAlloc(bvh),
  498. typename BVH::AABBNodeMB::Create(),
  499. typename BVH::AABBNodeMB::Set(),
  500. CreateLeafGridMB<N>(scene,bvh,sgrids.data()),
  501. bvh->scene->progressInterface,
  502. prims.data(),pinfo,settings);
  503. bvh->set(root.ref,root.lbounds,pinfo.size());
  504. }
  505. #endif
  506. void buildMultiSegment(size_t numPrimitives)
  507. {
  508. /* create primref array */
  509. mvector<PrimRefMB> prims(scene->device,numPrimitives);
  510. PrimInfoMB pinfo = createPrimRefArrayMSMBlurGrid(scene,prims,bvh->scene->progressInterface);
  511. /* early out if no valid primitives */
  512. if (pinfo.size() == 0) { bvh->clear(); return; }
  513. GridRecalculatePrimRef recalculatePrimRef(scene,sgrids.data());
  514. /* estimate acceleration structure size */
  515. const size_t node_bytes = pinfo.num_time_segments*sizeof(AABBNodeMB)/(4*N);
  516. //FIXME: check leaf_bytes
  517. //const size_t leaf_bytes = size_t(1.2*Primitive::blocks(pinfo.num_time_segments)*sizeof(SubGridQBVHN<N>));
  518. const size_t leaf_bytes = size_t(1.2*(float)numPrimitives/N * sizeof(SubGridQBVHN<N>));
  519. bvh->alloc.init_estimate(node_bytes+leaf_bytes);
  520. /* settings for BVH build */
  521. BVHBuilderMSMBlur::Settings settings;
  522. settings.branchingFactor = N;
  523. settings.maxDepth = BVH::maxDepth;
  524. settings.logBlockSize = bsr(sahBlockSize);
  525. settings.minLeafSize = min(minLeafSize,maxLeafSize);
  526. settings.maxLeafSize = maxLeafSize;
  527. settings.travCost = travCost;
  528. settings.intCost = intCost;
  529. settings.singleLeafTimeSegment = false;
  530. settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes);
  531. /* build hierarchy */
  532. auto root =
  533. BVHBuilderMSMBlur::build<NodeRef>(prims,pinfo,scene->device,
  534. recalculatePrimRef,
  535. typename BVH::CreateAlloc(bvh),
  536. typename BVH::AABBNodeMB4D::Create(),
  537. typename BVH::AABBNodeMB4D::Set(),
  538. CreateMSMBlurLeafGrid<N>(scene,bvh,sgrids.data()),
  539. bvh->scene->progressInterface,
  540. settings);
  541. bvh->set(root.ref,root.lbounds,pinfo.num_time_segments);
  542. }
  543. void clear() {
  544. }
  545. };
  546. /************************************************************************************/
  547. /************************************************************************************/
  548. /************************************************************************************/
  549. /************************************************************************************/
  550. #if defined(EMBREE_GEOMETRY_TRIANGLE)
  551. Builder* BVH4Triangle4iMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<4,TriangleMesh,Triangle4i>((BVH4*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_TRIANGLE_MESH); }
  552. Builder* BVH4Triangle4vMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<4,TriangleMesh,Triangle4vMB>((BVH4*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_TRIANGLE_MESH); }
  553. #if defined(__AVX__)
  554. Builder* BVH8Triangle4iMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<8,TriangleMesh,Triangle4i>((BVH8*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_TRIANGLE_MESH); }
  555. Builder* BVH8Triangle4vMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<8,TriangleMesh,Triangle4vMB>((BVH8*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_TRIANGLE_MESH); }
  556. #endif
  557. #endif
  558. #if defined(EMBREE_GEOMETRY_QUAD)
  559. Builder* BVH4Quad4iMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<4,QuadMesh,Quad4i>((BVH4*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_QUAD_MESH); }
  560. #if defined(__AVX__)
  561. Builder* BVH8Quad4iMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<8,QuadMesh,Quad4i>((BVH8*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_QUAD_MESH); }
  562. #endif
  563. #endif
  564. #if defined(EMBREE_GEOMETRY_USER)
  565. Builder* BVH4VirtualMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) {
  566. int minLeafSize = scene->device->object_accel_mb_min_leaf_size;
  567. int maxLeafSize = scene->device->object_accel_mb_max_leaf_size;
  568. return new BVHNBuilderMBlurSAH<4,UserGeometry,Object>((BVH4*)bvh,scene,4,1.0f,minLeafSize,maxLeafSize,Geometry::MTY_USER_GEOMETRY);
  569. }
  570. #if defined(__AVX__)
  571. Builder* BVH8VirtualMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) {
  572. int minLeafSize = scene->device->object_accel_mb_min_leaf_size;
  573. int maxLeafSize = scene->device->object_accel_mb_max_leaf_size;
  574. return new BVHNBuilderMBlurSAH<8,UserGeometry,Object>((BVH8*)bvh,scene,8,1.0f,minLeafSize,maxLeafSize,Geometry::MTY_USER_GEOMETRY);
  575. }
  576. #endif
  577. #endif
  578. #if defined(EMBREE_GEOMETRY_INSTANCE)
  579. Builder* BVH4InstanceMBSceneBuilderSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype) { return new BVHNBuilderMBlurSAH<4,Instance,InstancePrimitive>((BVH4*)bvh,scene,4,1.0f,1,1,gtype); }
  580. #if defined(__AVX__)
  581. Builder* BVH8InstanceMBSceneBuilderSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype) { return new BVHNBuilderMBlurSAH<8,Instance,InstancePrimitive>((BVH8*)bvh,scene,8,1.0f,1,1,gtype); }
  582. #endif
  583. #endif
  584. #if defined(EMBREE_GEOMETRY_GRID)
  585. Builder* BVH4GridMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAHGrid<4>((BVH4*)bvh,scene,4,1.0f,4,4); }
  586. #if defined(__AVX__)
  587. Builder* BVH8GridMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAHGrid<8>((BVH8*)bvh,scene,8,1.0f,8,8); }
  588. #endif
  589. #endif
  590. }
  591. }