// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh.h" #include "bvh_builder.h" #include "../builders/bvh_builder_msmblur.h" #include "../builders/primrefgen.h" #include "../builders/splitter.h" #include "../geometry/linei.h" #include "../geometry/triangle.h" #include "../geometry/trianglev.h" #include "../geometry/trianglev_mb.h" #include "../geometry/trianglei.h" #include "../geometry/quadv.h" #include "../geometry/quadi.h" #include "../geometry/object.h" #include "../geometry/instance.h" #include "../geometry/instance_array.h" #include "../geometry/subgrid.h" #include "../common/state.h" // FIXME: remove after removing BVHNBuilderMBlurRootTimeSplitsSAH #include "../../common/algorithms/parallel_for_for.h" #include "../../common/algorithms/parallel_for_for_prefix_sum.h" namespace embree { namespace isa { #if 0 template struct CreateMBlurLeaf { typedef BVHN BVH; typedef typename BVH::NodeRef NodeRef; typedef typename BVH::NodeRecordMB NodeRecordMB; __forceinline CreateMBlurLeaf (BVH* bvh, PrimRef* prims, size_t time) : bvh(bvh), prims(prims), time(time) {} __forceinline NodeRecordMB operator() (const PrimRef* prims, const range& set, const FastAllocator::CachedAllocator& alloc) const { size_t items = Primitive::blocks(set.size()); size_t start = set.begin(); for (size_t i=start; iencodeLeaf((char*)accel,items); LBBox3fa allBounds = empty; for (size_t i=0; iscene, time)); return NodeRecordMB(node,allBounds); } BVH* bvh; PrimRef* prims; size_t time; }; #endif template struct CreateMSMBlurLeaf { typedef BVHN BVH; typedef typename BVH::NodeRef NodeRef; typedef typename BVH::NodeRecordMB4D NodeRecordMB4D; __forceinline CreateMSMBlurLeaf (BVH* bvh) : bvh(bvh) {} __forceinline const NodeRecordMB4D operator() (const BVHBuilderMSMBlur::BuildRecord& current, const FastAllocator::CachedAllocator& alloc) const { size_t items = Primitive::blocks(current.prims.size()); size_t start = current.prims.begin(); size_t end = current.prims.end(); for (size_t i=start; iencodeLeaf((char*)accel,items); LBBox3fa allBounds = empty; for (size_t i=0; idata(), start, current.prims.end(), bvh->scene, current.prims.time_range)); return NodeRecordMB4D(node,allBounds,current.prims.time_range); } BVH* bvh; }; /* Motion blur BVH with 4D nodes and internal time splits */ template struct BVHNBuilderMBlurSAH : public Builder { typedef BVHN BVH; typedef typename BVHN::NodeRef NodeRef; typedef typename BVHN::NodeRecordMB NodeRecordMB; typedef typename BVHN::AABBNodeMB AABBNodeMB; BVH* bvh; Scene* scene; const size_t sahBlockSize; const float intCost; const size_t minLeafSize; const size_t maxLeafSize; const Geometry::GTypeMask gtype_; BVHNBuilderMBlurSAH (BVH* bvh, Scene* scene, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const Geometry::GTypeMask gtype) : bvh(bvh), scene(scene), sahBlockSize(sahBlockSize), intCost(intCost), minLeafSize(minLeafSize), maxLeafSize(min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks)), gtype_(gtype) {} void build() { /* skip build for empty scene */ const size_t numPrimitives = scene->getNumPrimitives(gtype_,true); if (numPrimitives == 0) { bvh->clear(); return; } double t0 = bvh->preBuild(TOSTRING(isa) "::BVH" + toString(N) + "BuilderMBlurSAH"); #if PROFILE profile(2,PROFILE_RUNS,numPrimitives,[&] (ProfileTimer& timer) { #endif //const size_t numTimeSteps = scene->getNumTimeSteps(); //const size_t numTimeSegments = numTimeSteps-1; assert(numTimeSteps > 1); /*if (numTimeSegments == 1) buildSingleSegment(numPrimitives); else*/ buildMultiSegment(numPrimitives); #if PROFILE }); #endif /* clear temporary data for static geometry */ bvh->cleanup(); bvh->postBuild(t0); } #if 0 // No longer compatible when time_ranges are present for geometries. Would have to create temporal nodes sometimes, and put only a single geometry into leaf. void buildSingleSegment(size_t numPrimitives) { /* create primref array */ mvector prims(scene->device,numPrimitives); const PrimInfo pinfo = createPrimRefArrayMBlur(scene,gtype_,numPrimitives,prims,bvh->scene->progressInterface,0); /* early out if no valid primitives */ if (pinfo.size() == 0) { bvh->clear(); return; } /* estimate acceleration structure size */ const size_t node_bytes = pinfo.size()*sizeof(AABBNodeMB)/(4*N); const size_t leaf_bytes = size_t(1.2*Primitive::blocks(pinfo.size())*sizeof(Primitive)); bvh->alloc.init_estimate(node_bytes+leaf_bytes); /* settings for BVH build */ GeneralBVHBuilder::Settings settings; settings.branchingFactor = N; settings.maxDepth = BVH::maxBuildDepthLeaf; settings.logBlockSize = bsr(sahBlockSize); settings.minLeafSize = min(minLeafSize,maxLeafSize); settings.maxLeafSize = maxLeafSize; settings.travCost = travCost; settings.intCost = intCost; settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes); /* build hierarchy */ auto root = BVHBuilderBinnedSAH::build (typename BVH::CreateAlloc(bvh),typename BVH::AABBNodeMB::Create(),typename BVH::AABBNodeMB::Set(), CreateMBlurLeaf(bvh,prims.data(),0),bvh->scene->progressInterface, prims.data(),pinfo,settings); bvh->set(root.ref,root.lbounds,pinfo.size()); } #endif void buildMultiSegment(size_t numPrimitives) { /* create primref array */ mvector prims(scene->device,numPrimitives); PrimInfoMB pinfo = createPrimRefArrayMSMBlur(scene,gtype_,numPrimitives,prims,bvh->scene->progressInterface); /* early out if no valid primitives */ if (pinfo.size() == 0) { bvh->clear(); return; } /* estimate acceleration structure size */ const size_t node_bytes = pinfo.num_time_segments*sizeof(AABBNodeMB)/(4*N); const size_t leaf_bytes = size_t(1.2*Primitive::blocks(pinfo.num_time_segments)*sizeof(Primitive)); bvh->alloc.init_estimate(node_bytes+leaf_bytes); /* settings for BVH build */ BVHBuilderMSMBlur::Settings settings; settings.branchingFactor = N; settings.maxDepth = BVH::maxDepth; settings.logBlockSize = bsr(sahBlockSize); settings.minLeafSize = min(minLeafSize,maxLeafSize); settings.maxLeafSize = maxLeafSize; settings.travCost = travCost; settings.intCost = intCost; settings.singleLeafTimeSegment = Primitive::singleTimeSegment; settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes); /* build hierarchy */ auto root = BVHBuilderMSMBlur::build(prims,pinfo,scene->device, RecalculatePrimRef(scene), typename BVH::CreateAlloc(bvh), typename BVH::AABBNodeMB4D::Create(), typename BVH::AABBNodeMB4D::Set(), CreateMSMBlurLeaf(bvh), bvh->scene->progressInterface, settings); bvh->set(root.ref,root.lbounds,pinfo.num_time_segments); } void clear() { } }; /************************************************************************************/ /************************************************************************************/ /************************************************************************************/ /************************************************************************************/ struct GridRecalculatePrimRef { Scene* scene; const SubGridBuildData * const sgrids; __forceinline GridRecalculatePrimRef (Scene* scene, const SubGridBuildData * const sgrids) : scene(scene), sgrids(sgrids) {} __forceinline PrimRefMB operator() (const PrimRefMB& prim, const BBox1f time_range) const { const unsigned int geomID = prim.geomID(); const GridMesh* mesh = scene->get(geomID); const unsigned int buildID = prim.primID(); const SubGridBuildData &subgrid = sgrids[buildID]; const unsigned int primID = subgrid.primID; const size_t x = subgrid.x(); const size_t y = subgrid.y(); const LBBox3fa lbounds = mesh->linearBounds(mesh->grid(primID),x,y,time_range); const unsigned num_time_segments = mesh->numTimeSegments(); const range tbounds = mesh->timeSegmentRange(time_range); return PrimRefMB (lbounds, tbounds.size(), mesh->time_range, num_time_segments, geomID, buildID); } __forceinline LBBox3fa linearBounds(const PrimRefMB& prim, const BBox1f time_range) const { const unsigned int geomID = prim.geomID(); const GridMesh* mesh = scene->get(geomID); const unsigned int buildID = prim.primID(); const SubGridBuildData &subgrid = sgrids[buildID]; const unsigned int primID = subgrid.primID; const size_t x = subgrid.x(); const size_t y = subgrid.y(); return mesh->linearBounds(mesh->grid(primID),x,y,time_range); } }; template struct CreateMSMBlurLeafGrid { typedef BVHN BVH; typedef typename BVH::NodeRef NodeRef; typedef typename BVH::NodeRecordMB4D NodeRecordMB4D; __forceinline CreateMSMBlurLeafGrid (Scene* scene, BVH* bvh, const SubGridBuildData * const sgrids) : scene(scene), bvh(bvh), sgrids(sgrids) {} __forceinline const NodeRecordMB4D operator() (const BVHBuilderMSMBlur::BuildRecord& current, const FastAllocator::CachedAllocator& alloc) const { const size_t items = current.prims.size(); const size_t start = current.prims.begin(); const PrimRefMB* prims = current.prims.prims->data(); /* collect all subsets with unique geomIDs */ assert(items <= N); unsigned int geomIDs[N]; unsigned int num_geomIDs = 1; geomIDs[0] = prims[start].geomID(); for (size_t i=1;i* accel = (SubGridMBQBVHN*) alloc.malloc1(num_geomIDs*sizeof(SubGridMBQBVHN),BVH::byteAlignment); typename BVH::NodeRef node = bvh->encodeLeaf((char*)accel,num_geomIDs); LBBox3fa allBounds = empty; for (size_t g=0;gget(geomIDs[g]); unsigned int x[N]; unsigned int y[N]; unsigned int primID[N]; BBox3fa bounds0[N]; BBox3fa bounds1[N]; unsigned int pos = 0; for (size_t i=0;ilinearBounds(mesh->grid(sgrid_bd.primID),x,y,current.prims.time_range); allBounds.extend(newBounds); bounds0[pos] = newBounds.bounds0; bounds1[pos] = newBounds.bounds1; pos++; } assert(pos <= N); new (&accel[g]) SubGridMBQBVHN(x,y,primID,bounds0,bounds1,geomIDs[g],current.prims.time_range.lower,1.0f/current.prims.time_range.size(),pos); } return NodeRecordMB4D(node,allBounds,current.prims.time_range); } Scene *scene; BVH* bvh; const SubGridBuildData * const sgrids; }; #if 0 template struct CreateLeafGridMB { typedef BVHN BVH; typedef typename BVH::NodeRef NodeRef; typedef typename BVH::NodeRecordMB NodeRecordMB; __forceinline CreateLeafGridMB (Scene* scene, BVH* bvh, const SubGridBuildData * const sgrids) : scene(scene), bvh(bvh), sgrids(sgrids) {} __forceinline NodeRecordMB operator() (const PrimRef* prims, const range& set, const FastAllocator::CachedAllocator& alloc) const { const size_t items = set.size(); const size_t start = set.begin(); /* collect all subsets with unique geomIDs */ assert(items <= N); unsigned int geomIDs[N]; unsigned int num_geomIDs = 1; geomIDs[0] = prims[start].geomID(); for (size_t i=1;i* accel = (SubGridMBQBVHN*) alloc.malloc1(num_geomIDs*sizeof(SubGridMBQBVHN),BVH::byteAlignment); typename BVH::NodeRef node = bvh->encodeLeaf((char*)accel,num_geomIDs); LBBox3fa allBounds = empty; for (size_t g=0;gget(geomIDs[g]); unsigned int x[N]; unsigned int y[N]; unsigned int primID[N]; BBox3fa bounds0[N]; BBox3fa bounds1[N]; unsigned int pos = 0; for (size_t i=0;ibuildBounds(mesh->grid(sgrid_bd.primID),x,y,0,bounds0[pos]); bool MAYBE_UNUSED valid1 = mesh->buildBounds(mesh->grid(sgrid_bd.primID),x,y,1,bounds1[pos]); assert(valid0); assert(valid1); allBounds.extend(LBBox3fa(bounds0[pos],bounds1[pos])); pos++; } new (&accel[g]) SubGridMBQBVHN(x,y,primID,bounds0,bounds1,geomIDs[g],0.0f,1.0f,pos); } return NodeRecordMB(node,allBounds); } Scene *scene; BVH* bvh; const SubGridBuildData * const sgrids; }; #endif /* Motion blur BVH with 4D nodes and internal time splits */ template struct BVHNBuilderMBlurSAHGrid : public Builder { typedef BVHN BVH; typedef typename BVHN::NodeRef NodeRef; typedef typename BVHN::NodeRecordMB NodeRecordMB; typedef typename BVHN::AABBNodeMB AABBNodeMB; BVH* bvh; Scene* scene; const size_t sahBlockSize; const float intCost; const size_t minLeafSize; const size_t maxLeafSize; mvector sgrids; BVHNBuilderMBlurSAHGrid (BVH* bvh, Scene* scene, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize) : bvh(bvh), scene(scene), sahBlockSize(sahBlockSize), intCost(intCost), minLeafSize(minLeafSize), maxLeafSize(min(maxLeafSize,BVH::maxLeafBlocks)), sgrids(scene->device,0) {} PrimInfo createPrimRefArrayMBlurGrid(Scene* scene, mvector& prims, BuildProgressMonitor& progressMonitor, size_t itime) { /* first run to get #primitives */ ParallelForForPrefixSumState pstate; Scene::Iterator iter(scene); pstate.init(iter,size_t(1024)); /* iterate over all meshes in the scene */ PrimInfo pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range& r, size_t k, size_t geomID) -> PrimInfo { PrimInfo pinfo(empty); for (size_t j=r.begin(); jvalid(j,range(0,1))) continue; BBox3fa bounds = empty; const PrimRef prim(bounds,unsigned(geomID),unsigned(j)); pinfo.add_center2(prim,mesh->getNumSubGrids(j)); } return pinfo; }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); }); size_t numPrimitives = pinfo.size(); if (numPrimitives == 0) return pinfo; /* resize arrays */ sgrids.resize(numPrimitives); prims.resize(numPrimitives); /* second run to fill primrefs and SubGridBuildData arrays */ pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range& r, size_t k, size_t geomID, const PrimInfo& base) -> PrimInfo { k = base.size(); size_t p_index = k; PrimInfo pinfo(empty); for (size_t j=r.begin(); jgrid(j); if (!mesh->valid(j,range(0,1))) continue; for (unsigned int y=0; ybuildBounds(g,x,y,itime,bounds)) continue; // get bounds of subgrid const PrimRef prim(bounds,unsigned(geomID),unsigned(p_index)); pinfo.add_center2(prim); sgrids[p_index] = SubGridBuildData(x | g.get3x3FlagsX(x), y | g.get3x3FlagsY(y), unsigned(j)); prims[p_index++] = prim; } } return pinfo; }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); }); assert(pinfo.size() == numPrimitives); return pinfo; } PrimInfoMB createPrimRefArrayMSMBlurGrid(Scene* scene, mvector& prims, BuildProgressMonitor& progressMonitor, BBox1f t0t1 = BBox1f(0.0f,1.0f)) { /* first run to get #primitives */ ParallelForForPrefixSumState pstate; Scene::Iterator iter(scene); pstate.init(iter,size_t(1024)); /* iterate over all meshes in the scene */ PrimInfoMB pinfoMB = parallel_for_for_prefix_sum0( pstate, iter, PrimInfoMB(empty), [&](GridMesh* mesh, const range& r, size_t k, size_t /*geomID*/) -> PrimInfoMB { PrimInfoMB pinfoMB(empty); for (size_t j=r.begin(); jvalid(j, mesh->timeSegmentRange(t0t1))) continue; LBBox3fa bounds(empty); PrimInfoMB gridMB(0,mesh->getNumSubGrids(j)); pinfoMB.merge(gridMB); } return pinfoMB; }, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); }); size_t numPrimitives = pinfoMB.size(); if (numPrimitives == 0) return pinfoMB; /* resize arrays */ sgrids.resize(numPrimitives); prims.resize(numPrimitives); /* second run to fill primrefs and SubGridBuildData arrays */ pinfoMB = parallel_for_for_prefix_sum1( pstate, iter, PrimInfoMB(empty), [&](GridMesh* mesh, const range& r, size_t k, size_t geomID, const PrimInfoMB& base) -> PrimInfoMB { k = base.size(); size_t p_index = k; PrimInfoMB pinfoMB(empty); for (size_t j=r.begin(); jvalid(j, mesh->timeSegmentRange(t0t1))) continue; const GridMesh::Grid &g = mesh->grid(j); for (unsigned int y=0; ylinearBounds(g,x,y,t0t1),mesh->numTimeSegments(),mesh->time_range,mesh->numTimeSegments(),unsigned(geomID),unsigned(p_index)); pinfoMB.add_primref(prim); sgrids[p_index] = SubGridBuildData(x | g.get3x3FlagsX(x), y | g.get3x3FlagsY(y), unsigned(j)); prims[p_index++] = prim; } } return pinfoMB; }, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); }); assert(pinfoMB.size() == numPrimitives); pinfoMB.time_range = t0t1; return pinfoMB; } void build() { /* skip build for empty scene */ const size_t numPrimitives = scene->getNumPrimitives(GridMesh::geom_type,true); if (numPrimitives == 0) { bvh->clear(); return; } double t0 = bvh->preBuild(TOSTRING(isa) "::BVH" + toString(N) + "BuilderMBlurSAHGrid"); //const size_t numTimeSteps = scene->getNumTimeSteps(); //const size_t numTimeSegments = numTimeSteps-1; assert(numTimeSteps > 1); //if (numTimeSegments == 1) // buildSingleSegment(numPrimitives); //else buildMultiSegment(numPrimitives); /* clear temporary data for static geometry */ bvh->cleanup(); bvh->postBuild(t0); } #if 0 void buildSingleSegment(size_t numPrimitives) { /* create primref array */ mvector prims(scene->device,numPrimitives); const PrimInfo pinfo = createPrimRefArrayMBlurGrid(scene,prims,bvh->scene->progressInterface,0); /* early out if no valid primitives */ if (pinfo.size() == 0) { bvh->clear(); return; } /* estimate acceleration structure size */ const size_t node_bytes = pinfo.size()*sizeof(AABBNodeMB)/(4*N); //TODO: check leaf_bytes const size_t leaf_bytes = size_t(1.2*(float)numPrimitives/N * sizeof(SubGridQBVHN)); bvh->alloc.init_estimate(node_bytes+leaf_bytes); /* settings for BVH build */ GeneralBVHBuilder::Settings settings; settings.branchingFactor = N; settings.maxDepth = BVH::maxBuildDepthLeaf; settings.logBlockSize = bsr(sahBlockSize); settings.minLeafSize = min(minLeafSize,maxLeafSize); settings.maxLeafSize = maxLeafSize; settings.travCost = travCost; settings.intCost = intCost; settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes); /* build hierarchy */ auto root = BVHBuilderBinnedSAH::build (typename BVH::CreateAlloc(bvh), typename BVH::AABBNodeMB::Create(), typename BVH::AABBNodeMB::Set(), CreateLeafGridMB(scene,bvh,sgrids.data()), bvh->scene->progressInterface, prims.data(),pinfo,settings); bvh->set(root.ref,root.lbounds,pinfo.size()); } #endif void buildMultiSegment(size_t numPrimitives) { /* create primref array */ mvector prims(scene->device,numPrimitives); PrimInfoMB pinfo = createPrimRefArrayMSMBlurGrid(scene,prims,bvh->scene->progressInterface); /* early out if no valid primitives */ if (pinfo.size() == 0) { bvh->clear(); return; } GridRecalculatePrimRef recalculatePrimRef(scene,sgrids.data()); /* estimate acceleration structure size */ const size_t node_bytes = pinfo.num_time_segments*sizeof(AABBNodeMB)/(4*N); //FIXME: check leaf_bytes //const size_t leaf_bytes = size_t(1.2*Primitive::blocks(pinfo.num_time_segments)*sizeof(SubGridQBVHN)); const size_t leaf_bytes = size_t(1.2*(float)numPrimitives/N * sizeof(SubGridQBVHN)); bvh->alloc.init_estimate(node_bytes+leaf_bytes); /* settings for BVH build */ BVHBuilderMSMBlur::Settings settings; settings.branchingFactor = N; settings.maxDepth = BVH::maxDepth; settings.logBlockSize = bsr(sahBlockSize); settings.minLeafSize = min(minLeafSize,maxLeafSize); settings.maxLeafSize = maxLeafSize; settings.travCost = travCost; settings.intCost = intCost; settings.singleLeafTimeSegment = false; settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes); /* build hierarchy */ auto root = BVHBuilderMSMBlur::build(prims,pinfo,scene->device, recalculatePrimRef, typename BVH::CreateAlloc(bvh), typename BVH::AABBNodeMB4D::Create(), typename BVH::AABBNodeMB4D::Set(), CreateMSMBlurLeafGrid(scene,bvh,sgrids.data()), bvh->scene->progressInterface, settings); bvh->set(root.ref,root.lbounds,pinfo.num_time_segments); } void clear() { } }; /************************************************************************************/ /************************************************************************************/ /************************************************************************************/ /************************************************************************************/ #if defined(EMBREE_GEOMETRY_TRIANGLE) Builder* BVH4Triangle4iMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<4,TriangleMesh,Triangle4i>((BVH4*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_TRIANGLE_MESH); } Builder* BVH4Triangle4vMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<4,TriangleMesh,Triangle4vMB>((BVH4*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_TRIANGLE_MESH); } #if defined(__AVX__) Builder* BVH8Triangle4iMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<8,TriangleMesh,Triangle4i>((BVH8*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_TRIANGLE_MESH); } Builder* BVH8Triangle4vMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<8,TriangleMesh,Triangle4vMB>((BVH8*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_TRIANGLE_MESH); } #endif #endif #if defined(EMBREE_GEOMETRY_QUAD) Builder* BVH4Quad4iMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<4,QuadMesh,Quad4i>((BVH4*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_QUAD_MESH); } #if defined(__AVX__) Builder* BVH8Quad4iMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<8,QuadMesh,Quad4i>((BVH8*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_QUAD_MESH); } #endif #endif #if defined(EMBREE_GEOMETRY_USER) Builder* BVH4VirtualMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { int minLeafSize = scene->device->object_accel_mb_min_leaf_size; int maxLeafSize = scene->device->object_accel_mb_max_leaf_size; return new BVHNBuilderMBlurSAH<4,UserGeometry,Object>((BVH4*)bvh,scene,4,1.0f,minLeafSize,maxLeafSize,Geometry::MTY_USER_GEOMETRY); } #if defined(__AVX__) Builder* BVH8VirtualMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { int minLeafSize = scene->device->object_accel_mb_min_leaf_size; int maxLeafSize = scene->device->object_accel_mb_max_leaf_size; return new BVHNBuilderMBlurSAH<8,UserGeometry,Object>((BVH8*)bvh,scene,8,1.0f,minLeafSize,maxLeafSize,Geometry::MTY_USER_GEOMETRY); } #endif #endif #if defined(EMBREE_GEOMETRY_INSTANCE) Builder* BVH4InstanceMBSceneBuilderSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype) { return new BVHNBuilderMBlurSAH<4,Instance,InstancePrimitive>((BVH4*)bvh,scene,4,1.0f,1,1,gtype); } #if defined(__AVX__) Builder* BVH8InstanceMBSceneBuilderSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype) { return new BVHNBuilderMBlurSAH<8,Instance,InstancePrimitive>((BVH8*)bvh,scene,8,1.0f,1,1,gtype); } #endif #endif #if defined(EMBREE_GEOMETRY_INSTANCE_ARRAY) Builder* BVH4InstanceArrayMBSceneBuilderSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype) { return new BVHNBuilderMBlurSAH<4,InstanceArray,InstanceArrayPrimitive>((BVH4*)bvh,scene,4,1.0f,1,1,gtype); } #if defined(__AVX__) Builder* BVH8InstanceArrayMBSceneBuilderSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype) { return new BVHNBuilderMBlurSAH<8,InstanceArray,InstanceArrayPrimitive>((BVH8*)bvh,scene,8,1.0f,1,1,gtype); } #endif #endif #if defined(EMBREE_GEOMETRY_GRID) Builder* BVH4GridMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAHGrid<4>((BVH4*)bvh,scene,4,1.0f,4,4); } #if defined(__AVX__) Builder* BVH8GridMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAHGrid<8>((BVH8*)bvh,scene,8,1.0f,8,8); } #endif #endif } }