bvh_builder_twolevel.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  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_builder_twolevel.h"
  17. #include "bvh_statistics.h"
  18. #include "../builders/bvh_builder_sah.h"
  19. #include "../common/scene_line_segments.h"
  20. #include "../common/scene_triangle_mesh.h"
  21. #include "../common/scene_quad_mesh.h"
  22. #define PROFILE 0
  23. #define MAX_OPEN_SIZE 10000
  24. #define PROFILE_ITERATIONS 200
  25. namespace embree
  26. {
  27. namespace isa
  28. {
  29. template<int N, typename Mesh>
  30. BVHNBuilderTwoLevel<N,Mesh>::BVHNBuilderTwoLevel (BVH* bvh, Scene* scene, const createMeshAccelTy createMeshAccel, const size_t singleThreadThreshold)
  31. : bvh(bvh), objects(bvh->objects), scene(scene), createMeshAccel(createMeshAccel), refs(scene->device), prims(scene->device), singleThreadThreshold(singleThreadThreshold) {}
  32. template<int N, typename Mesh>
  33. BVHNBuilderTwoLevel<N,Mesh>::~BVHNBuilderTwoLevel ()
  34. {
  35. for (size_t i=0; i<builders.size(); i++)
  36. delete builders[i];
  37. }
  38. template<int N, typename Mesh>
  39. void BVHNBuilderTwoLevel<N,Mesh>::build()
  40. {
  41. /* delete some objects */
  42. size_t num = scene->size();
  43. if (num < objects.size()) {
  44. parallel_for(num, objects.size(), [&] (const range<size_t>& r) {
  45. for (size_t i=r.begin(); i<r.end(); i++) {
  46. delete builders[i]; builders[i] = nullptr;
  47. delete objects[i]; objects[i] = nullptr;
  48. }
  49. });
  50. }
  51. /* reset memory allocator */
  52. bvh->alloc.reset();
  53. /* skip build for empty scene */
  54. const size_t numPrimitives = scene->getNumPrimitives<Mesh,false>();
  55. if (numPrimitives == 0) {
  56. prims.resize(0);
  57. bvh->set(BVH::emptyNode,empty,0);
  58. return;
  59. }
  60. double t0 = bvh->preBuild(TOSTRING(isa) "::BVH" + toString(N) + "BuilderTwoLevel");
  61. #if PROFILE
  62. profile(2,PROFILE_ITERATIONS,numPrimitives,[&] (ProfileTimer& timer)
  63. {
  64. #endif
  65. /* resize object array if scene got larger */
  66. if (objects.size() < num) objects.resize(num);
  67. if (builders.size() < num) builders.resize(num);
  68. if (refs.size() < num) refs.resize(num);
  69. nextRef.store(0);
  70. /* create of acceleration structures */
  71. parallel_for(size_t(0), num, [&] (const range<size_t>& r)
  72. {
  73. for (size_t objectID=r.begin(); objectID<r.end(); objectID++)
  74. {
  75. Mesh* mesh = scene->getSafe<Mesh>(objectID);
  76. /* verify meshes got deleted properly */
  77. if (mesh == nullptr || mesh->numTimeSteps != 1) {
  78. assert(objectID < objects.size () && objects[objectID] == nullptr);
  79. assert(objectID < builders.size() && builders[objectID] == nullptr);
  80. continue;
  81. }
  82. /* create BVH and builder for new meshes */
  83. if (objects[objectID] == nullptr)
  84. createMeshAccel(mesh,(AccelData*&)objects[objectID],builders[objectID]);
  85. }
  86. });
  87. /* parallel build of acceleration structures */
  88. parallel_for(size_t(0), num, [&] (const range<size_t>& r)
  89. {
  90. for (size_t objectID=r.begin(); objectID<r.end(); objectID++)
  91. {
  92. /* ignore if no triangle mesh or not enabled */
  93. Mesh* mesh = scene->getSafe<Mesh>(objectID);
  94. if (mesh == nullptr || !mesh->isEnabled() || mesh->numTimeSteps != 1)
  95. continue;
  96. BVH* object = objects [objectID]; assert(object);
  97. Builder* builder = builders[objectID]; assert(builder);
  98. /* build object if it got modified */
  99. #if !PROFILE
  100. if (mesh->isModified())
  101. #endif
  102. builder->build();
  103. /* create build primitive */
  104. if (!object->getBounds().empty())
  105. refs[nextRef++] = BVHNBuilderTwoLevel::BuildRef(object->getBounds(),object->root);
  106. }
  107. });
  108. /* fast path for single geometry scenes */
  109. if (nextRef == 1) {
  110. bvh->set(refs[0].node,LBBox3fa(refs[0].bounds()),numPrimitives);
  111. }
  112. else
  113. {
  114. /* open all large nodes */
  115. refs.resize(nextRef);
  116. open_sequential(numPrimitives);
  117. //open_overlap(numPrimitives);
  118. // PRINT(numPrimitives);
  119. // PRINT(refs.size());
  120. /* compute PrimRefs */
  121. prims.resize(refs.size());
  122. bvh->alloc.init_estimate(refs.size()*16);
  123. #if defined(TASKING_TBB) && defined(__AVX512ER__) && USE_TASK_ARENA // KNL
  124. tbb::task_arena limited(min(32,(int)TaskScheduler::threadCount()));
  125. limited.execute([&]
  126. #endif
  127. {
  128. const PrimInfo pinfo = parallel_reduce(size_t(0), refs.size(), PrimInfo(empty), [&] (const range<size_t>& r) -> PrimInfo {
  129. PrimInfo pinfo(empty);
  130. for (size_t i=r.begin(); i<r.end(); i++) {
  131. pinfo.add(refs[i].bounds());
  132. prims[i] = PrimRef(refs[i].bounds(),(size_t)refs[i].node);
  133. }
  134. return pinfo;
  135. }, [] (const PrimInfo& a, const PrimInfo& b) { return PrimInfo::merge(a,b); });
  136. /* skip if all objects where empty */
  137. if (pinfo.size() == 0)
  138. bvh->set(BVH::emptyNode,empty,0);
  139. /* otherwise build toplevel hierarchy */
  140. else
  141. {
  142. /* settings for BVH build */
  143. GeneralBVHBuilder::Settings settings;
  144. settings.branchingFactor = N;
  145. settings.maxDepth = BVH::maxBuildDepthLeaf;
  146. settings.logBlockSize = __bsr(N);
  147. settings.minLeafSize = 1;
  148. settings.maxLeafSize = 1;
  149. settings.travCost = 1.0f;
  150. settings.intCost = 1.0f;
  151. settings.singleThreadThreshold = singleThreadThreshold;
  152. NodeRef root = BVHBuilderBinnedSAH::build<NodeRef>
  153. (
  154. typename BVH::CreateAlloc(bvh),
  155. typename BVH::AlignedNode::Create2(),
  156. typename BVH::AlignedNode::Set2(),
  157. [&] (const BVHBuilderBinnedSAH::BuildRecord& current, FastAllocator::ThreadLocal2* alloc) -> NodeRef
  158. {
  159. assert(current.prims.size() == 1);
  160. return (NodeRef) prims[current.prims.begin()].ID();
  161. },
  162. [&] (size_t dn) { bvh->scene->progressMonitor(0); },
  163. prims.data(),pinfo,settings);
  164. bvh->set(root,LBBox3fa(pinfo.geomBounds),numPrimitives);
  165. }
  166. }
  167. #if defined(TASKING_TBB) && defined(__AVX512ER__) && USE_TASK_ARENA // KNL
  168. );
  169. #endif
  170. }
  171. #if PROFILE
  172. });
  173. #endif
  174. bvh->alloc.cleanup();
  175. bvh->postBuild(t0);
  176. }
  177. template<int N, typename Mesh>
  178. void BVHNBuilderTwoLevel<N,Mesh>::deleteGeometry(size_t geomID)
  179. {
  180. if (geomID >= objects.size()) return;
  181. delete builders[geomID]; builders[geomID] = nullptr;
  182. delete objects [geomID]; objects [geomID] = nullptr;
  183. }
  184. template<int N, typename Mesh>
  185. void BVHNBuilderTwoLevel<N,Mesh>::clear()
  186. {
  187. for (size_t i=0; i<objects.size(); i++)
  188. if (objects[i]) objects[i]->clear();
  189. for (size_t i=0; i<builders.size(); i++)
  190. if (builders[i]) builders[i]->clear();
  191. refs.clear();
  192. }
  193. template<int N, typename Mesh>
  194. void BVHNBuilderTwoLevel<N,Mesh>::open_sequential(size_t numPrimitives)
  195. {
  196. if (refs.size() == 0)
  197. return;
  198. size_t num = min(numPrimitives/400,size_t(MAX_OPEN_SIZE));
  199. refs.reserve(num);
  200. #if 1
  201. for (size_t i=0;i<refs.size();i++)
  202. {
  203. NodeRef ref = refs.back().node;
  204. if (ref.isAlignedNode())
  205. ref.prefetch();
  206. }
  207. #endif
  208. std::make_heap(refs.begin(),refs.end());
  209. while (refs.size()+3 <= num)
  210. {
  211. std::pop_heap (refs.begin(),refs.end());
  212. NodeRef ref = refs.back().node;
  213. if (ref.isLeaf()) break;
  214. refs.pop_back();
  215. AlignedNode* node = ref.alignedNode();
  216. for (size_t i=0; i<N; i++) {
  217. if (node->child(i) == BVH::emptyNode) continue;
  218. refs.push_back(BuildRef(node->bounds(i),node->child(i)));
  219. #if 1
  220. NodeRef ref_pre = node->child(i);
  221. if (ref_pre.isAlignedNode())
  222. ref_pre.prefetch();
  223. #endif
  224. std::push_heap (refs.begin(),refs.end());
  225. }
  226. }
  227. }
  228. template<int N, typename Mesh>
  229. void BVHNBuilderTwoLevel<N,Mesh>::open_overlap(size_t numPrimitives)
  230. {
  231. if (refs.size() == 0)
  232. return;
  233. size_t num = min(numPrimitives/400,size_t(MAX_OPEN_SIZE));
  234. refs.reserve(num);
  235. #if 1
  236. for (size_t i=0;i<refs.size();i++)
  237. {
  238. NodeRef ref = refs.back().node;
  239. if (ref.isAlignedNode())
  240. ref.prefetch();
  241. }
  242. #endif
  243. for (size_t i=0;i<refs.size();i++)
  244. for (size_t j=i+1;j<refs.size();j++)
  245. {
  246. //std::cout << "i " << i << " j " << j << " -> " << disjoint(refs[i].bounds(),refs[j].bounds()) << std::endl;
  247. }
  248. std::make_heap(refs.begin(),refs.end());
  249. while (refs.size()+3 <= num)
  250. {
  251. std::pop_heap (refs.begin(),refs.end());
  252. NodeRef ref = refs.back().node;
  253. if (ref.isLeaf()) break;
  254. refs.pop_back();
  255. AlignedNode* node = ref.alignedNode();
  256. for (size_t i=0; i<N; i++) {
  257. if (node->child(i) == BVH::emptyNode) continue;
  258. refs.push_back(BuildRef(node->bounds(i),node->child(i)));
  259. #if 1
  260. NodeRef ref_pre = node->child(i);
  261. if (ref_pre.isAlignedNode())
  262. ref_pre.prefetch();
  263. #endif
  264. std::push_heap (refs.begin(),refs.end());
  265. }
  266. }
  267. }
  268. #if defined(EMBREE_GEOMETRY_LINES)
  269. Builder* BVH4BuilderTwoLevelLineSegmentsSAH (void* bvh, Scene* scene, const createLineSegmentsAccelTy createMeshAccel) {
  270. return new BVHNBuilderTwoLevel<4,LineSegments>((BVH4*)bvh,scene,createMeshAccel);
  271. }
  272. #endif
  273. #if defined(EMBREE_GEOMETRY_TRIANGLES)
  274. Builder* BVH4BuilderTwoLevelTriangleMeshSAH (void* bvh, Scene* scene, const createTriangleMeshAccelTy createMeshAccel) {
  275. return new BVHNBuilderTwoLevel<4,TriangleMesh>((BVH4*)bvh,scene,createMeshAccel);
  276. }
  277. #endif
  278. #if defined(EMBREE_GEOMETRY_QUADS)
  279. Builder* BVH4BuilderTwoLevelQuadMeshSAH (void* bvh, Scene* scene, const createQuadMeshAccelTy createMeshAccel) {
  280. return new BVHNBuilderTwoLevel<4,QuadMesh>((BVH4*)bvh,scene,createMeshAccel);
  281. }
  282. #endif
  283. #if defined(EMBREE_GEOMETRY_USER)
  284. Builder* BVH4BuilderTwoLevelVirtualSAH (void* bvh, Scene* scene, const createAccelSetAccelTy createMeshAccel) {
  285. return new BVHNBuilderTwoLevel<4,AccelSet>((BVH4*)bvh,scene,createMeshAccel);
  286. }
  287. #endif
  288. #if defined(__AVX__)
  289. #if defined(EMBREE_GEOMETRY_TRIANGLES)
  290. Builder* BVH8BuilderTwoLevelTriangleMeshSAH (void* bvh, Scene* scene, const createTriangleMeshAccelTy createMeshAccel) {
  291. return new BVHNBuilderTwoLevel<8,TriangleMesh>((BVH8*)bvh,scene,createMeshAccel);
  292. }
  293. #endif
  294. #if defined(EMBREE_GEOMETRY_QUADS)
  295. Builder* BVH8BuilderTwoLevelQuadMeshSAH (void* bvh, Scene* scene, const createQuadMeshAccelTy createMeshAccel) {
  296. return new BVHNBuilderTwoLevel<8,QuadMesh>((BVH8*)bvh,scene,createMeshAccel);
  297. }
  298. #endif
  299. #if defined(EMBREE_GEOMETRY_USER)
  300. Builder* BVH8BuilderTwoLevelVirtualSAH (void* bvh, Scene* scene, const createAccelSetAccelTy createMeshAccel) {
  301. return new BVHNBuilderTwoLevel<8,AccelSet>((BVH8*)bvh,scene,createMeshAccel);
  302. }
  303. #endif
  304. #endif
  305. }
  306. }