2
0

bvh_refit.cpp 10 KB

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