Path: blob/master/thirdparty/embree/kernels/builders/primrefgen.cpp
9906 views
// Copyright 2009-2021 Intel Corporation1// SPDX-License-Identifier: Apache-2.023#include "primrefgen.h"4#include "primrefgen_presplit.h"56#include "../../common/algorithms/parallel_for_for.h"7#include "../../common/algorithms/parallel_for_for_prefix_sum.h"89namespace embree10{11namespace isa12{13PrimInfo createPrimRefArray(Geometry* geometry, unsigned int geomID, const size_t numPrimRefs, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor)14{15ParallelPrefixSumState<PrimInfo> pstate;1617/* first try */18progressMonitor(0);19PrimInfo pinfo = parallel_prefix_sum( pstate, size_t(0), geometry->size(), size_t(1024), PrimInfo(empty), [&](const range<size_t>& r, const PrimInfo& base) -> PrimInfo {20return geometry->createPrimRefArray(prims,r,r.begin(),geomID);21}, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });2223/* if we need to filter out geometry, run again */24if (pinfo.size() != numPrimRefs)25{26progressMonitor(0);27pinfo = parallel_prefix_sum( pstate, size_t(0), geometry->size(), size_t(1024), PrimInfo(empty), [&](const range<size_t>& r, const PrimInfo& base) -> PrimInfo {28return geometry->createPrimRefArray(prims,r,base.size(),geomID);29}, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });30}31return pinfo;32}3334PrimInfo createPrimRefArray(Scene* scene, Geometry::GTypeMask types, bool mblur, const size_t numPrimRefs, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor)35{36ParallelForForPrefixSumState<PrimInfo> pstate;37Scene::Iterator2 iter(scene,types,mblur);3839/* first try */40progressMonitor(0);41pstate.init(iter,size_t(1024));42PrimInfo pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfo {43return mesh->createPrimRefArray(prims,r,k,(unsigned)geomID);44}, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });4546/* if we need to filter out geometry, run again */47if (pinfo.size() != numPrimRefs)48{49progressMonitor(0);50pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfo& base) -> PrimInfo {51return mesh->createPrimRefArray(prims,r,base.size(),(unsigned)geomID);52}, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });53}54return pinfo;55}5657PrimInfo createPrimRefArray(Scene* scene, Geometry::GTypeMask types, bool mblur, const size_t numPrimRefs, mvector<PrimRef>& prims, mvector<SubGridBuildData>& sgrids, BuildProgressMonitor& progressMonitor)58{59ParallelForForPrefixSumState<PrimInfo> pstate;60Scene::Iterator2 iter(scene,types,mblur);6162/* first try */63progressMonitor(0);64pstate.init(iter,size_t(1024));65PrimInfo pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfo {66return mesh->createPrimRefArray(prims,sgrids,r,k,(unsigned)geomID);67}, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });6869/* if we need to filter out geometry, run again */70if (pinfo.size() != numPrimRefs)71{72progressMonitor(0);73pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfo& base) -> PrimInfo {74return mesh->createPrimRefArray(prims,sgrids,r,base.size(),(unsigned)geomID);75}, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });76}77return pinfo;78}7980PrimInfo createPrimRefArrayMBlur(Scene* scene, Geometry::GTypeMask types, const size_t numPrimRefs, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor, size_t itime)81{82ParallelForForPrefixSumState<PrimInfo> pstate;83Scene::Iterator2 iter(scene,types,true);8485/* first try */86progressMonitor(0);87pstate.init(iter,size_t(1024));88PrimInfo pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfo {89return mesh->createPrimRefArrayMB(prims,itime,r,k,(unsigned)geomID);90}, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });9192/* if we need to filter out geometry, run again */93if (pinfo.size() != numPrimRefs)94{95progressMonitor(0);96pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfo& base) -> PrimInfo {97return mesh->createPrimRefArrayMB(prims,itime,r,base.size(),(unsigned)geomID);98}, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });99}100return pinfo;101}102103PrimInfoMB createPrimRefArrayMSMBlur(Scene* scene, Geometry::GTypeMask types, const size_t numPrimRefs, mvector<PrimRefMB>& prims, BuildProgressMonitor& progressMonitor, BBox1f t0t1)104{105ParallelForForPrefixSumState<PrimInfoMB> pstate;106Scene::Iterator2 iter(scene,types,true);107108/* first try */109progressMonitor(0);110pstate.init(iter,size_t(1024));111PrimInfoMB pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfoMB(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfoMB {112return mesh->createPrimRefMBArray(prims,t0t1,r,k,(unsigned)geomID);113}, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });114115/* if we need to filter out geometry, run again */116if (pinfo.size() != numPrimRefs)117{118progressMonitor(0);119pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfoMB(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfoMB& base) -> PrimInfoMB {120return mesh->createPrimRefMBArray(prims,t0t1,r,base.size(),(unsigned)geomID);121}, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });122}123124/* the BVH starts with that time range, even though primitives might have smaller/larger time range */125pinfo.time_range = t0t1;126return pinfo;127}128129PrimInfoMB createPrimRefArrayMSMBlur(Scene* scene, Geometry::GTypeMask types, const size_t numPrimRefs, mvector<PrimRefMB>& prims, mvector<SubGridBuildData>& sgrids, BuildProgressMonitor& progressMonitor, BBox1f t0t1)130{131ParallelForForPrefixSumState<PrimInfoMB> pstate;132Scene::Iterator2 iter(scene,types,true);133134/* first try */135progressMonitor(0);136pstate.init(iter,size_t(1024));137PrimInfoMB pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfoMB(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfoMB {138return mesh->createPrimRefMBArray(prims,sgrids,t0t1,r,k,(unsigned)geomID);139}, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });140141/* if we need to filter out geometry, run again */142if (pinfo.size() != numPrimRefs)143{144progressMonitor(0);145pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfoMB(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfoMB& base) -> PrimInfoMB {146return mesh->createPrimRefMBArray(prims,sgrids,t0t1,r,base.size(),(unsigned)geomID);147}, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });148}149150/* the BVH starts with that time range, even though primitives might have smaller/larger time range */151pinfo.time_range = t0t1;152return pinfo;153}154155template<typename Mesh>156size_t createMortonCodeArray(Mesh* mesh, mvector<BVHBuilderMorton::BuildPrim>& morton, BuildProgressMonitor& progressMonitor)157{158size_t numPrimitives = morton.size();159160/* compute scene bounds */161std::pair<size_t,BBox3fa> cb_empty(0,empty);162auto cb = parallel_reduce163( size_t(0), numPrimitives, size_t(1024), cb_empty, [&](const range<size_t>& r) -> std::pair<size_t,BBox3fa>164{165size_t num = 0;166BBox3fa bounds = empty;167168for (size_t j=r.begin(); j<r.end(); j++)169{170BBox3fa prim_bounds = empty;171if (unlikely(!mesh->buildBounds(j,&prim_bounds))) continue;172bounds.extend(center2(prim_bounds));173num++;174}175return std::make_pair(num,bounds);176}, [] (const std::pair<size_t,BBox3fa>& a, const std::pair<size_t,BBox3fa>& b) {177return std::make_pair(a.first + b.first,merge(a.second,b.second));178});179180181size_t numPrimitivesGen = cb.first;182const BBox3fa centBounds = cb.second;183184/* compute morton codes */185if (likely(numPrimitivesGen == numPrimitives))186{187/* fast path if all primitives were valid */188BVHBuilderMorton::MortonCodeMapping mapping(centBounds);189parallel_for( size_t(0), numPrimitives, size_t(1024), [&](const range<size_t>& r) -> void {190BVHBuilderMorton::MortonCodeGenerator generator(mapping,&morton.data()[r.begin()]);191for (size_t j=r.begin(); j<r.end(); j++)192generator(mesh->bounds(j),unsigned(j));193});194}195else196{197/* slow path, fallback in case some primitives were invalid */198ParallelPrefixSumState<size_t> pstate;199BVHBuilderMorton::MortonCodeMapping mapping(centBounds);200parallel_prefix_sum( pstate, size_t(0), numPrimitives, size_t(1024), size_t(0), [&](const range<size_t>& r, const size_t base) -> size_t {201size_t num = 0;202BVHBuilderMorton::MortonCodeGenerator generator(mapping,&morton.data()[r.begin()]);203for (size_t j=r.begin(); j<r.end(); j++)204{205BBox3fa bounds = empty;206if (unlikely(!mesh->buildBounds(j,&bounds))) continue;207generator(bounds,unsigned(j));208num++;209}210return num;211}, std::plus<size_t>());212213parallel_prefix_sum( pstate, size_t(0), numPrimitives, size_t(1024), size_t(0), [&](const range<size_t>& r, const size_t base) -> size_t {214size_t num = 0;215BVHBuilderMorton::MortonCodeGenerator generator(mapping,&morton.data()[base]);216for (size_t j=r.begin(); j<r.end(); j++)217{218BBox3fa bounds = empty;219if (!mesh->buildBounds(j,&bounds)) continue;220generator(bounds,unsigned(j));221num++;222}223return num;224}, std::plus<size_t>());225}226return numPrimitivesGen;227}228229// ====================================================================================================230// ====================================================================================================231// ====================================================================================================232233// special variants for grid meshes234235#if defined(EMBREE_GEOMETRY_GRID)236PrimInfo createPrimRefArrayGrids(Scene* scene, mvector<PrimRef>& prims, mvector<SubGridBuildData>& sgrids)237{238PrimInfo pinfo(empty);239size_t numPrimitives = 0;240241/* first run to get #primitives */242243ParallelForForPrefixSumState<PrimInfo> pstate;244Scene::Iterator<GridMesh,false> iter(scene);245246pstate.init(iter,size_t(1024));247248/* iterate over all meshes in the scene */249pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfo {250PrimInfo pinfo(empty);251for (size_t j=r.begin(); j<r.end(); j++)252{253if (!mesh->valid(j)) continue;254BBox3fa bounds = empty;255const PrimRef prim(bounds,(unsigned)geomID,(unsigned)j);256if (!mesh->valid(j)) continue;257pinfo.add_center2(prim,mesh->getNumSubGrids(j));258}259return pinfo;260}, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });261numPrimitives = pinfo.size();262263/* resize arrays */264sgrids.resize(numPrimitives);265prims.resize(numPrimitives);266267/* second run to fill primrefs and SubGridBuildData arrays */268pinfo = 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 {269return mesh->createPrimRefArray(prims,sgrids,r,base.size(),geomID);270}, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });271assert(pinfo.size() == numPrimitives);272return pinfo;273}274275PrimInfo createPrimRefArrayGrids(GridMesh* mesh, mvector<PrimRef>& prims, mvector<SubGridBuildData>& sgrids)276{277unsigned int geomID_ = std::numeric_limits<unsigned int>::max ();278279PrimInfo pinfo(empty);280size_t numPrimitives = 0;281282ParallelPrefixSumState<PrimInfo> pstate;283/* iterate over all grids in a single mesh */284pinfo = parallel_prefix_sum( pstate, size_t(0), mesh->size(), size_t(1024), PrimInfo(empty), [&](const range<size_t>& r, const PrimInfo& base) -> PrimInfo285{286PrimInfo pinfo(empty);287for (size_t j=r.begin(); j<r.end(); j++)288{289if (!mesh->valid(j)) continue;290BBox3fa bounds = empty;291const PrimRef prim(bounds,geomID_,unsigned(j));292pinfo.add_center2(prim,mesh->getNumSubGrids(j));293}294return pinfo;295}, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });296numPrimitives = pinfo.size();297/* resize arrays */298sgrids.resize(numPrimitives);299prims.resize(numPrimitives);300301/* second run to fill primrefs and SubGridBuildData arrays */302pinfo = parallel_prefix_sum( pstate, size_t(0), mesh->size(), size_t(1024), PrimInfo(empty), [&](const range<size_t>& r, const PrimInfo& base) -> PrimInfo {303return mesh->createPrimRefArray(prims,sgrids,r,base.size(),geomID_);304}, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });305306return pinfo;307}308309PrimInfoMB createPrimRefArrayMSMBlurGrid(Scene* scene, mvector<PrimRefMB>& prims, mvector<SubGridBuildData>& sgrids, BuildProgressMonitor& progressMonitor, BBox1f t0t1)310{311/* first run to get #primitives */312ParallelForForPrefixSumState<PrimInfoMB> pstate;313Scene::Iterator<GridMesh,true> iter(scene);314315pstate.init(iter,size_t(1024));316/* iterate over all meshes in the scene */317PrimInfoMB pinfoMB = parallel_for_for_prefix_sum0( pstate, iter, PrimInfoMB(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t /*geomID*/) -> PrimInfoMB {318319PrimInfoMB pinfoMB(empty);320for (size_t j=r.begin(); j<r.end(); j++)321{322if (!mesh->valid(j, mesh->timeSegmentRange(t0t1))) continue;323LBBox3fa bounds(empty);324PrimInfoMB gridMB(0,mesh->getNumSubGrids(j));325pinfoMB.merge(gridMB);326}327return pinfoMB;328}, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });329330size_t numPrimitives = pinfoMB.size();331if (numPrimitives == 0) return pinfoMB;332333/* resize arrays */334sgrids.resize(numPrimitives);335prims.resize(numPrimitives);336/* second run to fill primrefs and SubGridBuildData arrays */337pinfoMB = 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 {338return mesh->createPrimRefMBArray(prims,sgrids,t0t1,r,base.size(),(unsigned)geomID);339}, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });340341assert(pinfoMB.size() == numPrimitives);342pinfoMB.time_range = t0t1;343return pinfoMB;344}345346#endif347348// ====================================================================================================349// ====================================================================================================350// ====================================================================================================351352IF_ENABLED_TRIS (template size_t createMortonCodeArray<TriangleMesh>(TriangleMesh* mesh COMMA mvector<BVHBuilderMorton::BuildPrim>& morton COMMA BuildProgressMonitor& progressMonitor));353IF_ENABLED_QUADS(template size_t createMortonCodeArray<QuadMesh>(QuadMesh* mesh COMMA mvector<BVHBuilderMorton::BuildPrim>& morton COMMA BuildProgressMonitor& progressMonitor));354IF_ENABLED_USER (template size_t createMortonCodeArray<UserGeometry>(UserGeometry* mesh COMMA mvector<BVHBuilderMorton::BuildPrim>& morton COMMA BuildProgressMonitor& progressMonitor));355IF_ENABLED_INSTANCE (template size_t createMortonCodeArray<Instance>(Instance* mesh COMMA mvector<BVHBuilderMorton::BuildPrim>& morton COMMA BuildProgressMonitor& progressMonitor));356IF_ENABLED_INSTANCE_ARRAY (template size_t createMortonCodeArray<InstanceArray>(InstanceArray* mesh COMMA mvector<BVHBuilderMorton::BuildPrim>& morton COMMA BuildProgressMonitor& progressMonitor));357}358}359360361