bvh_refit.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. // Copyright 2009-2021 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #include "bvh_refit.h"
  4. #include "bvh_statistics.h"
  5. #include "../geometry/linei.h"
  6. #include "../geometry/triangle.h"
  7. #include "../geometry/trianglev.h"
  8. #include "../geometry/trianglei.h"
  9. #include "../geometry/quadv.h"
  10. #include "../geometry/object.h"
  11. #include "../geometry/instance.h"
  12. #include "../geometry/instance_array.h"
  13. #include "../../common/algorithms/parallel_for.h"
  14. namespace embree
  15. {
  16. namespace isa
  17. {
  18. static const size_t SINGLE_THREAD_THRESHOLD = 4*1024;
  19. template<int N>
  20. __forceinline bool compare(const typename BVHN<N>::NodeRef* a, const typename BVHN<N>::NodeRef* b)
  21. {
  22. size_t sa = *(size_t*)&a->node()->lower_x;
  23. size_t sb = *(size_t*)&b->node()->lower_x;
  24. return sa < sb;
  25. }
  26. template<int N>
  27. BVHNRefitter<N>::BVHNRefitter (BVH* bvh, const LeafBoundsInterface& leafBounds)
  28. : bvh(bvh), leafBounds(leafBounds), numSubTrees(0)
  29. {
  30. }
  31. template<int N>
  32. void BVHNRefitter<N>::refit()
  33. {
  34. if (bvh->numPrimitives <= SINGLE_THREAD_THRESHOLD) {
  35. bvh->bounds = LBBox3fa(recurse_bottom(bvh->root));
  36. }
  37. else
  38. {
  39. BBox3fa subTreeBounds[MAX_NUM_SUB_TREES];
  40. numSubTrees = 0;
  41. gather_subtree_refs(bvh->root,numSubTrees,0);
  42. if (numSubTrees)
  43. parallel_for(size_t(0), numSubTrees, size_t(1), [&](const range<size_t>& r) {
  44. for (size_t i=r.begin(); i<r.end(); i++) {
  45. NodeRef& ref = subTrees[i];
  46. subTreeBounds[i] = recurse_bottom(ref);
  47. }
  48. });
  49. numSubTrees = 0;
  50. bvh->bounds = LBBox3fa(refit_toplevel(bvh->root,numSubTrees,subTreeBounds,0));
  51. }
  52. }
  53. template<int N>
  54. void BVHNRefitter<N>::gather_subtree_refs(NodeRef& ref,
  55. size_t &subtrees,
  56. const size_t depth)
  57. {
  58. if (depth >= MAX_SUB_TREE_EXTRACTION_DEPTH)
  59. {
  60. assert(subtrees < MAX_NUM_SUB_TREES);
  61. subTrees[subtrees++] = ref;
  62. return;
  63. }
  64. if (ref.isAABBNode())
  65. {
  66. AABBNode* node = ref.getAABBNode();
  67. for (size_t i=0; i<N; i++) {
  68. NodeRef& child = node->child(i);
  69. if (unlikely(child == BVH::emptyNode)) continue;
  70. gather_subtree_refs(child,subtrees,depth+1);
  71. }
  72. }
  73. }
  74. template<int N>
  75. BBox3fa BVHNRefitter<N>::refit_toplevel(NodeRef& ref,
  76. size_t &subtrees,
  77. const BBox3fa *const subTreeBounds,
  78. const size_t depth)
  79. {
  80. if (depth >= MAX_SUB_TREE_EXTRACTION_DEPTH)
  81. {
  82. assert(subtrees < MAX_NUM_SUB_TREES);
  83. assert(subTrees[subtrees] == ref);
  84. return subTreeBounds[subtrees++];
  85. }
  86. if (ref.isAABBNode())
  87. {
  88. AABBNode* node = ref.getAABBNode();
  89. BBox3fa bounds[N];
  90. for (size_t i=0; i<N; i++)
  91. {
  92. NodeRef& child = node->child(i);
  93. if (unlikely(child == BVH::emptyNode))
  94. bounds[i] = BBox3fa(empty);
  95. else
  96. bounds[i] = refit_toplevel(child,subtrees,subTreeBounds,depth+1);
  97. }
  98. BBox3vf<N> boundsT = transpose<N>(bounds);
  99. /* set new bounds */
  100. node->lower_x = boundsT.lower.x;
  101. node->lower_y = boundsT.lower.y;
  102. node->lower_z = boundsT.lower.z;
  103. node->upper_x = boundsT.upper.x;
  104. node->upper_y = boundsT.upper.y;
  105. node->upper_z = boundsT.upper.z;
  106. return merge<N>(bounds);
  107. }
  108. else
  109. return leafBounds.leafBounds(ref);
  110. }
  111. // =========================================================
  112. // =========================================================
  113. // =========================================================
  114. template<int N>
  115. BBox3fa BVHNRefitter<N>::recurse_bottom(NodeRef& ref)
  116. {
  117. /* this is a leaf node */
  118. if (unlikely(ref.isLeaf()))
  119. return leafBounds.leafBounds(ref);
  120. /* recurse if this is an internal node */
  121. AABBNode* node = ref.getAABBNode();
  122. /* enable exclusive prefetch for >= AVX platforms */
  123. #if defined(__AVX__)
  124. BVH::prefetchW(ref);
  125. #endif
  126. BBox3fa bounds[N];
  127. for (size_t i=0; i<N; i++)
  128. if (unlikely(node->child(i) == BVH::emptyNode))
  129. {
  130. bounds[i] = BBox3fa(empty);
  131. }
  132. else
  133. bounds[i] = recurse_bottom(node->child(i));
  134. /* AOS to SOA transform */
  135. BBox3vf<N> boundsT = transpose<N>(bounds);
  136. /* set new bounds */
  137. node->lower_x = boundsT.lower.x;
  138. node->lower_y = boundsT.lower.y;
  139. node->lower_z = boundsT.lower.z;
  140. node->upper_x = boundsT.upper.x;
  141. node->upper_y = boundsT.upper.y;
  142. node->upper_z = boundsT.upper.z;
  143. return merge<N>(bounds);
  144. }
  145. template<int N, typename Mesh, typename Primitive>
  146. BVHNRefitT<N,Mesh,Primitive>::BVHNRefitT (BVH* bvh, Builder* builder, Mesh* mesh, size_t mode)
  147. : bvh(bvh), builder(builder), refitter(new BVHNRefitter<N>(bvh,*(typename BVHNRefitter<N>::LeafBoundsInterface*)this)), mesh(mesh), topologyVersion(0) {}
  148. template<int N, typename Mesh, typename Primitive>
  149. void BVHNRefitT<N,Mesh,Primitive>::clear()
  150. {
  151. if (builder)
  152. builder->clear();
  153. }
  154. template<int N, typename Mesh, typename Primitive>
  155. void BVHNRefitT<N,Mesh,Primitive>::build()
  156. {
  157. if (mesh->topologyChanged(topologyVersion)) {
  158. topologyVersion = mesh->getTopologyVersion();
  159. builder->build();
  160. }
  161. else
  162. refitter->refit();
  163. }
  164. template class BVHNRefitter<4>;
  165. #if defined(__AVX__)
  166. template class BVHNRefitter<8>;
  167. #endif
  168. #if defined(EMBREE_GEOMETRY_TRIANGLE)
  169. Builder* BVH4Triangle4MeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode);
  170. Builder* BVH4Triangle4vMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode);
  171. Builder* BVH4Triangle4iMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode);
  172. Builder* BVH4Triangle4MeshRefitSAH (void* accel, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<4,TriangleMesh,Triangle4> ((BVH4*)accel,BVH4Triangle4MeshBuilderSAH (accel,mesh,geomID,mode),mesh,mode); }
  173. Builder* BVH4Triangle4vMeshRefitSAH (void* accel, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<4,TriangleMesh,Triangle4v>((BVH4*)accel,BVH4Triangle4vMeshBuilderSAH(accel,mesh,geomID,mode),mesh,mode); }
  174. Builder* BVH4Triangle4iMeshRefitSAH (void* accel, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<4,TriangleMesh,Triangle4i>((BVH4*)accel,BVH4Triangle4iMeshBuilderSAH(accel,mesh,geomID,mode),mesh,mode); }
  175. #if defined(__AVX__)
  176. Builder* BVH8Triangle4MeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode);
  177. Builder* BVH8Triangle4vMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode);
  178. Builder* BVH8Triangle4iMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode);
  179. Builder* BVH8Triangle4MeshRefitSAH (void* accel, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<8,TriangleMesh,Triangle4> ((BVH8*)accel,BVH8Triangle4MeshBuilderSAH (accel,mesh,geomID,mode),mesh,mode); }
  180. Builder* BVH8Triangle4vMeshRefitSAH (void* accel, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<8,TriangleMesh,Triangle4v>((BVH8*)accel,BVH8Triangle4vMeshBuilderSAH(accel,mesh,geomID,mode),mesh,mode); }
  181. Builder* BVH8Triangle4iMeshRefitSAH (void* accel, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<8,TriangleMesh,Triangle4i>((BVH8*)accel,BVH8Triangle4iMeshBuilderSAH(accel,mesh,geomID,mode),mesh,mode); }
  182. #endif
  183. #endif
  184. #if defined(EMBREE_GEOMETRY_QUAD)
  185. Builder* BVH4Quad4vMeshBuilderSAH (void* bvh, QuadMesh* mesh, unsigned int geomID, size_t mode);
  186. Builder* BVH4Quad4vMeshRefitSAH (void* accel, QuadMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<4,QuadMesh,Quad4v>((BVH4*)accel,BVH4Quad4vMeshBuilderSAH(accel,mesh,geomID,mode),mesh,mode); }
  187. #if defined(__AVX__)
  188. Builder* BVH8Quad4vMeshBuilderSAH (void* bvh, QuadMesh* mesh, unsigned int geomID, size_t mode);
  189. Builder* BVH8Quad4vMeshRefitSAH (void* accel, QuadMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<8,QuadMesh,Quad4v>((BVH8*)accel,BVH8Quad4vMeshBuilderSAH(accel,mesh,geomID,mode),mesh,mode); }
  190. #endif
  191. #endif
  192. #if defined(EMBREE_GEOMETRY_USER)
  193. Builder* BVH4VirtualMeshBuilderSAH (void* bvh, UserGeometry* mesh, unsigned int geomID, size_t mode);
  194. Builder* BVH4VirtualMeshRefitSAH (void* accel, UserGeometry* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<4,UserGeometry,Object>((BVH4*)accel,BVH4VirtualMeshBuilderSAH(accel,mesh,geomID,mode),mesh,mode); }
  195. #if defined(__AVX__)
  196. Builder* BVH8VirtualMeshBuilderSAH (void* bvh, UserGeometry* mesh, unsigned int geomID, size_t mode);
  197. Builder* BVH8VirtualMeshRefitSAH (void* accel, UserGeometry* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<8,UserGeometry,Object>((BVH8*)accel,BVH8VirtualMeshBuilderSAH(accel,mesh,geomID,mode),mesh,mode); }
  198. #endif
  199. #endif
  200. #if defined(EMBREE_GEOMETRY_INSTANCE)
  201. Builder* BVH4InstanceMeshBuilderSAH (void* bvh, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode);
  202. Builder* BVH4InstanceMeshRefitSAH (void* accel, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) { return new BVHNRefitT<4,Instance,InstancePrimitive>((BVH4*)accel,BVH4InstanceMeshBuilderSAH(accel,mesh,gtype,geomID,mode),mesh,mode); }
  203. #if defined(__AVX__)
  204. Builder* BVH8InstanceMeshBuilderSAH (void* bvh, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode);
  205. Builder* BVH8InstanceMeshRefitSAH (void* accel, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) { return new BVHNRefitT<8,Instance,InstancePrimitive>((BVH8*)accel,BVH8InstanceMeshBuilderSAH(accel,mesh,gtype,geomID,mode),mesh,mode); }
  206. #endif
  207. #endif
  208. #if defined(EMBREE_GEOMETRY_INSTANCE_ARRAY)
  209. Builder* BVH4InstanceArrayMeshBuilderSAH (void* bvh, InstanceArray* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode);
  210. Builder* BVH4InstanceArrayMeshRefitSAH (void* accel, InstanceArray* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) { return new BVHNRefitT<4,InstanceArray,InstanceArrayPrimitive>((BVH4*)accel,BVH4InstanceArrayMeshBuilderSAH(accel,mesh,gtype,geomID,mode),mesh,mode); }
  211. #if defined(__AVX__)
  212. Builder* BVH8InstanceArrayMeshBuilderSAH (void* bvh, InstanceArray* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode);
  213. Builder* BVH8InstanceArrayMeshRefitSAH (void* accel, InstanceArray* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) { return new BVHNRefitT<8,InstanceArray,InstanceArrayPrimitive>((BVH8*)accel,BVH8InstanceArrayMeshBuilderSAH(accel,mesh,gtype,geomID,mode),mesh,mode); }
  214. #endif
  215. #endif
  216. }
  217. }