bvh_builder_sah_spatial.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  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/primrefgen.h"
  6. #include "../builders/primrefgen_presplit.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. namespace embree
  20. {
  21. namespace isa
  22. {
  23. template<int N, typename Primitive>
  24. struct CreateLeafSpatial
  25. {
  26. typedef BVHN<N> BVH;
  27. typedef typename BVH::NodeRef NodeRef;
  28. __forceinline CreateLeafSpatial (BVH* bvh) : bvh(bvh) {}
  29. __forceinline NodeRef operator() (const PrimRef* prims, const range<size_t>& set, const FastAllocator::CachedAllocator& alloc) const
  30. {
  31. size_t n = set.size();
  32. size_t items = Primitive::blocks(n);
  33. size_t start = set.begin();
  34. Primitive* accel = (Primitive*) alloc.malloc1(items*sizeof(Primitive),BVH::byteAlignment);
  35. typename BVH::NodeRef node = BVH::encodeLeaf((char*)accel,items);
  36. for (size_t i=0; i<items; i++) {
  37. accel[i].fill(prims,start,set.end(),bvh->scene);
  38. }
  39. return node;
  40. }
  41. BVH* bvh;
  42. };
  43. template<int N, typename Mesh, typename Primitive, typename Splitter>
  44. struct BVHNBuilderFastSpatialSAH : public Builder
  45. {
  46. typedef BVHN<N> BVH;
  47. typedef typename BVH::NodeRef NodeRef;
  48. BVH* bvh;
  49. Scene* scene;
  50. Mesh* mesh;
  51. mvector<PrimRef> prims0;
  52. GeneralBVHBuilder::Settings settings;
  53. const float splitFactor;
  54. unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
  55. unsigned int numPreviousPrimitives = 0;
  56. BVHNBuilderFastSpatialSAH (BVH* bvh, Scene* scene, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const size_t mode)
  57. : bvh(bvh), scene(scene), mesh(nullptr), prims0(scene->device,0), settings(sahBlockSize, minLeafSize, min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks), travCost, intCost, DEFAULT_SINGLE_THREAD_THRESHOLD),
  58. splitFactor(scene->device->max_spatial_split_replications) {}
  59. BVHNBuilderFastSpatialSAH (BVH* bvh, Mesh* mesh, const unsigned int geomID, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const size_t mode)
  60. : bvh(bvh), scene(nullptr), mesh(mesh), prims0(bvh->device,0), settings(sahBlockSize, minLeafSize, min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks), travCost, intCost, DEFAULT_SINGLE_THREAD_THRESHOLD),
  61. splitFactor(scene->device->max_spatial_split_replications), geomID_(geomID) {}
  62. // FIXME: shrink bvh->alloc in destructor here and in other builders too
  63. void build()
  64. {
  65. /* we reset the allocator when the mesh size changed */
  66. if (mesh && mesh->numPrimitives != numPreviousPrimitives) {
  67. bvh->alloc.clear();
  68. }
  69. /* skip build for empty scene */
  70. const size_t numOriginalPrimitives = mesh ? mesh->size() : scene->getNumPrimitives(Mesh::geom_type,false);
  71. numPreviousPrimitives = numOriginalPrimitives;
  72. if (numOriginalPrimitives == 0) {
  73. prims0.clear();
  74. bvh->clear();
  75. return;
  76. }
  77. const unsigned int maxGeomID = mesh ? geomID_ : scene->getMaxGeomID<Mesh,false>();
  78. const bool usePreSplits = scene->device->useSpatialPreSplits || (maxGeomID >= ((unsigned int)1 << (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS)));
  79. double t0 = bvh->preBuild(mesh ? "" : TOSTRING(isa) "::BVH" + toString(N) + (usePreSplits ? "BuilderFastSpatialPresplitSAH" : "BuilderFastSpatialSAH"));
  80. /* create primref array */
  81. const size_t numSplitPrimitives = max(numOriginalPrimitives,size_t(splitFactor*numOriginalPrimitives));
  82. prims0.resize(numSplitPrimitives);
  83. /* enable os_malloc for two level build */
  84. if (mesh)
  85. bvh->alloc.setOSallocation(true);
  86. NodeRef root(0);
  87. PrimInfo pinfo;
  88. if (likely(usePreSplits))
  89. {
  90. /* spatial presplit SAH BVH builder */
  91. pinfo = mesh ?
  92. createPrimRefArray_presplit<Mesh,Splitter>(mesh,maxGeomID,numOriginalPrimitives,prims0,bvh->scene->progressInterface) :
  93. createPrimRefArray_presplit<Mesh,Splitter>(scene,Mesh::geom_type,false,numOriginalPrimitives,prims0,bvh->scene->progressInterface);
  94. const size_t node_bytes = pinfo.size()*sizeof(typename BVH::AABBNode)/(4*N);
  95. const size_t leaf_bytes = size_t(1.2*Primitive::blocks(pinfo.size())*sizeof(Primitive));
  96. bvh->alloc.init_estimate(node_bytes+leaf_bytes);
  97. settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes);
  98. settings.branchingFactor = N;
  99. settings.maxDepth = BVH::maxBuildDepthLeaf;
  100. /* call BVH builder */
  101. root = BVHNBuilderVirtual<N>::build(&bvh->alloc,CreateLeafSpatial<N,Primitive>(bvh),bvh->scene->progressInterface,prims0.data(),pinfo,settings);
  102. }
  103. else
  104. {
  105. /* standard spatial split SAH BVH builder */
  106. pinfo = mesh ?
  107. createPrimRefArray(mesh,geomID_,numSplitPrimitives,prims0,bvh->scene->progressInterface) :
  108. createPrimRefArray(scene,Mesh::geom_type,false,numSplitPrimitives,prims0,bvh->scene->progressInterface);
  109. Splitter splitter(scene);
  110. const size_t node_bytes = pinfo.size()*sizeof(typename BVH::AABBNode)/(4*N);
  111. const size_t leaf_bytes = size_t(1.2*Primitive::blocks(pinfo.size())*sizeof(Primitive));
  112. bvh->alloc.init_estimate(node_bytes+leaf_bytes);
  113. settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes);
  114. settings.branchingFactor = N;
  115. settings.maxDepth = BVH::maxBuildDepthLeaf;
  116. /* call BVH builder */
  117. root = BVHBuilderBinnedFastSpatialSAH::build<NodeRef>(
  118. typename BVH::CreateAlloc(bvh),
  119. typename BVH::AABBNode::Create2(),
  120. typename BVH::AABBNode::Set2(),
  121. CreateLeafSpatial<N,Primitive>(bvh),
  122. splitter,
  123. bvh->scene->progressInterface,
  124. prims0.data(),
  125. numSplitPrimitives,
  126. pinfo,settings);
  127. /* ==================== */
  128. }
  129. bvh->set(root,LBBox3fa(pinfo.geomBounds),pinfo.size());
  130. bvh->layoutLargeNodes(size_t(pinfo.size()*0.005f));
  131. /* clear temporary data for static geometry */
  132. if (scene && scene->isStaticAccel()) {
  133. prims0.clear();
  134. }
  135. bvh->cleanup();
  136. bvh->postBuild(t0);
  137. }
  138. void clear() {
  139. prims0.clear();
  140. }
  141. };
  142. /************************************************************************************/
  143. /************************************************************************************/
  144. /************************************************************************************/
  145. /************************************************************************************/
  146. #if defined(EMBREE_GEOMETRY_TRIANGLE)
  147. Builder* BVH4Triangle4SceneBuilderFastSpatialSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderFastSpatialSAH<4,TriangleMesh,Triangle4,TriangleSplitterFactory>((BVH4*)bvh,scene,4,1.0f,4,scene->device->max_triangles_per_leaf,mode); }
  148. Builder* BVH4Triangle4vSceneBuilderFastSpatialSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderFastSpatialSAH<4,TriangleMesh,Triangle4v,TriangleSplitterFactory>((BVH4*)bvh,scene,4,1.0f,4,scene->device->max_triangles_per_leaf,mode); }
  149. Builder* BVH4Triangle4iSceneBuilderFastSpatialSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderFastSpatialSAH<4,TriangleMesh,Triangle4i,TriangleSplitterFactory>((BVH4*)bvh,scene,4,1.0f,4,scene->device->max_triangles_per_leaf,mode); }
  150. #if defined(__AVX__)
  151. Builder* BVH8Triangle4SceneBuilderFastSpatialSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderFastSpatialSAH<8,TriangleMesh,Triangle4,TriangleSplitterFactory>((BVH8*)bvh,scene,4,1.0f,4,inf,mode); }
  152. Builder* BVH8Triangle4vSceneBuilderFastSpatialSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderFastSpatialSAH<8,TriangleMesh,Triangle4v,TriangleSplitterFactory>((BVH8*)bvh,scene,4,1.0f,4,inf,mode); }
  153. #endif
  154. #endif
  155. #if defined(EMBREE_GEOMETRY_QUAD)
  156. Builder* BVH4Quad4vSceneBuilderFastSpatialSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderFastSpatialSAH<4,QuadMesh,Quad4v,QuadSplitterFactory>((BVH4*)bvh,scene,4,1.0f,4,inf,mode); }
  157. #if defined(__AVX__)
  158. Builder* BVH8Quad4vSceneBuilderFastSpatialSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderFastSpatialSAH<8,QuadMesh,Quad4v,QuadSplitterFactory>((BVH8*)bvh,scene,4,1.0f,4,inf,mode); }
  159. #endif
  160. #endif
  161. }
  162. }