bvh_builder_subdiv.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  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. #include "bvh.h"
  17. #if defined(EMBREE_GEOMETRY_SUBDIV)
  18. #include "bvh_refit.h"
  19. #include "bvh_builder.h"
  20. #include "../builders/primrefgen.h"
  21. #include "../builders/bvh_builder_sah.h"
  22. #include "../../common/algorithms/parallel_for_for.h"
  23. #include "../../common/algorithms/parallel_for_for_prefix_sum.h"
  24. #include "../subdiv/bezier_curve.h"
  25. #include "../subdiv/bspline_curve.h"
  26. #include "../geometry/subdivpatch1cached.h"
  27. #include "../geometry/grid_soa.h"
  28. namespace embree
  29. {
  30. namespace isa
  31. {
  32. typedef FastAllocator::ThreadLocal2 Allocator;
  33. template<int N>
  34. struct BVHNSubdivPatch1EagerBuilderBinnedSAHClass : public Builder
  35. {
  36. ALIGNED_STRUCT;
  37. typedef BVHN<N> BVH;
  38. typedef typename BVH::NodeRef NodeRef;
  39. BVH* bvh;
  40. Scene* scene;
  41. mvector<PrimRef> prims;
  42. ParallelForForPrefixSumState<PrimInfo> pstate;
  43. BVHNSubdivPatch1EagerBuilderBinnedSAHClass (BVH* bvh, Scene* scene)
  44. : bvh(bvh), scene(scene), prims(scene->device) {}
  45. #define SUBGRID 9
  46. static unsigned getNumEagerLeaves(unsigned width, unsigned height) {
  47. const unsigned w = (width+SUBGRID-1)/SUBGRID;
  48. const unsigned h = (height+SUBGRID-1)/SUBGRID;
  49. return w*h;
  50. }
  51. __forceinline static unsigned createEager(SubdivPatch1Base& patch, Scene* scene, SubdivMesh* mesh, unsigned primID, FastAllocator::ThreadLocal& alloc, PrimRef* prims)
  52. {
  53. unsigned NN = 0;
  54. const unsigned x0 = 0, x1 = patch.grid_u_res-1;
  55. const unsigned y0 = 0, y1 = patch.grid_v_res-1;
  56. for (unsigned y=y0; y<y1; y+=SUBGRID-1)
  57. {
  58. for (unsigned x=x0; x<x1; x+=SUBGRID-1)
  59. {
  60. const unsigned lx0 = x, lx1 = min(lx0+SUBGRID-1,x1);
  61. const unsigned ly0 = y, ly1 = min(ly0+SUBGRID-1,y1);
  62. BBox3fa bounds;
  63. GridSOA* leaf = GridSOA::create(&patch,1,1,lx0,lx1,ly0,ly1,scene,alloc,&bounds);
  64. *prims = PrimRef(bounds,BVH4::encodeTypedLeaf(leaf,1)); prims++;
  65. NN++;
  66. }
  67. }
  68. return NN;
  69. }
  70. void build()
  71. {
  72. /* initialize all half edge structures */
  73. const size_t numPrimitives = scene->getNumPrimitives<SubdivMesh,false>();
  74. if (numPrimitives > 0 || scene->isInterpolatable()) {
  75. Scene::Iterator<SubdivMesh> iter(scene,scene->isInterpolatable());
  76. parallel_for(size_t(0),iter.size(),[&](const range<size_t>& range) {
  77. for (size_t i=range.begin(); i<range.end(); i++)
  78. if (iter[i]) iter[i]->initializeHalfEdgeStructures();
  79. });
  80. }
  81. /* skip build for empty scene */
  82. if (numPrimitives == 0) {
  83. prims.resize(numPrimitives);
  84. bvh->set(BVH::emptyNode,empty,0);
  85. return;
  86. }
  87. //bvh->alloc.reset();
  88. bvh->alloc.init_estimate(numPrimitives*sizeof(PrimRef));
  89. double t0 = bvh->preBuild(TOSTRING(isa) "::BVH" + toString(N) + "SubdivPatch1EagerBuilderBinnedSAH");
  90. auto progress = [&] (size_t dn) { bvh->scene->progressMonitor(double(dn)); };
  91. auto virtualprogress = BuildProgressMonitorFromClosure(progress);
  92. /* initialize allocator and parallel_for_for_prefix_sum */
  93. Scene::Iterator<SubdivMesh> iter(scene);
  94. pstate.init(iter,size_t(1024));
  95. PrimInfo pinfo1 = parallel_for_for_prefix_sum( pstate, iter, PrimInfo(empty), [&](SubdivMesh* mesh, const range<size_t>& r, size_t k, const PrimInfo& base) -> PrimInfo
  96. {
  97. size_t p = 0;
  98. size_t g = 0;
  99. for (size_t f=r.begin(); f!=r.end(); ++f) {
  100. if (!mesh->valid(f)) continue;
  101. patch_eval_subdivision(mesh->getHalfEdge(0,f),[&](const Vec2f uv[4], const int subdiv[4], const float edge_level[4], int subPatch)
  102. {
  103. float level[4]; SubdivPatch1Base::computeEdgeLevels(edge_level,subdiv,level);
  104. Vec2i grid = SubdivPatch1Base::computeGridSize(level);
  105. size_t num = getNumEagerLeaves(grid.x,grid.y);
  106. g+=num;
  107. p++;
  108. });
  109. }
  110. return PrimInfo(p,g,empty,empty);
  111. }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo(a.begin+b.begin,a.end+b.end,empty,empty); });
  112. size_t numSubPatches = pinfo1.begin;
  113. if (numSubPatches == 0) {
  114. bvh->set(BVH::emptyNode,empty,0);
  115. return;
  116. }
  117. prims.resize(pinfo1.end);
  118. if (pinfo1.end == 0) {
  119. bvh->set(BVH::emptyNode,empty,0);
  120. return;
  121. }
  122. PrimInfo pinfo3 = parallel_for_for_prefix_sum( pstate, iter, PrimInfo(empty), [&](SubdivMesh* mesh, const range<size_t>& r, size_t k, const PrimInfo& base) -> PrimInfo
  123. {
  124. FastAllocator::ThreadLocal& alloc = *bvh->alloc.threadLocal();
  125. PrimInfo s(empty);
  126. for (size_t f=r.begin(); f!=r.end(); ++f) {
  127. if (!mesh->valid(f)) continue;
  128. patch_eval_subdivision(mesh->getHalfEdge(0,f),[&](const Vec2f uv[4], const int subdiv[4], const float edge_level[4], int subPatch)
  129. {
  130. SubdivPatch1Base patch(mesh->id,unsigned(f),subPatch,mesh,0,uv,edge_level,subdiv,VSIZEX);
  131. size_t num = createEager(patch,scene,mesh,unsigned(f),alloc,&prims[base.end+s.end]);
  132. assert(num == getNumEagerLeaves(patch.grid_u_res,patch.grid_v_res));
  133. for (size_t i=0; i<num; i++)
  134. s.add(prims[base.end+s.end].bounds());
  135. s.begin++;
  136. });
  137. }
  138. return s;
  139. }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a, b); });
  140. PrimInfo pinfo(pinfo3.end,pinfo3.geomBounds,pinfo3.centBounds);
  141. auto createLeaf = [&] (const BVHBuilderBinnedSAH::BuildRecord& current, Allocator* alloc) -> NodeRef {
  142. assert(current.prims.size() == 1);
  143. size_t leaf = (size_t) prims[current.prims.begin()].ID();
  144. return NodeRef(leaf);
  145. };
  146. /* settings for BVH build */
  147. GeneralBVHBuilder::Settings settings;
  148. settings.logBlockSize = __bsr(N);
  149. settings.minLeafSize = 1;
  150. settings.maxLeafSize = 1;
  151. settings.travCost = 1.0f;
  152. settings.intCost = 1.0f;
  153. settings.singleThreadThreshold = DEFAULT_SINGLE_THREAD_THRESHOLD;
  154. NodeRef root = BVHNBuilderVirtual<N>::build(&bvh->alloc,createLeaf,virtualprogress,prims.data(),pinfo,settings);
  155. bvh->set(root,LBBox3fa(pinfo.geomBounds),pinfo.size());
  156. bvh->layoutLargeNodes(size_t(pinfo.size()*0.005f));
  157. /* clear temporary data for static geometry */
  158. if (scene->isStatic()) {
  159. prims.clear();
  160. bvh->shrink();
  161. }
  162. bvh->cleanup();
  163. bvh->postBuild(t0);
  164. }
  165. void clear() {
  166. prims.clear();
  167. }
  168. };
  169. // =======================================================================================================
  170. // =======================================================================================================
  171. // =======================================================================================================
  172. template<int N, bool mblur>
  173. struct BVHNSubdivPatch1CachedBuilderBinnedSAHClass : public Builder, public BVHNRefitter<N>::LeafBoundsInterface
  174. {
  175. ALIGNED_STRUCT;
  176. typedef BVHN<N> BVH;
  177. typedef typename BVH::NodeRef NodeRef;
  178. typedef typename BVHN<N>::Allocator BVH_Allocator;
  179. BVH* bvh;
  180. std::unique_ptr<BVHNRefitter<N>> refitter;
  181. Scene* scene;
  182. size_t numTimeSteps;
  183. mvector<PrimRef> prims;
  184. mvector<BBox3fa> bounds;
  185. ParallelForForPrefixSumState<PrimInfo> pstate;
  186. size_t numSubdivEnableDisableEvents;
  187. bool cached;
  188. BVHNSubdivPatch1CachedBuilderBinnedSAHClass (BVH* bvh, Scene* scene, bool cached)
  189. : bvh(bvh), refitter(nullptr), scene(scene), numTimeSteps(0), prims(scene->device), bounds(scene->device), numSubdivEnableDisableEvents(0), cached(cached) {}
  190. virtual const BBox3fa leafBounds (NodeRef& ref) const
  191. {
  192. if (ref == BVH::emptyNode) return BBox3fa(empty);
  193. size_t num; SubdivPatch1Cached *sptr = (SubdivPatch1Cached*)ref.leaf(num);
  194. const size_t index = ((size_t)sptr - (size_t)bvh->subdiv_patches.data()) / sizeof(SubdivPatch1Cached);
  195. return prims[index].bounds();
  196. }
  197. bool initializeHalfEdges(size_t& numPrimitives)
  198. {
  199. /* initialize all half edge structures */
  200. bool fastUpdateMode = true;
  201. numPrimitives = scene->getNumPrimitives<SubdivMesh,mblur>();
  202. if (numPrimitives > 0 || scene->isInterpolatable())
  203. {
  204. Scene::Iterator<SubdivMesh,mblur> iter(scene,scene->isInterpolatable());
  205. fastUpdateMode = parallel_reduce(size_t(0),iter.size(),true,[&](const range<size_t>& range)
  206. {
  207. bool fastUpdate = true;
  208. for (size_t i=range.begin(); i<range.end(); i++)
  209. {
  210. if (!iter[i]) continue;
  211. fastUpdate &= !iter[i]->faceVertices.isModified();
  212. fastUpdate &= !iter[i]->holes.isModified();
  213. fastUpdate &= iter[i]->levels.isModified();
  214. fastUpdate &= !iter[i]->topology[0].vertexIndices.isModified();
  215. fastUpdate &= !iter[i]->edge_creases.isModified();
  216. fastUpdate &= !iter[i]->edge_crease_weights.isModified();
  217. fastUpdate &= !iter[i]->vertex_creases.isModified();
  218. fastUpdate &= !iter[i]->vertex_crease_weights.isModified();
  219. iter[i]->initializeHalfEdgeStructures();
  220. //iter[i]->patch_eval_trees.resize(iter[i]->size()*numTimeSteps);
  221. }
  222. return fastUpdate;
  223. }, [](const bool a, const bool b) { return a && b; });
  224. }
  225. /* only enable fast mode if no subdiv mesh got enabled or disabled since last run */
  226. fastUpdateMode &= numSubdivEnableDisableEvents == scene->numSubdivEnableDisableEvents;
  227. numSubdivEnableDisableEvents = scene->numSubdivEnableDisableEvents;
  228. return fastUpdateMode;
  229. }
  230. void countSubPatches(size_t& numSubPatches, size_t& numSubPatchesMB)
  231. {
  232. Scene::Iterator<SubdivMesh,mblur> iter(scene);
  233. pstate.init(iter,size_t(1024));
  234. PrimInfo pinfo = parallel_for_for_prefix_sum( pstate, iter, PrimInfo(empty), [&](SubdivMesh* mesh, const range<size_t>& r, size_t k, const PrimInfo& base) -> PrimInfo
  235. {
  236. size_t s = 0;
  237. size_t sMB = 0;
  238. for (size_t f=r.begin(); f!=r.end(); ++f)
  239. {
  240. if (!mesh->valid(f)) continue;
  241. size_t count = patch_eval_subdivision_count(mesh->getHalfEdge(0,f));
  242. s += count;
  243. sMB += count * mesh->numTimeSteps;
  244. }
  245. return PrimInfo(s,sMB,empty,empty);
  246. }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo(a.begin+b.begin,a.end+b.end,empty,empty); });
  247. numSubPatches = pinfo.begin;
  248. numSubPatchesMB = pinfo.end;
  249. }
  250. PrimInfo updatePrimRefArray(size_t t)
  251. {
  252. SubdivPatch1Cached* const subdiv_patches = (SubdivPatch1Cached*) bvh->subdiv_patches.data();
  253. const PrimInfo pinfo = parallel_reduce(size_t(0), prims.size(), PrimInfo(empty), [&] (const range<size_t>& r) -> PrimInfo
  254. {
  255. PrimInfo pinfo(empty);
  256. for (size_t i = r.begin(); i < r.end(); i++) {
  257. size_t patchIndexMB = prims[i].ID();
  258. BBox3fa bound;
  259. if (mblur) {
  260. size_t patchNumTimeSteps = scene->get<SubdivMesh>(subdiv_patches[patchIndexMB].geom)->numTimeSteps;
  261. Geometry::buildBounds([&] (size_t itime, BBox3fa& bbox) -> bool
  262. {
  263. bbox = bounds[patchIndexMB+itime];
  264. return true;
  265. },
  266. t, numTimeSteps, patchNumTimeSteps, bound);
  267. } else {
  268. bound = bounds[patchIndexMB];
  269. }
  270. prims[i] = PrimRef(bound,patchIndexMB);
  271. pinfo.add(bound);
  272. }
  273. return pinfo;
  274. }, [] (const PrimInfo& a, const PrimInfo& b) { return PrimInfo::merge(a,b); });
  275. return pinfo;
  276. }
  277. void rebuild(size_t numPrimitives)
  278. {
  279. SubdivPatch1Cached* const subdiv_patches = (SubdivPatch1Cached*) bvh->subdiv_patches.data();
  280. //bvh->alloc.reset();
  281. bvh->alloc.init_estimate(numPrimitives*sizeof(PrimRef)*numTimeSteps);
  282. Scene::Iterator<SubdivMesh,mblur> iter(scene);
  283. parallel_for_for_prefix_sum( pstate, iter, PrimInfo(empty), [&](SubdivMesh* mesh, const range<size_t>& r, size_t k, const PrimInfo& base) -> PrimInfo
  284. {
  285. size_t s = 0;
  286. size_t sMB = 0;
  287. for (size_t f=r.begin(); f!=r.end(); ++f)
  288. {
  289. if (!mesh->valid(f)) continue;
  290. BVH_Allocator alloc(bvh);
  291. //for (size_t t=0; t<numTimeSteps; t++)
  292. //mesh->patch_eval_trees[f*numTimeSteps+t] = Patch3fa::create(alloc, mesh->getHalfEdge(0,f), mesh->getVertexBuffer(t).getPtr(), mesh->getVertexBuffer(t).getStride());
  293. patch_eval_subdivision(mesh->getHalfEdge(0,f),[&](const Vec2f uv[4], const int subdiv[4], const float edge_level[4], int subPatch)
  294. {
  295. const size_t patchIndex = base.begin+s;
  296. const size_t patchIndexMB = base.end+sMB;
  297. assert(patchIndex < numPrimitives);
  298. for (size_t t=0; t<mesh->numTimeSteps; t++)
  299. {
  300. SubdivPatch1Base& patch = subdiv_patches[patchIndexMB+t];
  301. new (&patch) SubdivPatch1Cached(mesh->id,unsigned(f),subPatch,mesh,t,uv,edge_level,subdiv,VSIZEX);
  302. }
  303. if (cached)
  304. {
  305. for (size_t t=0; t<mesh->numTimeSteps; t++)
  306. {
  307. SubdivPatch1Base& patch = subdiv_patches[patchIndexMB+t];
  308. BBox3fa bound = evalGridBounds(patch,0,patch.grid_u_res-1,0,patch.grid_v_res-1,patch.grid_u_res,patch.grid_v_res,mesh);
  309. bounds[patchIndexMB+t] = bound;
  310. }
  311. }
  312. else
  313. {
  314. SubdivPatch1Base& patch0 = subdiv_patches[patchIndexMB];
  315. patch0.root_ref.set((int64_t) GridSOA::create(&patch0,(unsigned)mesh->numTimeSteps,(unsigned)numTimeSteps,scene,alloc,&bounds[patchIndexMB]));
  316. }
  317. prims[patchIndex] = PrimRef(empty,patchIndexMB);
  318. s++;
  319. sMB += mesh->numTimeSteps;
  320. });
  321. }
  322. return PrimInfo(s,sMB,empty,empty);
  323. }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo(a.begin+b.begin,a.end+b.end,empty,empty); });
  324. auto virtualprogress = BuildProgressMonitorFromClosure([&] (size_t dn) {
  325. //bvh->scene->progressMonitor(double(dn)); // FIXME: triggers GCC compiler bug
  326. });
  327. /* build normal BVH over patches */
  328. if (!mblur)
  329. {
  330. auto createLeaf = [&] (const BVHBuilderBinnedSAH::BuildRecord& current, Allocator* alloc) -> NodeRef {
  331. assert(current.prims.size() == 1);
  332. const size_t patchIndex = prims[current.prims.begin()].ID();
  333. return bvh->encodeLeaf((char*)&subdiv_patches[patchIndex],1);
  334. };
  335. /* create primrefs */
  336. const PrimInfo pinfo = updatePrimRefArray(0);
  337. /* settings for BVH build */
  338. GeneralBVHBuilder::Settings settings;
  339. settings.logBlockSize = __bsr(N);
  340. settings.minLeafSize = 1;
  341. settings.maxLeafSize = 1;
  342. settings.travCost = 1.0f;
  343. settings.intCost = 1.0f;
  344. settings.singleThreadThreshold = DEFAULT_SINGLE_THREAD_THRESHOLD;
  345. /* call BVH builder */
  346. NodeRef root = BVHNBuilderVirtual<N>::build(&bvh->alloc,createLeaf,virtualprogress,prims.data(),pinfo,settings);
  347. bvh->set(root,LBBox3fa(pinfo.geomBounds),pinfo.size());
  348. bvh->layoutLargeNodes(size_t(pinfo.size()*0.005f));
  349. }
  350. /* build MBlur BVH over patches */
  351. else
  352. {
  353. /* allocate buffers */
  354. const size_t numTimeSegments = bvh->numTimeSteps-1; assert(bvh->numTimeSteps > 1);
  355. NodeRef* roots = (NodeRef*) bvh->alloc.threadLocal()->malloc(sizeof(NodeRef)*numTimeSegments,BVH::byteNodeAlignment);
  356. /* build BVH for each timestep */
  357. avector<BBox3fa> boxes(bvh->numTimeSteps);
  358. size_t num_bvh_primitives = 0;
  359. for (size_t t=0; t<numTimeSegments; t++)
  360. {
  361. auto createLeaf = [&] (const BVHBuilderBinnedSAH::BuildRecord& current, Allocator* alloc) -> std::pair<NodeRef,LBBox3fa> {
  362. assert(current.prims.size() == 1);
  363. const size_t patchIndexMB = prims[current.prims.begin()].ID();
  364. SubdivPatch1Base& patch = subdiv_patches[patchIndexMB+0];
  365. NodeRef ref = bvh->encodeLeaf((char*)&patch,1);
  366. size_t patchNumTimeSteps = scene->get<SubdivMesh>(patch.geom)->numTimeSteps;
  367. LBBox3fa lbounds = Geometry::linearBounds([&] (size_t itime) { return bounds[patchIndexMB+itime]; },
  368. t, numTimeSteps, patchNumTimeSteps);
  369. return std::make_pair(ref,lbounds);
  370. };
  371. /* create primrefs */
  372. const PrimInfo pinfo = updatePrimRefArray(t);
  373. /* settings for BVH build */
  374. GeneralBVHBuilder::Settings settings;
  375. settings.logBlockSize = __bsr(N);
  376. settings.minLeafSize = 1;
  377. settings.maxLeafSize = 1;
  378. settings.travCost = 1.0f;
  379. settings.intCost = 1.0f;
  380. settings.singleThreadThreshold = DEFAULT_SINGLE_THREAD_THRESHOLD;
  381. /* call BVH builder */
  382. NodeRef root; LBBox3fa tbounds;
  383. std::tie(root, tbounds) = BVHNBuilderMblurVirtual<N>::build(&bvh->alloc,createLeaf,bvh->scene->progressInterface,prims.data(),pinfo,settings);
  384. roots[t] = root;
  385. boxes[t+0] = tbounds.bounds0;
  386. boxes[t+1] = tbounds.bounds1;
  387. num_bvh_primitives = max(num_bvh_primitives,pinfo.size());
  388. }
  389. bvh->set(NodeRef((size_t)roots),LBBox3fa(boxes),num_bvh_primitives);
  390. bvh->msmblur = true;
  391. }
  392. }
  393. void cachedUpdate(size_t numPrimitives)
  394. {
  395. SubdivPatch1Cached* const subdiv_patches = (SubdivPatch1Cached*) bvh->subdiv_patches.data();
  396. Scene::Iterator<SubdivMesh,mblur> iter(scene);
  397. parallel_for_for_prefix_sum( pstate, iter, PrimInfo(empty), [&](SubdivMesh* mesh, const range<size_t>& r, size_t k, const PrimInfo& base) -> PrimInfo
  398. {
  399. size_t s = 0;
  400. for (size_t f=r.begin(); f!=r.end(); ++f)
  401. {
  402. if (!mesh->valid(f)) continue;
  403. patch_eval_subdivision(mesh->getHalfEdge(0,f),[&](const Vec2f uv[4], const int subdiv[4], const float edge_level[4], int subPatch)
  404. {
  405. const size_t patchIndex = base.begin+s;
  406. assert(patchIndex < numPrimitives);
  407. SubdivPatch1Base& patch = subdiv_patches[patchIndex];
  408. BBox3fa bound = empty;
  409. bool grid_changed = patch.updateEdgeLevels(edge_level,subdiv,mesh,VSIZEX);
  410. if (grid_changed) {
  411. patch.resetRootRef();
  412. bound = evalGridBounds(patch,0,patch.grid_u_res-1,0,patch.grid_v_res-1,patch.grid_u_res,patch.grid_v_res,mesh);
  413. }
  414. else {
  415. bound = bounds[patchIndex];
  416. }
  417. bounds[patchIndex] = bound;
  418. prims[patchIndex] = PrimRef(bound,patchIndex);
  419. s++;
  420. });
  421. }
  422. return PrimInfo(s,s,empty,empty);
  423. }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo(a.begin+b.begin,a.end+b.end,empty,empty); });
  424. /* refit BVH over patches */
  425. if (!refitter)
  426. refitter.reset(new BVHNRefitter<N>(bvh,*(typename BVHNRefitter<N>::LeafBoundsInterface*)this));
  427. refitter->refit();
  428. }
  429. void build()
  430. {
  431. bvh->numTimeSteps = scene->getNumTimeSteps<SubdivMesh,mblur>();
  432. numTimeSteps = bvh->numTimeSteps;
  433. /* initialize all half edge structures */
  434. size_t numPatches;
  435. bool fastUpdateMode = initializeHalfEdges(numPatches);
  436. //static size_t counter = 0; if ((++counter) % 16 == 0) fastUpdateMode = false;
  437. /* skip build for empty scene */
  438. if (numPatches == 0) {
  439. prims.resize(numPatches);
  440. bounds.resize(numPatches);
  441. bvh->set(BVH::emptyNode,empty,0);
  442. return;
  443. }
  444. double t0 = bvh->preBuild(TOSTRING(isa) "::BVH" + toString(N) + "SubdivPatch1" + (mblur ? "MBlur" : "") + (cached ? "Cached" : "") + "BuilderBinnedSAH");
  445. /* calculate number of primitives (some patches need initial subdivision) */
  446. size_t numSubPatches, numSubPatchesMB;
  447. countSubPatches(numSubPatches, numSubPatchesMB);
  448. prims.resize(numSubPatches);
  449. bounds.resize(numSubPatchesMB);
  450. /* exit if there are no primitives to process */
  451. if (numSubPatches == 0) {
  452. bvh->set(BVH::emptyNode,empty,0);
  453. bvh->postBuild(t0);
  454. return;
  455. }
  456. /* Allocate memory for gregory and b-spline patches */
  457. bvh->subdiv_patches.resize(sizeof(SubdivPatch1Cached) * numSubPatchesMB);
  458. /* switch between fast and slow mode */
  459. if (mblur) rebuild(numSubPatches);
  460. else if (cached && fastUpdateMode) cachedUpdate(numSubPatches);
  461. else rebuild(numSubPatches);
  462. /* clear temporary data for static geometry */
  463. if (scene->isStatic()) {
  464. prims.clear();
  465. bvh->shrink();
  466. }
  467. bvh->cleanup();
  468. bvh->postBuild(t0);
  469. }
  470. void clear() {
  471. prims.clear();
  472. }
  473. };
  474. /* entry functions for the scene builder */
  475. Builder* BVH4SubdivPatch1EagerBuilderBinnedSAH(void* bvh, Scene* scene, size_t mode) { return new BVHNSubdivPatch1EagerBuilderBinnedSAHClass<4>((BVH4*)bvh,scene); }
  476. Builder* BVH4SubdivPatch1CachedBuilderBinnedSAH(void* bvh, Scene* scene, size_t mode) { return new BVHNSubdivPatch1CachedBuilderBinnedSAHClass<4,false>((BVH4*)bvh,scene,mode); }
  477. Builder* BVH4SubdivPatch1MBlurCachedBuilderBinnedSAH(void* bvh, Scene* scene, size_t mode) { return new BVHNSubdivPatch1CachedBuilderBinnedSAHClass<4,true>((BVH4*)bvh,scene,mode); }
  478. }
  479. }
  480. #endif