void BVHNStatistics<N>::statistics(NodeRef node, const float A, size_t& depth) { if (node.isNode()) { numAlignedNodes++; AlignedNode* n = node.node(); bvhSAH += A*travCostAligned; depth = 0; for (size_t i=0; i<N; i++) { if (n->child(i) == BVH::emptyNode) continue; childrenAlignedNodes++; const float Ai = max(0.0f,halfArea(n->extend(i))); size_t cdepth; statistics(n->child(i),Ai,cdepth); depth=max(depth,cdepth); } depth++; } else if (node.isUnalignedNode()) { numUnalignedNodes++; UnalignedNode* n = node.unalignedNode(); bvhSAH += A*travCostUnaligned; depth = 0; for (size_t i=0; i<N; i++) { if (n->child(i) == BVH::emptyNode) continue; childrenUnalignedNodes++; const float Ai = max(0.0f,halfArea(n->extend(i))); size_t cdepth; statistics(n->child(i),Ai,cdepth); depth=max(depth,cdepth); } depth++; } else if (node.isNodeMB()) { numAlignedNodesMB++; AlignedNodeMB* n = node.nodeMB(); bvhSAH += A*travCostAligned; depth = 0; for (size_t i=0; i<N; i++) { if (n->child(i) == BVH::emptyNode) continue; childrenAlignedNodesMB++; const float Ai = max(0.0f,halfArea(n->extend0(i))); size_t cdepth; statistics(n->child(i),Ai,cdepth); depth=max(depth,cdepth); } depth++; } else if (node.isUnalignedNodeMB()) { numUnalignedNodesMB++; UnalignedNodeMB* n = node.unalignedNodeMB(); bvhSAH += A*travCostUnaligned; depth = 0; for (size_t i=0; i<N; i++) { if (n->child(i) == BVH::emptyNode) continue; childrenUnalignedNodesMB++; const float Ai = max(0.0f,halfArea(n->extend0(i))); size_t cdepth; statistics(n->child(i),Ai,cdepth); depth=max(depth,cdepth); } depth++; } else if (node.isTransformNode()) { numTransformNodes++; TransformNode* n = node.transformNode(); bvhSAH += A*travCostTransform; depth = 0; const BBox3fa worldBounds = xfmBounds(n->local2world,n->localBounds); const float Ai = max(0.0f,halfArea(worldBounds)); //size_t cdepth; statistics(n->child,Ai,cdepth); //depth=max(depth,cdepth)+1; } else { depth = 0; size_t num; const char* tri = node.leaf(num); if (!num) return; numLeaves++; numPrimBlocks += num; for (size_t i=0; i<num; i++) numPrims += bvh->primTy.size(tri+i*bvh->primTy.bytes); float sah = A * intCost * num; leafSAH += sah; } }
typename BVHNStatistics<N>::Statistics BVHNStatistics<N>::statistics(NodeRef node, const double A, const BBox1f t0t1) { Statistics s; double dt = max(0.0f,t0t1.size()); if (node.isAlignedNode()) { AlignedNode* n = node.alignedNode(); for (size_t i=0; i<N; i++) { if (n->child(i) == BVH::emptyNode) continue; s.statAlignedNodes.numChildren++; const double Ai = max(0.0f,halfArea(n->extend(i))); s = s + statistics(n->child(i),Ai,t0t1); } s.statAlignedNodes.numNodes++; s.statAlignedNodes.nodeSAH += dt*A; s.depth++; } else if (node.isUnalignedNode()) { UnalignedNode* n = node.unalignedNode(); for (size_t i=0; i<N; i++) { if (n->child(i) == BVH::emptyNode) continue; s.statUnalignedNodes.numChildren++; const double Ai = max(0.0f,halfArea(n->extend(i))); s = s + statistics(n->child(i),Ai,t0t1); } s.statUnalignedNodes.numNodes++; s.statUnalignedNodes.nodeSAH += dt*A; s.depth++; } else if (node.isAlignedNodeMB()) { AlignedNodeMB* n = node.alignedNodeMB(); for (size_t i=0; i<N; i++) { if (n->child(i) == BVH::emptyNode) continue; s.statAlignedNodesMB.numChildren++; const double Ai = max(0.0f,halfArea(n->extend0(i))); s = s + statistics(n->child(i),Ai,t0t1); } s.statAlignedNodesMB.numNodes++; s.statAlignedNodesMB.nodeSAH += dt*A; s.depth++; } else if (node.isUnalignedNodeMB()) { UnalignedNodeMB* n = node.unalignedNodeMB(); for (size_t i=0; i<N; i++) { if (n->child(i) == BVH::emptyNode) continue; s.statUnalignedNodesMB.numChildren++; const double Ai = max(0.0f,halfArea(n->extend0(i))); s = s + statistics(n->child(i),Ai,t0t1); } s.statUnalignedNodesMB.numNodes++; s.statUnalignedNodesMB.nodeSAH += dt*A; s.depth++; } else if (node.isTransformNode()) { s.statTransformNodes.numNodes++; s.statTransformNodes.nodeSAH += dt*A; s.depth++; } else if (node.isQuantizedNode()) { QuantizedNode* n = node.quantizedNode(); for (size_t i=0; i<N; i++) { if (n->child(i) == BVH::emptyNode) continue; s.statQuantizedNodes.numChildren++; const double Ai = max(0.0f,halfArea(n->extend(i))); s = s + statistics(n->child(i),Ai,t0t1); } s.statQuantizedNodes.numNodes++; s.statQuantizedNodes.nodeSAH += dt*A; s.depth++; } else if (node.isLeaf()) { size_t num; const char* tri = node.leaf(num); if (num) { for (size_t i=0; i<num; i++) { s.statLeaf.numPrims += bvh->primTy.size(tri+i*bvh->primTy.bytes); } s.statLeaf.numLeaves++; s.statLeaf.numPrimBlocks += num; s.statLeaf.leafSAH += dt*A*num; if (num-1 < Statistics::LeafStat::NHIST) { s.statLeaf.numPrimBlocksHistogram[num-1]++; } } } else { throw std::runtime_error("not supported node type in bvh_statistics"); } return s; }
void build(size_t, size_t) { /* progress monitor */ auto progress = [&] (size_t dn) { bvh->scene->progressMonitor(dn); }; auto virtualprogress = BuildProgressMonitorFromClosure(progress); /* fast path for empty BVH */ const size_t numPrimitives = scene->getNumPrimitives<BezierCurves,2>(); if (numPrimitives == 0) { prims.clear(); bvh->set(BVH::emptyNode,empty,0); return; } double t0 = bvh->preBuild(TOSTRING(isa) "::BVH" + toString(N) + "BuilderMBHairSAH"); //profile(1,5,numPrimitives,[&] (ProfileTimer& timer) { /* create primref array */ bvh->alloc.init_estimate(numPrimitives*sizeof(Primitive)); prims.resize(numPrimitives); const PrimInfo pinfo = createBezierRefArray<2>(scene,prims,virtualprogress); NodeRef root = bvh_obb_builder_binned_sah<N> ( [&] () { return bvh->alloc.threadLocal2(); }, [&] (const PrimInfo* children, const size_t numChildren, HeuristicArrayBinningSAH<BezierPrim> alignedHeuristic, FastAllocator::ThreadLocal2* alloc) -> NodeMB* { NodeMB* node = (NodeMB*) alloc->alloc0.malloc(sizeof(NodeMB),16); node->clear(); for (size_t i=0; i<numChildren; i++) { std::pair<BBox3fa,BBox3fa> bounds = alignedHeuristic.computePrimInfoMB(scene,children[i]); node->set(i,bounds.first,bounds.second); } return node; }, [&] (const PrimInfo* children, const size_t numChildren, UnalignedHeuristicArrayBinningSAH<BezierPrim> unalignedHeuristic, FastAllocator::ThreadLocal2* alloc) -> UnalignedNodeMB* { UnalignedNodeMB* node = (UnalignedNodeMB*) alloc->alloc0.malloc(sizeof(UnalignedNodeMB),16); node->clear(); for (size_t i=0; i<numChildren; i++) { const AffineSpace3fa space = unalignedHeuristic.computeAlignedSpaceMB(scene,children[i]); UnalignedHeuristicArrayBinningSAH<BezierPrim>::PrimInfoMB pinfo = unalignedHeuristic.computePrimInfoMB(scene,children[i],space); node->set(i,space,pinfo.s0t0,pinfo.s1t1); } return node; }, [&] (size_t depth, const PrimInfo& pinfo, FastAllocator::ThreadLocal2* alloc) -> NodeRef { size_t items = pinfo.size(); size_t start = pinfo.begin; Primitive* accel = (Primitive*) alloc->alloc1.malloc(items*sizeof(Primitive)); NodeRef node = bvh->encodeLeaf((char*)accel,items); for (size_t i=0; i<items; i++) { accel[i].fill(prims.data(),start,pinfo.end,bvh->scene,false); } return node; }, progress, prims.data(),pinfo,N,BVH::maxBuildDepthLeaf,1,1,BVH::maxLeafBlocks); bvh->set(root,pinfo.geomBounds,pinfo.size()); //}); /* clear temporary data for static geometry */ if (scene->isStatic()) { prims.clear(); bvh->shrink(); } bvh->cleanup(); bvh->postBuild(t0); }