Path: blob/master/thirdparty/embree/kernels/bvh/bvh_builder_sah_mb.cpp
9906 views
// Copyright 2009-2021 Intel Corporation1// SPDX-License-Identifier: Apache-2.023#include "bvh.h"4#include "bvh_builder.h"5#include "../builders/bvh_builder_msmblur.h"67#include "../builders/primrefgen.h"8#include "../builders/splitter.h"910#include "../geometry/linei.h"11#include "../geometry/triangle.h"12#include "../geometry/trianglev.h"13#include "../geometry/trianglev_mb.h"14#include "../geometry/trianglei.h"15#include "../geometry/quadv.h"16#include "../geometry/quadi.h"17#include "../geometry/object.h"18#include "../geometry/instance.h"19#include "../geometry/instance_array.h"20#include "../geometry/subgrid.h"2122#include "../common/state.h"2324// FIXME: remove after removing BVHNBuilderMBlurRootTimeSplitsSAH25#include "../../common/algorithms/parallel_for_for.h"26#include "../../common/algorithms/parallel_for_for_prefix_sum.h"272829namespace embree30{31namespace isa32{3334#if 035template<int N, typename Primitive>36struct CreateMBlurLeaf37{38typedef BVHN<N> BVH;39typedef typename BVH::NodeRef NodeRef;40typedef typename BVH::NodeRecordMB NodeRecordMB;4142__forceinline CreateMBlurLeaf (BVH* bvh, PrimRef* prims, size_t time) : bvh(bvh), prims(prims), time(time) {}4344__forceinline NodeRecordMB operator() (const PrimRef* prims, const range<size_t>& set, const FastAllocator::CachedAllocator& alloc) const45{46size_t items = Primitive::blocks(set.size());47size_t start = set.begin();48for (size_t i=start; i<end; i++) assert((*current.prims.prims)[start].geomID() == (*current.prims.prims)[i].geomID()); // assert that all geomIDs are identical49Primitive* accel = (Primitive*) alloc.malloc1(items*sizeof(Primitive),BVH::byteAlignment);50NodeRef node = bvh->encodeLeaf((char*)accel,items);5152LBBox3fa allBounds = empty;53for (size_t i=0; i<items; i++)54allBounds.extend(accel[i].fillMB(prims, start, set.end(), bvh->scene, time));5556return NodeRecordMB(node,allBounds);57}5859BVH* bvh;60PrimRef* prims;61size_t time;62};63#endif6465template<int N, typename Mesh, typename Primitive>66struct CreateMSMBlurLeaf67{68typedef BVHN<N> BVH;69typedef typename BVH::NodeRef NodeRef;70typedef typename BVH::NodeRecordMB4D NodeRecordMB4D;7172__forceinline CreateMSMBlurLeaf (BVH* bvh) : bvh(bvh) {}7374__forceinline const NodeRecordMB4D operator() (const BVHBuilderMSMBlur::BuildRecord& current, const FastAllocator::CachedAllocator& alloc) const75{76size_t items = Primitive::blocks(current.prims.size());77size_t start = current.prims.begin();78size_t end = current.prims.end();79for (size_t i=start; i<end; i++) assert((*current.prims.prims)[start].geomID() == (*current.prims.prims)[i].geomID()); // assert that all geomIDs are identical80Primitive* accel = (Primitive*) alloc.malloc1(items*sizeof(Primitive),BVH::byteNodeAlignment);81NodeRef node = bvh->encodeLeaf((char*)accel,items);82LBBox3fa allBounds = empty;83for (size_t i=0; i<items; i++)84allBounds.extend(accel[i].fillMB(current.prims.prims->data(), start, current.prims.end(), bvh->scene, current.prims.time_range));85return NodeRecordMB4D(node,allBounds,current.prims.time_range);86}8788BVH* bvh;89};9091/* Motion blur BVH with 4D nodes and internal time splits */92template<int N, typename Mesh, typename Primitive>93struct BVHNBuilderMBlurSAH : public Builder94{95typedef BVHN<N> BVH;96typedef typename BVHN<N>::NodeRef NodeRef;97typedef typename BVHN<N>::NodeRecordMB NodeRecordMB;98typedef typename BVHN<N>::AABBNodeMB AABBNodeMB;99100BVH* bvh;101Scene* scene;102const size_t sahBlockSize;103const float intCost;104const size_t minLeafSize;105const size_t maxLeafSize;106const Geometry::GTypeMask gtype_;107108BVHNBuilderMBlurSAH (BVH* bvh, Scene* scene, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const Geometry::GTypeMask gtype)109: bvh(bvh), scene(scene), sahBlockSize(sahBlockSize), intCost(intCost), minLeafSize(minLeafSize), maxLeafSize(min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks)), gtype_(gtype) {}110111void build()112{113/* skip build for empty scene */114const size_t numPrimitives = scene->getNumPrimitives(gtype_,true);115if (numPrimitives == 0) { bvh->clear(); return; }116117double t0 = bvh->preBuild(TOSTRING(isa) "::BVH" + toString(N) + "BuilderMBlurSAH");118119#if PROFILE120profile(2,PROFILE_RUNS,numPrimitives,[&] (ProfileTimer& timer) {121#endif122123//const size_t numTimeSteps = scene->getNumTimeSteps<typename Mesh::type_t,true>();124//const size_t numTimeSegments = numTimeSteps-1; assert(numTimeSteps > 1);125126/*if (numTimeSegments == 1)127buildSingleSegment(numPrimitives);128else*/129buildMultiSegment(numPrimitives);130131#if PROFILE132});133#endif134135/* clear temporary data for static geometry */136bvh->cleanup();137bvh->postBuild(t0);138}139140#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.141void buildSingleSegment(size_t numPrimitives)142{143/* create primref array */144mvector<PrimRef> prims(scene->device,numPrimitives);145const PrimInfo pinfo = createPrimRefArrayMBlur(scene,gtype_,numPrimitives,prims,bvh->scene->progressInterface,0);146/* early out if no valid primitives */147if (pinfo.size() == 0) { bvh->clear(); return; }148/* estimate acceleration structure size */149const size_t node_bytes = pinfo.size()*sizeof(AABBNodeMB)/(4*N);150const size_t leaf_bytes = size_t(1.2*Primitive::blocks(pinfo.size())*sizeof(Primitive));151bvh->alloc.init_estimate(node_bytes+leaf_bytes);152153/* settings for BVH build */154GeneralBVHBuilder::Settings settings;155settings.branchingFactor = N;156settings.maxDepth = BVH::maxBuildDepthLeaf;157settings.logBlockSize = bsr(sahBlockSize);158settings.minLeafSize = min(minLeafSize,maxLeafSize);159settings.maxLeafSize = maxLeafSize;160settings.travCost = travCost;161settings.intCost = intCost;162settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes);163164/* build hierarchy */165auto root = BVHBuilderBinnedSAH::build<NodeRecordMB>166(typename BVH::CreateAlloc(bvh),typename BVH::AABBNodeMB::Create(),typename BVH::AABBNodeMB::Set(),167CreateMBlurLeaf<N,Primitive>(bvh,prims.data(),0),bvh->scene->progressInterface,168prims.data(),pinfo,settings);169170bvh->set(root.ref,root.lbounds,pinfo.size());171}172#endif173174void buildMultiSegment(size_t numPrimitives)175{176/* create primref array */177mvector<PrimRefMB> prims(scene->device,numPrimitives);178PrimInfoMB pinfo = createPrimRefArrayMSMBlur(scene,gtype_,numPrimitives,prims,bvh->scene->progressInterface);179180/* early out if no valid primitives */181if (pinfo.size() == 0) { bvh->clear(); return; }182183/* estimate acceleration structure size */184const size_t node_bytes = pinfo.num_time_segments*sizeof(AABBNodeMB)/(4*N);185const size_t leaf_bytes = size_t(1.2*Primitive::blocks(pinfo.num_time_segments)*sizeof(Primitive));186bvh->alloc.init_estimate(node_bytes+leaf_bytes);187188/* settings for BVH build */189BVHBuilderMSMBlur::Settings settings;190settings.branchingFactor = N;191settings.maxDepth = BVH::maxDepth;192settings.logBlockSize = bsr(sahBlockSize);193settings.minLeafSize = min(minLeafSize,maxLeafSize);194settings.maxLeafSize = maxLeafSize;195settings.travCost = travCost;196settings.intCost = intCost;197settings.singleLeafTimeSegment = Primitive::singleTimeSegment;198settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes);199200/* build hierarchy */201auto root =202BVHBuilderMSMBlur::build<NodeRef>(prims,pinfo,scene->device,203RecalculatePrimRef<Mesh>(scene),204typename BVH::CreateAlloc(bvh),205typename BVH::AABBNodeMB4D::Create(),206typename BVH::AABBNodeMB4D::Set(),207CreateMSMBlurLeaf<N,Mesh,Primitive>(bvh),208bvh->scene->progressInterface,209settings);210211bvh->set(root.ref,root.lbounds,pinfo.num_time_segments);212}213214void clear() {215}216};217218/************************************************************************************/219/************************************************************************************/220/************************************************************************************/221/************************************************************************************/222223struct GridRecalculatePrimRef224{225Scene* scene;226const SubGridBuildData * const sgrids;227228__forceinline GridRecalculatePrimRef (Scene* scene, const SubGridBuildData * const sgrids)229: scene(scene), sgrids(sgrids) {}230231__forceinline PrimRefMB operator() (const PrimRefMB& prim, const BBox1f time_range) const232{233const unsigned int geomID = prim.geomID();234const GridMesh* mesh = scene->get<GridMesh>(geomID);235const unsigned int buildID = prim.primID();236const SubGridBuildData &subgrid = sgrids[buildID];237const unsigned int primID = subgrid.primID;238const size_t x = subgrid.x();239const size_t y = subgrid.y();240const LBBox3fa lbounds = mesh->linearBounds(mesh->grid(primID),x,y,time_range);241const unsigned num_time_segments = mesh->numTimeSegments();242const range<int> tbounds = mesh->timeSegmentRange(time_range);243return PrimRefMB (lbounds, tbounds.size(), mesh->time_range, num_time_segments, geomID, buildID);244}245246__forceinline LBBox3fa linearBounds(const PrimRefMB& prim, const BBox1f time_range) const {247const unsigned int geomID = prim.geomID();248const GridMesh* mesh = scene->get<GridMesh>(geomID);249const unsigned int buildID = prim.primID();250const SubGridBuildData &subgrid = sgrids[buildID];251const unsigned int primID = subgrid.primID;252const size_t x = subgrid.x();253const size_t y = subgrid.y();254return mesh->linearBounds(mesh->grid(primID),x,y,time_range);255}256257};258259template<int N>260struct CreateMSMBlurLeafGrid261{262typedef BVHN<N> BVH;263typedef typename BVH::NodeRef NodeRef;264typedef typename BVH::NodeRecordMB4D NodeRecordMB4D;265266__forceinline CreateMSMBlurLeafGrid (Scene* scene, BVH* bvh, const SubGridBuildData * const sgrids) : scene(scene), bvh(bvh), sgrids(sgrids) {}267268__forceinline const NodeRecordMB4D operator() (const BVHBuilderMSMBlur::BuildRecord& current, const FastAllocator::CachedAllocator& alloc) const269{270const size_t items = current.prims.size();271const size_t start = current.prims.begin();272273const PrimRefMB* prims = current.prims.prims->data();274/* collect all subsets with unique geomIDs */275assert(items <= N);276unsigned int geomIDs[N];277unsigned int num_geomIDs = 1;278geomIDs[0] = prims[start].geomID();279280for (size_t i=1;i<items;i++)281{282bool found = false;283const unsigned int new_geomID = prims[start+i].geomID();284for (size_t j=0;j<num_geomIDs;j++)285if (new_geomID == geomIDs[j])286{ found = true; break; }287if (!found)288geomIDs[num_geomIDs++] = new_geomID;289}290291/* allocate all leaf memory in one single block */292SubGridMBQBVHN<N>* accel = (SubGridMBQBVHN<N>*) alloc.malloc1(num_geomIDs*sizeof(SubGridMBQBVHN<N>),BVH::byteAlignment);293typename BVH::NodeRef node = bvh->encodeLeaf((char*)accel,num_geomIDs);294295LBBox3fa allBounds = empty;296297for (size_t g=0;g<num_geomIDs;g++)298{299const GridMesh* __restrict__ const mesh = scene->get<GridMesh>(geomIDs[g]);300unsigned int x[N];301unsigned int y[N];302unsigned int primID[N];303BBox3fa bounds0[N];304BBox3fa bounds1[N];305unsigned int pos = 0;306for (size_t i=0;i<items;i++)307{308if (unlikely(prims[start+i].geomID() != geomIDs[g])) continue;309310const SubGridBuildData &sgrid_bd = sgrids[prims[start+i].primID()];311x[pos] = sgrid_bd.sx;312y[pos] = sgrid_bd.sy;313primID[pos] = sgrid_bd.primID;314const size_t x = sgrid_bd.x();315const size_t y = sgrid_bd.y();316LBBox3fa newBounds = mesh->linearBounds(mesh->grid(sgrid_bd.primID),x,y,current.prims.time_range);317allBounds.extend(newBounds);318bounds0[pos] = newBounds.bounds0;319bounds1[pos] = newBounds.bounds1;320pos++;321}322assert(pos <= N);323new (&accel[g]) SubGridMBQBVHN<N>(x,y,primID,bounds0,bounds1,geomIDs[g],current.prims.time_range.lower,1.0f/current.prims.time_range.size(),pos);324}325return NodeRecordMB4D(node,allBounds,current.prims.time_range);326}327328Scene *scene;329BVH* bvh;330const SubGridBuildData * const sgrids;331};332333#if 0334template<int N>335struct CreateLeafGridMB336{337typedef BVHN<N> BVH;338typedef typename BVH::NodeRef NodeRef;339typedef typename BVH::NodeRecordMB NodeRecordMB;340341__forceinline CreateLeafGridMB (Scene* scene, BVH* bvh, const SubGridBuildData * const sgrids)342: scene(scene), bvh(bvh), sgrids(sgrids) {}343344__forceinline NodeRecordMB operator() (const PrimRef* prims, const range<size_t>& set, const FastAllocator::CachedAllocator& alloc) const345{346const size_t items = set.size();347const size_t start = set.begin();348349/* collect all subsets with unique geomIDs */350assert(items <= N);351unsigned int geomIDs[N];352unsigned int num_geomIDs = 1;353geomIDs[0] = prims[start].geomID();354355for (size_t i=1;i<items;i++)356{357bool found = false;358const unsigned int new_geomID = prims[start+i].geomID();359for (size_t j=0;j<num_geomIDs;j++)360if (new_geomID == geomIDs[j])361{ found = true; break; }362if (!found)363geomIDs[num_geomIDs++] = new_geomID;364}365366/* allocate all leaf memory in one single block */367SubGridMBQBVHN<N>* accel = (SubGridMBQBVHN<N>*) alloc.malloc1(num_geomIDs*sizeof(SubGridMBQBVHN<N>),BVH::byteAlignment);368typename BVH::NodeRef node = bvh->encodeLeaf((char*)accel,num_geomIDs);369370LBBox3fa allBounds = empty;371372for (size_t g=0;g<num_geomIDs;g++)373{374const GridMesh* __restrict__ const mesh = scene->get<GridMesh>(geomIDs[g]);375376unsigned int x[N];377unsigned int y[N];378unsigned int primID[N];379BBox3fa bounds0[N];380BBox3fa bounds1[N];381unsigned int pos = 0;382for (size_t i=0;i<items;i++)383{384if (unlikely(prims[start+i].geomID() != geomIDs[g])) continue;385386const SubGridBuildData &sgrid_bd = sgrids[prims[start+i].primID()];387x[pos] = sgrid_bd.sx;388y[pos] = sgrid_bd.sy;389primID[pos] = sgrid_bd.primID;390const size_t x = sgrid_bd.x();391const size_t y = sgrid_bd.y();392bool MAYBE_UNUSED valid0 = mesh->buildBounds(mesh->grid(sgrid_bd.primID),x,y,0,bounds0[pos]);393bool MAYBE_UNUSED valid1 = mesh->buildBounds(mesh->grid(sgrid_bd.primID),x,y,1,bounds1[pos]);394assert(valid0);395assert(valid1);396allBounds.extend(LBBox3fa(bounds0[pos],bounds1[pos]));397pos++;398}399new (&accel[g]) SubGridMBQBVHN<N>(x,y,primID,bounds0,bounds1,geomIDs[g],0.0f,1.0f,pos);400}401return NodeRecordMB(node,allBounds);402}403404Scene *scene;405BVH* bvh;406const SubGridBuildData * const sgrids;407};408#endif409410411/* Motion blur BVH with 4D nodes and internal time splits */412template<int N>413struct BVHNBuilderMBlurSAHGrid : public Builder414{415typedef BVHN<N> BVH;416typedef typename BVHN<N>::NodeRef NodeRef;417typedef typename BVHN<N>::NodeRecordMB NodeRecordMB;418typedef typename BVHN<N>::AABBNodeMB AABBNodeMB;419420BVH* bvh;421Scene* scene;422const size_t sahBlockSize;423const float intCost;424const size_t minLeafSize;425const size_t maxLeafSize;426mvector<SubGridBuildData> sgrids;427428429BVHNBuilderMBlurSAHGrid (BVH* bvh, Scene* scene, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize)430: bvh(bvh), scene(scene), sahBlockSize(sahBlockSize), intCost(intCost), minLeafSize(minLeafSize), maxLeafSize(min(maxLeafSize,BVH::maxLeafBlocks)), sgrids(scene->device,0) {}431432433PrimInfo createPrimRefArrayMBlurGrid(Scene* scene, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor, size_t itime)434{435/* first run to get #primitives */436ParallelForForPrefixSumState<PrimInfo> pstate;437Scene::Iterator<GridMesh,true> iter(scene);438439pstate.init(iter,size_t(1024));440441/* iterate over all meshes in the scene */442PrimInfo pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfo {443444PrimInfo pinfo(empty);445for (size_t j=r.begin(); j<r.end(); j++)446{447if (!mesh->valid(j,range<size_t>(0,1))) continue;448BBox3fa bounds = empty;449const PrimRef prim(bounds,unsigned(geomID),unsigned(j));450pinfo.add_center2(prim,mesh->getNumSubGrids(j));451}452return pinfo;453}, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });454455size_t numPrimitives = pinfo.size();456if (numPrimitives == 0) return pinfo;457458/* resize arrays */459sgrids.resize(numPrimitives);460prims.resize(numPrimitives);461462/* second run to fill primrefs and SubGridBuildData arrays */463pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfo& base) -> PrimInfo {464465k = base.size();466size_t p_index = k;467PrimInfo pinfo(empty);468for (size_t j=r.begin(); j<r.end(); j++)469{470const GridMesh::Grid &g = mesh->grid(j);471if (!mesh->valid(j,range<size_t>(0,1))) continue;472473for (unsigned int y=0; y<g.resY-1u; y+=2)474for (unsigned int x=0; x<g.resX-1u; x+=2)475{476BBox3fa bounds = empty;477if (!mesh->buildBounds(g,x,y,itime,bounds)) continue; // get bounds of subgrid478const PrimRef prim(bounds,unsigned(geomID),unsigned(p_index));479pinfo.add_center2(prim);480sgrids[p_index] = SubGridBuildData(x | g.get3x3FlagsX(x), y | g.get3x3FlagsY(y), unsigned(j));481prims[p_index++] = prim;482}483}484return pinfo;485}, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });486487assert(pinfo.size() == numPrimitives);488return pinfo;489}490491PrimInfoMB createPrimRefArrayMSMBlurGrid(Scene* scene, mvector<PrimRefMB>& prims, BuildProgressMonitor& progressMonitor, BBox1f t0t1 = BBox1f(0.0f,1.0f))492{493/* first run to get #primitives */494ParallelForForPrefixSumState<PrimInfoMB> pstate;495Scene::Iterator<GridMesh,true> iter(scene);496497pstate.init(iter,size_t(1024));498/* iterate over all meshes in the scene */499PrimInfoMB pinfoMB = parallel_for_for_prefix_sum0( pstate, iter, PrimInfoMB(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t /*geomID*/) -> PrimInfoMB {500501PrimInfoMB pinfoMB(empty);502for (size_t j=r.begin(); j<r.end(); j++)503{504if (!mesh->valid(j, mesh->timeSegmentRange(t0t1))) continue;505LBBox3fa bounds(empty);506PrimInfoMB gridMB(0,mesh->getNumSubGrids(j));507pinfoMB.merge(gridMB);508}509return pinfoMB;510}, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });511512size_t numPrimitives = pinfoMB.size();513if (numPrimitives == 0) return pinfoMB;514515/* resize arrays */516sgrids.resize(numPrimitives);517prims.resize(numPrimitives);518/* second run to fill primrefs and SubGridBuildData arrays */519pinfoMB = parallel_for_for_prefix_sum1( pstate, iter, PrimInfoMB(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfoMB& base) -> PrimInfoMB {520521k = base.size();522size_t p_index = k;523PrimInfoMB pinfoMB(empty);524for (size_t j=r.begin(); j<r.end(); j++)525{526if (!mesh->valid(j, mesh->timeSegmentRange(t0t1))) continue;527const GridMesh::Grid &g = mesh->grid(j);528529for (unsigned int y=0; y<g.resY-1u; y+=2)530for (unsigned int x=0; x<g.resX-1u; x+=2)531{532const PrimRefMB prim(mesh->linearBounds(g,x,y,t0t1),mesh->numTimeSegments(),mesh->time_range,mesh->numTimeSegments(),unsigned(geomID),unsigned(p_index));533pinfoMB.add_primref(prim);534sgrids[p_index] = SubGridBuildData(x | g.get3x3FlagsX(x), y | g.get3x3FlagsY(y), unsigned(j));535prims[p_index++] = prim;536}537}538return pinfoMB;539}, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });540541assert(pinfoMB.size() == numPrimitives);542pinfoMB.time_range = t0t1;543return pinfoMB;544}545546void build()547{548/* skip build for empty scene */549const size_t numPrimitives = scene->getNumPrimitives(GridMesh::geom_type,true);550if (numPrimitives == 0) { bvh->clear(); return; }551552double t0 = bvh->preBuild(TOSTRING(isa) "::BVH" + toString(N) + "BuilderMBlurSAHGrid");553554//const size_t numTimeSteps = scene->getNumTimeSteps<GridMesh,true>();555//const size_t numTimeSegments = numTimeSteps-1; assert(numTimeSteps > 1);556//if (numTimeSegments == 1)557// buildSingleSegment(numPrimitives);558//else559buildMultiSegment(numPrimitives);560561/* clear temporary data for static geometry */562bvh->cleanup();563bvh->postBuild(t0);564}565566#if 0567void buildSingleSegment(size_t numPrimitives)568{569/* create primref array */570mvector<PrimRef> prims(scene->device,numPrimitives);571const PrimInfo pinfo = createPrimRefArrayMBlurGrid(scene,prims,bvh->scene->progressInterface,0);572/* early out if no valid primitives */573if (pinfo.size() == 0) { bvh->clear(); return; }574575/* estimate acceleration structure size */576const size_t node_bytes = pinfo.size()*sizeof(AABBNodeMB)/(4*N);577//TODO: check leaf_bytes578const size_t leaf_bytes = size_t(1.2*(float)numPrimitives/N * sizeof(SubGridQBVHN<N>));579bvh->alloc.init_estimate(node_bytes+leaf_bytes);580581/* settings for BVH build */582GeneralBVHBuilder::Settings settings;583settings.branchingFactor = N;584settings.maxDepth = BVH::maxBuildDepthLeaf;585settings.logBlockSize = bsr(sahBlockSize);586settings.minLeafSize = min(minLeafSize,maxLeafSize);587settings.maxLeafSize = maxLeafSize;588settings.travCost = travCost;589settings.intCost = intCost;590settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes);591592/* build hierarchy */593auto root = BVHBuilderBinnedSAH::build<NodeRecordMB>594(typename BVH::CreateAlloc(bvh),595typename BVH::AABBNodeMB::Create(),596typename BVH::AABBNodeMB::Set(),597CreateLeafGridMB<N>(scene,bvh,sgrids.data()),598bvh->scene->progressInterface,599prims.data(),pinfo,settings);600601bvh->set(root.ref,root.lbounds,pinfo.size());602}603#endif604605void buildMultiSegment(size_t numPrimitives)606{607/* create primref array */608mvector<PrimRefMB> prims(scene->device,numPrimitives);609PrimInfoMB pinfo = createPrimRefArrayMSMBlurGrid(scene,prims,bvh->scene->progressInterface);610611/* early out if no valid primitives */612if (pinfo.size() == 0) { bvh->clear(); return; }613614615616GridRecalculatePrimRef recalculatePrimRef(scene,sgrids.data());617618/* estimate acceleration structure size */619const size_t node_bytes = pinfo.num_time_segments*sizeof(AABBNodeMB)/(4*N);620//FIXME: check leaf_bytes621//const size_t leaf_bytes = size_t(1.2*Primitive::blocks(pinfo.num_time_segments)*sizeof(SubGridQBVHN<N>));622const size_t leaf_bytes = size_t(1.2*(float)numPrimitives/N * sizeof(SubGridQBVHN<N>));623624bvh->alloc.init_estimate(node_bytes+leaf_bytes);625626/* settings for BVH build */627BVHBuilderMSMBlur::Settings settings;628settings.branchingFactor = N;629settings.maxDepth = BVH::maxDepth;630settings.logBlockSize = bsr(sahBlockSize);631settings.minLeafSize = min(minLeafSize,maxLeafSize);632settings.maxLeafSize = maxLeafSize;633settings.travCost = travCost;634settings.intCost = intCost;635settings.singleLeafTimeSegment = false;636settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes);637638/* build hierarchy */639auto root =640BVHBuilderMSMBlur::build<NodeRef>(prims,pinfo,scene->device,641recalculatePrimRef,642typename BVH::CreateAlloc(bvh),643typename BVH::AABBNodeMB4D::Create(),644typename BVH::AABBNodeMB4D::Set(),645CreateMSMBlurLeafGrid<N>(scene,bvh,sgrids.data()),646bvh->scene->progressInterface,647settings);648bvh->set(root.ref,root.lbounds,pinfo.num_time_segments);649}650651void clear() {652}653};654655/************************************************************************************/656/************************************************************************************/657/************************************************************************************/658/************************************************************************************/659660#if defined(EMBREE_GEOMETRY_TRIANGLE)661Builder* 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); }662Builder* 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); }663#if defined(__AVX__)664Builder* 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); }665Builder* 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); }666#endif667#endif668669#if defined(EMBREE_GEOMETRY_QUAD)670Builder* 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); }671#if defined(__AVX__)672Builder* 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); }673#endif674#endif675676#if defined(EMBREE_GEOMETRY_USER)677Builder* BVH4VirtualMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) {678int minLeafSize = scene->device->object_accel_mb_min_leaf_size;679int maxLeafSize = scene->device->object_accel_mb_max_leaf_size;680return new BVHNBuilderMBlurSAH<4,UserGeometry,Object>((BVH4*)bvh,scene,4,1.0f,minLeafSize,maxLeafSize,Geometry::MTY_USER_GEOMETRY);681}682#if defined(__AVX__)683Builder* BVH8VirtualMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) {684int minLeafSize = scene->device->object_accel_mb_min_leaf_size;685int maxLeafSize = scene->device->object_accel_mb_max_leaf_size;686return new BVHNBuilderMBlurSAH<8,UserGeometry,Object>((BVH8*)bvh,scene,8,1.0f,minLeafSize,maxLeafSize,Geometry::MTY_USER_GEOMETRY);687}688#endif689#endif690691#if defined(EMBREE_GEOMETRY_INSTANCE)692Builder* BVH4InstanceMBSceneBuilderSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype) { return new BVHNBuilderMBlurSAH<4,Instance,InstancePrimitive>((BVH4*)bvh,scene,4,1.0f,1,1,gtype); }693#if defined(__AVX__)694Builder* BVH8InstanceMBSceneBuilderSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype) { return new BVHNBuilderMBlurSAH<8,Instance,InstancePrimitive>((BVH8*)bvh,scene,8,1.0f,1,1,gtype); }695#endif696#endif697698#if defined(EMBREE_GEOMETRY_INSTANCE_ARRAY)699Builder* BVH4InstanceArrayMBSceneBuilderSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype) { return new BVHNBuilderMBlurSAH<4,InstanceArray,InstanceArrayPrimitive>((BVH4*)bvh,scene,4,1.0f,1,1,gtype); }700#if defined(__AVX__)701Builder* BVH8InstanceArrayMBSceneBuilderSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype) { return new BVHNBuilderMBlurSAH<8,InstanceArray,InstanceArrayPrimitive>((BVH8*)bvh,scene,8,1.0f,1,1,gtype); }702#endif703#endif704705#if defined(EMBREE_GEOMETRY_GRID)706Builder* BVH4GridMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAHGrid<4>((BVH4*)bvh,scene,4,1.0f,4,4); }707#if defined(__AVX__)708Builder* BVH8GridMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAHGrid<8>((BVH8*)bvh,scene,8,1.0f,8,8); }709#endif710#endif711}712}713714715