bvh_refit.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  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_refit.h"
  17. #include "bvh_statistics.h"
  18. #include "../geometry/linei.h"
  19. #include "../geometry/triangle.h"
  20. #include "../geometry/trianglev.h"
  21. #include "../geometry/trianglei.h"
  22. #include "../geometry/quadv.h"
  23. #include "../geometry/object.h"
  24. namespace embree
  25. {
  26. namespace isa
  27. {
  28. static const size_t SINGLE_THREAD_THRESHOLD = 4*1024;
  29. template<int N>
  30. __forceinline bool compare(const typename BVHN<N>::NodeRef* a, const typename BVHN<N>::NodeRef* b)
  31. {
  32. size_t sa = *(size_t*)&a->node()->lower_x;
  33. size_t sb = *(size_t*)&b->node()->lower_x;
  34. return sa < sb;
  35. }
  36. template<int N>
  37. BVHNRefitter<N>::BVHNRefitter (BVH* bvh, const LeafBoundsInterface& leafBounds)
  38. : bvh(bvh), leafBounds(leafBounds), numSubTrees(0)
  39. {
  40. }
  41. template<int N>
  42. void BVHNRefitter<N>::refit()
  43. {
  44. if (bvh->numPrimitives <= SINGLE_THREAD_THRESHOLD) {
  45. bvh->bounds = LBBox3fa(recurse_bottom(bvh->root));
  46. }
  47. else
  48. {
  49. BBox3fa subTreeBounds[MAX_NUM_SUB_TREES];
  50. numSubTrees = 0;
  51. gather_subtree_refs(bvh->root,numSubTrees,0);
  52. if (numSubTrees)
  53. parallel_for(size_t(0), numSubTrees, size_t(1), [&](const range<size_t>& r) {
  54. for (size_t i=r.begin(); i<r.end(); i++) {
  55. NodeRef& ref = subTrees[i];
  56. subTreeBounds[i] = recurse_bottom(ref);
  57. }
  58. });
  59. numSubTrees = 0;
  60. bvh->bounds = LBBox3fa(refit_toplevel(bvh->root,numSubTrees,subTreeBounds,0));
  61. }
  62. }
  63. template<int N>
  64. void BVHNRefitter<N>::gather_subtree_refs(NodeRef& ref,
  65. size_t &subtrees,
  66. const size_t depth)
  67. {
  68. if (depth >= MAX_SUB_TREE_EXTRACTION_DEPTH)
  69. {
  70. assert(subtrees < MAX_NUM_SUB_TREES);
  71. subTrees[subtrees++] = ref;
  72. return;
  73. }
  74. if (ref.isAlignedNode())
  75. {
  76. AlignedNode* node = ref.alignedNode();
  77. for (size_t i=0; i<N; i++) {
  78. NodeRef& child = node->child(i);
  79. if (unlikely(child == BVH::emptyNode)) continue;
  80. gather_subtree_refs(child,subtrees,depth+1);
  81. }
  82. }
  83. }
  84. template<int N>
  85. BBox3fa BVHNRefitter<N>::refit_toplevel(NodeRef& ref,
  86. size_t &subtrees,
  87. const BBox3fa *const subTreeBounds,
  88. const size_t depth)
  89. {
  90. if (depth >= MAX_SUB_TREE_EXTRACTION_DEPTH)
  91. {
  92. assert(subtrees < MAX_NUM_SUB_TREES);
  93. assert(subTrees[subtrees] == ref);
  94. return subTreeBounds[subtrees++];
  95. }
  96. if (ref.isAlignedNode())
  97. {
  98. AlignedNode* node = ref.alignedNode();
  99. BBox3fa bounds[N];
  100. for (size_t i=0; i<N; i++)
  101. {
  102. NodeRef& child = node->child(i);
  103. if (unlikely(child == BVH::emptyNode))
  104. bounds[i] = BBox3fa(empty);
  105. else
  106. bounds[i] = refit_toplevel(child,subtrees,subTreeBounds,depth+1);
  107. }
  108. BBox<Vec3<vfloat<N>>> boundsT = transpose<N>(bounds);
  109. /* set new bounds */
  110. node->lower_x = boundsT.lower.x;
  111. node->lower_y = boundsT.lower.y;
  112. node->lower_z = boundsT.lower.z;
  113. node->upper_x = boundsT.upper.x;
  114. node->upper_y = boundsT.upper.y;
  115. node->upper_z = boundsT.upper.z;
  116. return merge<N>(bounds);
  117. }
  118. else
  119. return leafBounds.leafBounds(ref);
  120. }
  121. // =========================================================
  122. // =========================================================
  123. // =========================================================
  124. template<int N>
  125. BBox3fa BVHNRefitter<N>::recurse_bottom(NodeRef& ref)
  126. {
  127. /* this is a leaf node */
  128. if (unlikely(ref.isLeaf()))
  129. return leafBounds.leafBounds(ref);
  130. /* recurse if this is an internal node */
  131. AlignedNode* node = ref.alignedNode();
  132. /* enable exclusive prefetch for >= AVX platforms */
  133. #if defined(__AVX__)
  134. ref.prefetchW();
  135. #endif
  136. BBox3fa bounds[N];
  137. for (size_t i=0; i<N; i++)
  138. if (unlikely(node->child(i) == BVH::emptyNode))
  139. {
  140. bounds[i] = BBox3fa(empty);
  141. }
  142. else
  143. bounds[i] = recurse_bottom(node->child(i));
  144. /* AOS to SOA transform */
  145. BBox<Vec3<vfloat<N>>> boundsT = transpose<N>(bounds);
  146. /* set new bounds */
  147. node->lower_x = boundsT.lower.x;
  148. node->lower_y = boundsT.lower.y;
  149. node->lower_z = boundsT.lower.z;
  150. node->upper_x = boundsT.upper.x;
  151. node->upper_y = boundsT.upper.y;
  152. node->upper_z = boundsT.upper.z;
  153. return merge<N>(bounds);
  154. }
  155. template<int N, typename Mesh, typename Primitive>
  156. BVHNRefitT<N,Mesh,Primitive>::BVHNRefitT (BVH* bvh, Builder* builder, Mesh* mesh, size_t mode)
  157. : bvh(bvh), builder(builder), refitter(nullptr), mesh(mesh) {}
  158. template<int N, typename Mesh, typename Primitive>
  159. void BVHNRefitT<N,Mesh,Primitive>::clear()
  160. {
  161. if (builder)
  162. builder->clear();
  163. }
  164. template<int N, typename Mesh, typename Primitive>
  165. void BVHNRefitT<N,Mesh,Primitive>::build()
  166. {
  167. /* build initial BVH */
  168. if (builder) {
  169. builder->build();
  170. builder.reset(nullptr);
  171. refitter.reset(new BVHNRefitter<N>(bvh,*(typename BVHNRefitter<N>::LeafBoundsInterface*)this));
  172. }
  173. /* refit BVH */
  174. double t0 = 0.0;
  175. if (bvh->device->verbosity(2)) {
  176. std::cout << "refitting BVH" << N << " <" << bvh->primTy.name << "> ... " << std::flush;
  177. t0 = getSeconds();
  178. }
  179. refitter->refit();
  180. if (bvh->device->verbosity(2))
  181. {
  182. double t1 = getSeconds();
  183. std::cout << "[DONE]" << std::endl;
  184. std::cout << " dt = " << 1000.0f*(t1-t0) << "ms, perf = " << 1E-6*double(mesh->size())/(t1-t0) << " Mprim/s" << std::endl;
  185. std::cout << BVHNStatistics<N>(bvh).str();
  186. }
  187. }
  188. template class BVHNRefitter<4>;
  189. #if defined(__AVX__)
  190. template class BVHNRefitter<8>;
  191. #endif
  192. Builder* BVH4Line4iMeshBuilderSAH (void* bvh, LineSegments* mesh, size_t mode);
  193. #if defined(EMBREE_GEOMETRY_LINES)
  194. Builder* BVH4Line4iMeshRefitSAH (void* accel, LineSegments* mesh, size_t mode) { return new BVHNRefitT<4,LineSegments,Line4i>((BVH4*)accel,BVH4Line4iMeshBuilderSAH(accel,mesh,mode),mesh,mode); }
  195. #endif
  196. #if defined(EMBREE_GEOMETRY_TRIANGLES)
  197. Builder* BVH4Triangle4MeshBuilderSAH (void* bvh, TriangleMesh* mesh, size_t mode);
  198. Builder* BVH4Triangle4vMeshBuilderSAH (void* bvh, TriangleMesh* mesh, size_t mode);
  199. Builder* BVH4Triangle4iMeshBuilderSAH (void* bvh, TriangleMesh* mesh, size_t mode);
  200. Builder* BVH4Triangle4MeshRefitSAH (void* accel, TriangleMesh* mesh, size_t mode) { return new BVHNRefitT<4,TriangleMesh,Triangle4> ((BVH4*)accel,BVH4Triangle4MeshBuilderSAH (accel,mesh,mode),mesh,mode); }
  201. Builder* BVH4Triangle4vMeshRefitSAH (void* accel, TriangleMesh* mesh, size_t mode) { return new BVHNRefitT<4,TriangleMesh,Triangle4v>((BVH4*)accel,BVH4Triangle4vMeshBuilderSAH(accel,mesh,mode),mesh,mode); }
  202. Builder* BVH4Triangle4iMeshRefitSAH (void* accel, TriangleMesh* mesh, size_t mode) { return new BVHNRefitT<4,TriangleMesh,Triangle4i>((BVH4*)accel,BVH4Triangle4iMeshBuilderSAH(accel,mesh,mode),mesh,mode); }
  203. #if defined(__AVX__)
  204. Builder* BVH8Triangle4MeshBuilderSAH (void* bvh, TriangleMesh* mesh, size_t mode);
  205. Builder* BVH8Triangle4vMeshBuilderSAH (void* bvh, TriangleMesh* mesh, size_t mode);
  206. Builder* BVH8Triangle4iMeshBuilderSAH (void* bvh, TriangleMesh* mesh, size_t mode);
  207. Builder* BVH8Triangle4MeshRefitSAH (void* accel, TriangleMesh* mesh, size_t mode) { return new BVHNRefitT<8,TriangleMesh,Triangle4> ((BVH8*)accel,BVH8Triangle4MeshBuilderSAH (accel,mesh,mode),mesh,mode); }
  208. Builder* BVH8Triangle4vMeshRefitSAH (void* accel, TriangleMesh* mesh, size_t mode) { return new BVHNRefitT<8,TriangleMesh,Triangle4v>((BVH8*)accel,BVH8Triangle4vMeshBuilderSAH(accel,mesh,mode),mesh,mode); }
  209. Builder* BVH8Triangle4iMeshRefitSAH (void* accel, TriangleMesh* mesh, size_t mode) { return new BVHNRefitT<8,TriangleMesh,Triangle4i>((BVH8*)accel,BVH8Triangle4iMeshBuilderSAH(accel,mesh,mode),mesh,mode); }
  210. #endif
  211. #endif
  212. #if defined(EMBREE_GEOMETRY_QUADS)
  213. Builder* BVH4Quad4vMeshBuilderSAH (void* bvh, QuadMesh* mesh, size_t mode);
  214. Builder* BVH4Quad4vMeshRefitSAH (void* accel, QuadMesh* mesh, size_t mode) { return new BVHNRefitT<4,QuadMesh,Quad4v>((BVH4*)accel,BVH4Quad4vMeshBuilderSAH(accel,mesh,mode),mesh,mode); }
  215. #if defined(__AVX__)
  216. Builder* BVH8Quad4vMeshBuilderSAH (void* bvh, QuadMesh* mesh, size_t mode);
  217. Builder* BVH8Quad4vMeshRefitSAH (void* accel, QuadMesh* mesh, size_t mode) { return new BVHNRefitT<8,QuadMesh,Quad4v>((BVH8*)accel,BVH8Quad4vMeshBuilderSAH(accel,mesh,mode),mesh,mode); }
  218. #endif
  219. #endif
  220. #if defined(EMBREE_GEOMETRY_USER)
  221. Builder* BVH4VirtualMeshBuilderSAH (void* bvh, AccelSet* mesh, size_t mode);
  222. Builder* BVH4VirtualMeshRefitSAH (void* accel, AccelSet* mesh, size_t mode) { return new BVHNRefitT<4,AccelSet,Object>((BVH4*)accel,BVH4VirtualMeshBuilderSAH(accel,mesh,mode),mesh,mode); }
  223. #endif
  224. }
  225. }