// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../builders/bvh_builder_hair.h" #include "../builders/primrefgen.h" #include "../geometry/pointi.h" #include "../geometry/linei.h" #include "../geometry/curveNi.h" #include "../geometry/curveNv.h" #if defined(EMBREE_GEOMETRY_CURVE) || defined(EMBREE_GEOMETRY_POINT) namespace embree { namespace isa { template struct BVHNHairBuilderSAH : public Builder { typedef BVHN BVH; typedef typename BVH::NodeRef NodeRef; BVH* bvh; Scene* scene; mvector prims; BVHBuilderHair::Settings settings; BVHNHairBuilderSAH (BVH* bvh, Scene* scene) : bvh(bvh), scene(scene), prims(scene->device,0) {} void build() { /* if we use the primrefarray for allocations we have to take it back from the BVH */ if (settings.finished_range_threshold != size_t(inf)) bvh->alloc.unshare(prims); /* fast path for empty BVH */ const size_t numPrimitives = scene->getNumPrimitives(Geometry::MTY_CURVES,false); if (numPrimitives == 0) { bvh->clear(); prims.clear(); return; } double t0 = bvh->preBuild(TOSTRING(isa) "::BVH" + toString(N) + "HairBuilderSAH"); /* create primref array */ prims.resize(numPrimitives); const PrimInfo pinfo = createPrimRefArray(scene,Geometry::MTY_CURVES,false,numPrimitives,prims,scene->progressInterface); /* estimate acceleration structure size */ const size_t node_bytes = pinfo.size()*sizeof(typename BVH::OBBNode)/(4*N); const size_t leaf_bytes = CurvePrimitive::bytes(pinfo.size()); bvh->alloc.init_estimate(node_bytes+leaf_bytes); /* builder settings */ settings.branchingFactor = N; settings.maxDepth = BVH::maxBuildDepthLeaf; settings.logBlockSize = bsf(CurvePrimitive::max_size()); settings.minLeafSize = CurvePrimitive::max_size(); settings.maxLeafSize = CurvePrimitive::max_size(); settings.finished_range_threshold = numPrimitives/1000; if (settings.finished_range_threshold < 1000) settings.finished_range_threshold = inf; /* creates a leaf node */ auto createLeaf = [&] (const PrimRef* prims, const range& set, const FastAllocator::CachedAllocator& alloc) -> NodeRef { if (set.size() == 0) return BVH::emptyNode; const unsigned int geomID0 = prims[set.begin()].geomID(); if (scene->get(geomID0)->getTypeMask() & Geometry::MTY_POINTS) return PointPrimitive::createLeaf(bvh,prims,set,alloc); else if (scene->get(geomID0)->getCurveBasis() == Geometry::GTY_BASIS_LINEAR) return LinePrimitive::createLeaf(bvh,prims,set,alloc); else return CurvePrimitive::createLeaf(bvh,prims,set,alloc); }; auto reportFinishedRange = [&] (const range& range) -> void { PrimRef* begin = prims.data()+range.begin(); PrimRef* end = prims.data()+range.end(); // FIXME: extended end for spatial split builder!!!!! size_t bytes = (size_t)end - (size_t)begin; bvh->alloc.addBlock(begin,bytes); }; /* build hierarchy */ typename BVH::NodeRef root = BVHBuilderHair::build (typename BVH::CreateAlloc(bvh), typename BVH::AABBNode::Create(), typename BVH::AABBNode::Set(), typename BVH::OBBNode::Create(), typename BVH::OBBNode::Set(), createLeaf,scene->progressInterface, reportFinishedRange, scene,prims.data(),pinfo,settings); bvh->set(root,LBBox3fa(pinfo.geomBounds),pinfo.size()); /* if we allocated using the primrefarray we have to keep it alive */ if (settings.finished_range_threshold != size_t(inf)) bvh->alloc.share(prims); /* clear temporary data for static geometry */ if (scene->isStaticAccel()) { prims.clear(); } bvh->cleanup(); bvh->postBuild(t0); } void clear() { prims.clear(); } }; /*! entry functions for the builder */ Builder* BVH4Curve4vBuilder_OBB_New (void* bvh, Scene* scene, size_t mode) { return new BVHNHairBuilderSAH<4,Curve4v,Line4i,Point4i>((BVH4*)bvh,scene); } Builder* BVH4Curve4iBuilder_OBB_New (void* bvh, Scene* scene, size_t mode) { return new BVHNHairBuilderSAH<4,Curve4i,Line4i,Point4i>((BVH4*)bvh,scene); } #if defined(__AVX__) Builder* BVH8Curve8vBuilder_OBB_New (void* bvh, Scene* scene, size_t mode) { return new BVHNHairBuilderSAH<8,Curve8v,Line8i,Point8i>((BVH8*)bvh,scene); } Builder* BVH4Curve8iBuilder_OBB_New (void* bvh, Scene* scene, size_t mode) { return new BVHNHairBuilderSAH<4,Curve8i,Line8i,Point8i>((BVH4*)bvh,scene); } #endif } } #endif