123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- // Copyright 2009-2021 Intel Corporation
- // SPDX-License-Identifier: Apache-2.0
- #include "primrefgen.h"
- #include "primrefgen_presplit.h"
- #include "../../common/algorithms/parallel_for_for.h"
- #include "../../common/algorithms/parallel_for_for_prefix_sum.h"
- namespace embree
- {
- namespace isa
- {
- PrimInfo createPrimRefArray(Geometry* geometry, unsigned int geomID, const size_t numPrimRefs, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor)
- {
- ParallelPrefixSumState<PrimInfo> pstate;
-
- /* first try */
- progressMonitor(0);
- PrimInfo pinfo = parallel_prefix_sum( pstate, size_t(0), geometry->size(), size_t(1024), PrimInfo(empty), [&](const range<size_t>& r, const PrimInfo& base) -> PrimInfo {
- return geometry->createPrimRefArray(prims,r,r.begin(),geomID);
- }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
- /* if we need to filter out geometry, run again */
- if (pinfo.size() != numPrimRefs)
- {
- progressMonitor(0);
- pinfo = parallel_prefix_sum( pstate, size_t(0), geometry->size(), size_t(1024), PrimInfo(empty), [&](const range<size_t>& r, const PrimInfo& base) -> PrimInfo {
- return geometry->createPrimRefArray(prims,r,base.size(),geomID);
- }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
- }
- return pinfo;
- }
- PrimInfo createPrimRefArray(Scene* scene, Geometry::GTypeMask types, bool mblur, const size_t numPrimRefs, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor)
- {
- ParallelForForPrefixSumState<PrimInfo> pstate;
- Scene::Iterator2 iter(scene,types,mblur);
-
- /* first try */
- progressMonitor(0);
- pstate.init(iter,size_t(1024));
- PrimInfo pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfo {
- return mesh->createPrimRefArray(prims,r,k,(unsigned)geomID);
- }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
-
- /* if we need to filter out geometry, run again */
- if (pinfo.size() != numPrimRefs)
- {
- progressMonitor(0);
- pinfo = 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 {
- return mesh->createPrimRefArray(prims,r,base.size(),(unsigned)geomID);
- }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
- }
- return pinfo;
- }
- PrimInfo createPrimRefArrayMBlur(Scene* scene, Geometry::GTypeMask types, const size_t numPrimRefs, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor, size_t itime)
- {
- ParallelForForPrefixSumState<PrimInfo> pstate;
- Scene::Iterator2 iter(scene,types,true);
-
- /* first try */
- progressMonitor(0);
- pstate.init(iter,size_t(1024));
- PrimInfo pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfo {
- return mesh->createPrimRefArrayMB(prims,itime,r,k,(unsigned)geomID);
- }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
-
- /* if we need to filter out geometry, run again */
- if (pinfo.size() != numPrimRefs)
- {
- progressMonitor(0);
- pinfo = 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 {
- return mesh->createPrimRefArrayMB(prims,itime,r,base.size(),(unsigned)geomID);
- }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
- }
- return pinfo;
- }
- PrimInfoMB createPrimRefArrayMSMBlur(Scene* scene, Geometry::GTypeMask types, const size_t numPrimRefs, mvector<PrimRefMB>& prims, BuildProgressMonitor& progressMonitor, BBox1f t0t1)
- {
- ParallelForForPrefixSumState<PrimInfoMB> pstate;
- Scene::Iterator2 iter(scene,types,true);
-
- /* first try */
- progressMonitor(0);
- pstate.init(iter,size_t(1024));
- PrimInfoMB pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfoMB(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfoMB {
- return mesh->createPrimRefMBArray(prims,t0t1,r,k,(unsigned)geomID);
- }, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });
-
- /* if we need to filter out geometry, run again */
- if (pinfo.size() != numPrimRefs)
- {
- progressMonitor(0);
- pinfo = 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 {
- return mesh->createPrimRefMBArray(prims,t0t1,r,base.size(),(unsigned)geomID);
- }, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });
- }
- /* the BVH starts with that time range, even though primitives might have smaller/larger time range */
- pinfo.time_range = t0t1;
- return pinfo;
- }
- template<typename Mesh>
- size_t createMortonCodeArray(Mesh* mesh, mvector<BVHBuilderMorton::BuildPrim>& morton, BuildProgressMonitor& progressMonitor)
- {
- size_t numPrimitives = morton.size();
- /* compute scene bounds */
- std::pair<size_t,BBox3fa> cb_empty(0,empty);
- auto cb = parallel_reduce
- ( size_t(0), numPrimitives, size_t(1024), cb_empty, [&](const range<size_t>& r) -> std::pair<size_t,BBox3fa>
- {
- size_t num = 0;
- BBox3fa bounds = empty;
-
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- BBox3fa prim_bounds = empty;
- if (unlikely(!mesh->buildBounds(j,&prim_bounds))) continue;
- bounds.extend(center2(prim_bounds));
- num++;
- }
- return std::make_pair(num,bounds);
- }, [] (const std::pair<size_t,BBox3fa>& a, const std::pair<size_t,BBox3fa>& b) {
- return std::make_pair(a.first + b.first,merge(a.second,b.second));
- });
-
-
- size_t numPrimitivesGen = cb.first;
- const BBox3fa centBounds = cb.second;
-
- /* compute morton codes */
- if (likely(numPrimitivesGen == numPrimitives))
- {
- /* fast path if all primitives were valid */
- BVHBuilderMorton::MortonCodeMapping mapping(centBounds);
- parallel_for( size_t(0), numPrimitives, size_t(1024), [&](const range<size_t>& r) -> void {
- BVHBuilderMorton::MortonCodeGenerator generator(mapping,&morton.data()[r.begin()]);
- for (size_t j=r.begin(); j<r.end(); j++)
- generator(mesh->bounds(j),unsigned(j));
- });
- }
- else
- {
- /* slow path, fallback in case some primitives were invalid */
- ParallelPrefixSumState<size_t> pstate;
- BVHBuilderMorton::MortonCodeMapping mapping(centBounds);
- parallel_prefix_sum( pstate, size_t(0), numPrimitives, size_t(1024), size_t(0), [&](const range<size_t>& r, const size_t base) -> size_t {
- size_t num = 0;
- BVHBuilderMorton::MortonCodeGenerator generator(mapping,&morton.data()[r.begin()]);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- BBox3fa bounds = empty;
- if (unlikely(!mesh->buildBounds(j,&bounds))) continue;
- generator(bounds,unsigned(j));
- num++;
- }
- return num;
- }, std::plus<size_t>());
-
- parallel_prefix_sum( pstate, size_t(0), numPrimitives, size_t(1024), size_t(0), [&](const range<size_t>& r, const size_t base) -> size_t {
- size_t num = 0;
- BVHBuilderMorton::MortonCodeGenerator generator(mapping,&morton.data()[base]);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- BBox3fa bounds = empty;
- if (!mesh->buildBounds(j,&bounds)) continue;
- generator(bounds,unsigned(j));
- num++;
- }
- return num;
- }, std::plus<size_t>());
- }
- return numPrimitivesGen;
- }
- // ====================================================================================================
- // ====================================================================================================
- // ====================================================================================================
- // special variants for grid meshes
- #if defined(EMBREE_GEOMETRY_GRID)
- PrimInfo createPrimRefArrayGrids(Scene* scene, mvector<PrimRef>& prims, mvector<SubGridBuildData>& sgrids)
- {
- PrimInfo pinfo(empty);
- size_t numPrimitives = 0;
-
- /* first run to get #primitives */
- ParallelForForPrefixSumState<PrimInfo> pstate;
- Scene::Iterator<GridMesh,false> iter(scene);
- pstate.init(iter,size_t(1024));
- /* iterate over all meshes in the scene */
- pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfo {
- PrimInfo pinfo(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- if (!mesh->valid(j)) continue;
- BBox3fa bounds = empty;
- const PrimRef prim(bounds,(unsigned)geomID,(unsigned)j);
- if (!mesh->valid(j)) continue;
- pinfo.add_center2(prim,mesh->getNumSubGrids(j));
- }
- return pinfo;
- }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
- numPrimitives = pinfo.size();
-
- /* 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<size_t>& 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(); j<r.end(); j++)
- {
- if (!mesh->valid(j)) continue;
- const GridMesh::Grid &g = mesh->grid(j);
- for (unsigned int y=0; y<g.resY-1u; y+=2)
- for (unsigned int x=0; x<g.resX-1u; x+=2)
- {
- BBox3fa bounds = empty;
- if (!mesh->buildBounds(g,x,y,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;
- }
- PrimInfo createPrimRefArrayGrids(GridMesh* mesh, mvector<PrimRef>& prims, mvector<SubGridBuildData>& sgrids)
- {
- unsigned int geomID_ = std::numeric_limits<unsigned int>::max ();
- PrimInfo pinfo(empty);
- size_t numPrimitives = 0;
-
- ParallelPrefixSumState<PrimInfo> pstate;
- /* iterate over all grids in a single mesh */
- pinfo = parallel_prefix_sum( pstate, size_t(0), mesh->size(), size_t(1024), PrimInfo(empty), [&](const range<size_t>& r, const PrimInfo& base) -> PrimInfo
- {
- PrimInfo pinfo(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- if (!mesh->valid(j)) continue;
- BBox3fa bounds = empty;
- const PrimRef prim(bounds,geomID_,unsigned(j));
- pinfo.add_center2(prim,mesh->getNumSubGrids(j));
- }
- return pinfo;
- }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
- numPrimitives = pinfo.size();
- /* resize arrays */
- sgrids.resize(numPrimitives);
- prims.resize(numPrimitives);
- /* second run to fill primrefs and SubGridBuildData arrays */
- pinfo = parallel_prefix_sum( pstate, size_t(0), mesh->size(), size_t(1024), PrimInfo(empty), [&](const range<size_t>& r, const PrimInfo& base) -> PrimInfo
- {
- size_t p_index = base.size();
- PrimInfo pinfo(empty);
- for (size_t j=r.begin(); j<r.end(); j++)
- {
- if (!mesh->valid(j)) continue;
- const GridMesh::Grid &g = mesh->grid(j);
- for (unsigned int y=0; y<g.resY-1u; y+=2)
- for (unsigned int x=0; x<g.resX-1u; x+=2)
- {
- BBox3fa bounds = empty;
- if (!mesh->buildBounds(g,x,y,bounds)) continue; // get bounds of subgrid
- const PrimRef prim(bounds,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); });
- return pinfo;
- }
- #endif
-
- // ====================================================================================================
- // ====================================================================================================
- // ====================================================================================================
- IF_ENABLED_TRIS (template size_t createMortonCodeArray<TriangleMesh>(TriangleMesh* mesh COMMA mvector<BVHBuilderMorton::BuildPrim>& morton COMMA BuildProgressMonitor& progressMonitor));
- IF_ENABLED_QUADS(template size_t createMortonCodeArray<QuadMesh>(QuadMesh* mesh COMMA mvector<BVHBuilderMorton::BuildPrim>& morton COMMA BuildProgressMonitor& progressMonitor));
- IF_ENABLED_USER (template size_t createMortonCodeArray<UserGeometry>(UserGeometry* mesh COMMA mvector<BVHBuilderMorton::BuildPrim>& morton COMMA BuildProgressMonitor& progressMonitor));
- IF_ENABLED_INSTANCE (template size_t createMortonCodeArray<Instance>(Instance* mesh COMMA mvector<BVHBuilderMorton::BuildPrim>& morton COMMA BuildProgressMonitor& progressMonitor));
- }
- }
|