Path: blob/master/thirdparty/embree/kernels/bvh/bvh.cpp
9906 views
// Copyright 2009-2021 Intel Corporation1// SPDX-License-Identifier: Apache-2.023#include "bvh.h"4#include "bvh_statistics.h"56namespace embree7{8template<int N>9BVHN<N>::BVHN (const PrimitiveType& primTy, Scene* scene)10: AccelData((N==4) ? AccelData::TY_BVH4 : (N==8) ? AccelData::TY_BVH8 : AccelData::TY_UNKNOWN),11primTy(&primTy), device(scene->device), scene(scene),12root(emptyNode), alloc(scene->device,scene->isStaticAccel()), numPrimitives(0), numVertices(0)13{14}1516template<int N>17BVHN<N>::~BVHN ()18{19for (size_t i=0; i<objects.size(); i++)20delete objects[i];21}2223template<int N>24void BVHN<N>::clear()25{26set(BVHN::emptyNode,empty,0);27alloc.clear();28}2930template<int N>31void BVHN<N>::set (NodeRef root, const LBBox3fa& bounds, size_t numPrimitives)32{33this->root = root;34this->bounds = bounds;35this->numPrimitives = numPrimitives;36}3738template<int N>39void BVHN<N>::clearBarrier(NodeRef& node)40{41if (node.isBarrier())42node.clearBarrier();43else if (!node.isLeaf()) {44BaseNode* n = node.baseNode(); // FIXME: flags should be stored in BVH45for (size_t c=0; c<N; c++)46clearBarrier(n->child(c));47}48}4950template<int N>51void BVHN<N>::layoutLargeNodes(size_t num)52{53#if defined(__64BIT__) // do not use tree rotations on 32 bit platforms, barrier bit in NodeRef will cause issues54struct NodeArea55{56__forceinline NodeArea() {}5758__forceinline NodeArea(NodeRef& node, const BBox3fa& bounds)59: node(&node), A(node.isLeaf() ? float(neg_inf) : area(bounds)) {}6061__forceinline bool operator< (const NodeArea& other) const {62return this->A < other.A;63}6465NodeRef* node;66float A;67};68std::vector<NodeArea> lst;69lst.reserve(num);70lst.push_back(NodeArea(root,empty));7172while (lst.size() < num)73{74std::pop_heap(lst.begin(), lst.end());75NodeArea n = lst.back(); lst.pop_back();76if (!n.node->isAABBNode()) break;77AABBNode* node = n.node->getAABBNode();78for (size_t i=0; i<N; i++) {79if (node->child(i) == BVHN::emptyNode) continue;80lst.push_back(NodeArea(node->child(i),node->bounds(i)));81std::push_heap(lst.begin(), lst.end());82}83}8485for (size_t i=0; i<lst.size(); i++)86lst[i].node->setBarrier();8788root = layoutLargeNodesRecursion(root,alloc.getCachedAllocator());89#endif90}9192template<int N>93typename BVHN<N>::NodeRef BVHN<N>::layoutLargeNodesRecursion(NodeRef& node, const FastAllocator::CachedAllocator& allocator)94{95if (node.isBarrier()) {96node.clearBarrier();97return node;98}99else if (node.isAABBNode())100{101AABBNode* oldnode = node.getAABBNode();102AABBNode* newnode = (BVHN::AABBNode*) allocator.malloc0(sizeof(BVHN::AABBNode),byteNodeAlignment);103*newnode = *oldnode;104for (size_t c=0; c<N; c++)105newnode->child(c) = layoutLargeNodesRecursion(oldnode->child(c),allocator);106return encodeNode(newnode);107}108else return node;109}110111template<int N>112double BVHN<N>::preBuild(const std::string& builderName)113{114if (builderName == "")115return inf;116117if (device->verbosity(2))118{119Lock<MutexSys> lock(g_printMutex);120std::cout << "building BVH" << N << (builderName.find("MBlur") != std::string::npos ? "MB" : "") << "<" << primTy->name() << "> using " << builderName << " ..." << std::endl << std::flush;121}122123double t0 = 0.0;124if (device->benchmark || device->verbosity(2)) t0 = getSeconds();125return t0;126}127128template<int N>129void BVHN<N>::postBuild(double t0)130{131if (t0 == double(inf))132return;133134double dt = 0.0;135if (device->benchmark || device->verbosity(2))136dt = getSeconds()-t0;137138std::unique_ptr<BVHNStatistics<N>> stat;139140/* print statistics */141if (device->verbosity(2))142{143if (!stat) stat.reset(new BVHNStatistics<N>(this));144const size_t usedBytes = alloc.getUsedBytes();145Lock<MutexSys> lock(g_printMutex);146std::cout << "finished BVH" << N << "<" << primTy->name() << "> : " << 1000.0f*dt << "ms, " << 1E-6*double(numPrimitives)/dt << " Mprim/s, " << 1E-9*double(usedBytes)/dt << " GB/s" << std::endl;147148if (device->verbosity(2))149std::cout << stat->str();150151if (device->verbosity(2))152{153FastAllocator::AllStatistics stat(&alloc);154for (size_t i=0; i<objects.size(); i++)155if (objects[i])156stat = stat + FastAllocator::AllStatistics(&objects[i]->alloc);157158stat.print(numPrimitives);159}160161if (device->verbosity(3))162{163alloc.print_blocks();164for (size_t i=0; i<objects.size(); i++)165if (objects[i])166objects[i]->alloc.print_blocks();167}168169std::cout << std::flush;170}171172/* benchmark mode */173if (device->benchmark)174{175if (!stat) stat.reset(new BVHNStatistics<N>(this));176Lock<MutexSys> lock(g_printMutex);177std::cout << "BENCHMARK_BUILD " << dt << " " << double(numPrimitives)/dt << " " << stat->sah() << " " << stat->bytesUsed() << " BVH" << N << "<" << primTy->name() << ">" << std::endl << std::flush;178}179}180181#if defined(__AVX__)182template class BVHN<8>;183#endif184185#if !defined(__AVX__) || !defined(EMBREE_TARGET_SSE2) && !defined(EMBREE_TARGET_SSE42) || defined(__aarch64__)186template class BVHN<4>;187#endif188}189190191192