Path: blob/master/thirdparty/embree/kernels/bvh/bvh_refit.cpp
9912 views
// Copyright 2009-2021 Intel Corporation1// SPDX-License-Identifier: Apache-2.023#include "bvh_refit.h"4#include "bvh_statistics.h"56#include "../geometry/linei.h"7#include "../geometry/triangle.h"8#include "../geometry/trianglev.h"9#include "../geometry/trianglei.h"10#include "../geometry/quadv.h"11#include "../geometry/object.h"12#include "../geometry/instance.h"13#include "../geometry/instance_array.h"1415#include "../../common/algorithms/parallel_for.h"1617namespace embree18{19namespace isa20{21static const size_t SINGLE_THREAD_THRESHOLD = 4*1024;2223template<int N>24__forceinline bool compare(const typename BVHN<N>::NodeRef* a, const typename BVHN<N>::NodeRef* b)25{26size_t sa = *(size_t*)&a->node()->lower_x;27size_t sb = *(size_t*)&b->node()->lower_x;28return sa < sb;29}3031template<int N>32BVHNRefitter<N>::BVHNRefitter (BVH* bvh, const LeafBoundsInterface& leafBounds)33: bvh(bvh), leafBounds(leafBounds), numSubTrees(0)34{35}3637template<int N>38void BVHNRefitter<N>::refit()39{40if (bvh->numPrimitives <= SINGLE_THREAD_THRESHOLD) {41bvh->bounds = LBBox3fa(recurse_bottom(bvh->root));42}43else44{45BBox3fa subTreeBounds[MAX_NUM_SUB_TREES];46numSubTrees = 0;47gather_subtree_refs(bvh->root,numSubTrees,0);48if (numSubTrees)49parallel_for(size_t(0), numSubTrees, size_t(1), [&](const range<size_t>& r) {50for (size_t i=r.begin(); i<r.end(); i++) {51NodeRef& ref = subTrees[i];52subTreeBounds[i] = recurse_bottom(ref);53}54});5556numSubTrees = 0;57bvh->bounds = LBBox3fa(refit_toplevel(bvh->root,numSubTrees,subTreeBounds,0));58}59}6061template<int N>62void BVHNRefitter<N>::gather_subtree_refs(NodeRef& ref,63size_t &subtrees,64const size_t depth)65{66if (depth >= MAX_SUB_TREE_EXTRACTION_DEPTH)67{68assert(subtrees < MAX_NUM_SUB_TREES);69subTrees[subtrees++] = ref;70return;71}7273if (ref.isAABBNode())74{75AABBNode* node = ref.getAABBNode();76for (size_t i=0; i<N; i++) {77NodeRef& child = node->child(i);78if (unlikely(child == BVH::emptyNode)) continue;79gather_subtree_refs(child,subtrees,depth+1);80}81}82}8384template<int N>85BBox3fa BVHNRefitter<N>::refit_toplevel(NodeRef& ref,86size_t &subtrees,87const BBox3fa *const subTreeBounds,88const size_t depth)89{90if (depth >= MAX_SUB_TREE_EXTRACTION_DEPTH)91{92assert(subtrees < MAX_NUM_SUB_TREES);93assert(subTrees[subtrees] == ref);94return subTreeBounds[subtrees++];95}9697if (ref.isAABBNode())98{99AABBNode* node = ref.getAABBNode();100BBox3fa bounds[N];101102for (size_t i=0; i<N; i++)103{104NodeRef& child = node->child(i);105106if (unlikely(child == BVH::emptyNode))107bounds[i] = BBox3fa(empty);108else109bounds[i] = refit_toplevel(child,subtrees,subTreeBounds,depth+1);110}111112BBox3vf<N> boundsT = transpose<N>(bounds);113114/* set new bounds */115node->lower_x = boundsT.lower.x;116node->lower_y = boundsT.lower.y;117node->lower_z = boundsT.lower.z;118node->upper_x = boundsT.upper.x;119node->upper_y = boundsT.upper.y;120node->upper_z = boundsT.upper.z;121122return merge<N>(bounds);123}124else125return leafBounds.leafBounds(ref);126}127128// =========================================================129// =========================================================130// =========================================================131132133template<int N>134BBox3fa BVHNRefitter<N>::recurse_bottom(NodeRef& ref)135{136/* this is a leaf node */137if (unlikely(ref.isLeaf()))138return leafBounds.leafBounds(ref);139140/* recurse if this is an internal node */141AABBNode* node = ref.getAABBNode();142143/* enable exclusive prefetch for >= AVX platforms */144#if defined(__AVX__)145BVH::prefetchW(ref);146#endif147BBox3fa bounds[N];148149for (size_t i=0; i<N; i++)150if (unlikely(node->child(i) == BVH::emptyNode))151{152bounds[i] = BBox3fa(empty);153}154else155bounds[i] = recurse_bottom(node->child(i));156157/* AOS to SOA transform */158BBox3vf<N> boundsT = transpose<N>(bounds);159160/* set new bounds */161node->lower_x = boundsT.lower.x;162node->lower_y = boundsT.lower.y;163node->lower_z = boundsT.lower.z;164node->upper_x = boundsT.upper.x;165node->upper_y = boundsT.upper.y;166node->upper_z = boundsT.upper.z;167168return merge<N>(bounds);169}170171template<int N, typename Mesh, typename Primitive>172BVHNRefitT<N,Mesh,Primitive>::BVHNRefitT (BVH* bvh, Builder* builder, Mesh* mesh, size_t mode)173: bvh(bvh), builder(builder), refitter(new BVHNRefitter<N>(bvh,*(typename BVHNRefitter<N>::LeafBoundsInterface*)this)), mesh(mesh), topologyVersion(0) {}174175template<int N, typename Mesh, typename Primitive>176void BVHNRefitT<N,Mesh,Primitive>::clear()177{178if (builder)179builder->clear();180}181182template<int N, typename Mesh, typename Primitive>183void BVHNRefitT<N,Mesh,Primitive>::build()184{185if (mesh->topologyChanged(topologyVersion)) {186topologyVersion = mesh->getTopologyVersion();187builder->build();188}189else190refitter->refit();191}192193template class BVHNRefitter<4>;194#if defined(__AVX__)195template class BVHNRefitter<8>;196#endif197198#if defined(EMBREE_GEOMETRY_TRIANGLE)199Builder* BVH4Triangle4MeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode);200Builder* BVH4Triangle4vMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode);201Builder* BVH4Triangle4iMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode);202203Builder* 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); }204Builder* 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); }205Builder* 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); }206#if defined(__AVX__)207Builder* BVH8Triangle4MeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode);208Builder* BVH8Triangle4vMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode);209Builder* BVH8Triangle4iMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode);210211Builder* 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); }212Builder* 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); }213Builder* 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); }214#endif215#endif216217#if defined(EMBREE_GEOMETRY_QUAD)218Builder* BVH4Quad4vMeshBuilderSAH (void* bvh, QuadMesh* mesh, unsigned int geomID, size_t mode);219Builder* 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); }220221#if defined(__AVX__)222Builder* BVH8Quad4vMeshBuilderSAH (void* bvh, QuadMesh* mesh, unsigned int geomID, size_t mode);223Builder* 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); }224#endif225226#endif227228#if defined(EMBREE_GEOMETRY_USER)229Builder* BVH4VirtualMeshBuilderSAH (void* bvh, UserGeometry* mesh, unsigned int geomID, size_t mode);230Builder* 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); }231232#if defined(__AVX__)233Builder* BVH8VirtualMeshBuilderSAH (void* bvh, UserGeometry* mesh, unsigned int geomID, size_t mode);234Builder* 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); }235#endif236#endif237238#if defined(EMBREE_GEOMETRY_INSTANCE)239Builder* BVH4InstanceMeshBuilderSAH (void* bvh, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode);240Builder* 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); }241#if defined(__AVX__)242Builder* BVH8InstanceMeshBuilderSAH (void* bvh, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode);243Builder* 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); }244#endif245#endif246247#if defined(EMBREE_GEOMETRY_INSTANCE_ARRAY)248Builder* BVH4InstanceArrayMeshBuilderSAH (void* bvh, InstanceArray* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode);249Builder* 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); }250251#if defined(__AVX__)252Builder* BVH8InstanceArrayMeshBuilderSAH (void* bvh, InstanceArray* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode);253Builder* 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); }254#endif255#endif256}257}258259260