typename BVHN<N>::NodeRef BVHN<N>::layoutLargeNodesRecursion(NodeRef& node, FastAllocator::ThreadLocal& allocator) { if (node.isBarrier()) { node.clearBarrier(); return node; } else if (node.isAlignedNode()) { AlignedNode* oldnode = node.alignedNode(); AlignedNode* newnode = (BVHN::AlignedNode*) allocator.malloc(sizeof(BVHN::AlignedNode),byteNodeAlignment); *newnode = *oldnode; for (size_t c=0; c<N; c++) newnode->child(c) = layoutLargeNodesRecursion(oldnode->child(c),allocator); return encodeNode(newnode); } else return node; }
BBox3fa BVHNRefitter<N>::refit_toplevel(NodeRef& ref, size_t &subtrees, const BBox3fa *const subTreeBounds, const size_t depth) { if (depth >= MAX_SUB_TREE_EXTRACTION_DEPTH) { assert(subtrees < MAX_NUM_SUB_TREES); assert(subTrees[subtrees] == ref); return subTreeBounds[subtrees++]; } if (ref.isAlignedNode()) { AlignedNode* node = ref.alignedNode(); BBox3fa bounds[N]; for (size_t i=0; i<N; i++) { NodeRef& child = node->child(i); if (unlikely(child == BVH::emptyNode)) bounds[i] = BBox3fa(empty); else bounds[i] = refit_toplevel(child,subtrees,subTreeBounds,depth+1); } BBox3vf<N> boundsT = transpose<N>(bounds); /* set new bounds */ node->lower_x = boundsT.lower.x; node->lower_y = boundsT.lower.y; node->lower_z = boundsT.lower.z; node->upper_x = boundsT.upper.x; node->upper_y = boundsT.upper.y; node->upper_z = boundsT.upper.z; return merge<N>(bounds); } else return leafBounds.leafBounds(ref); }
void BVHNRefitter<N>::gather_subtree_refs(NodeRef& ref, size_t &subtrees, const size_t depth) { if (depth >= MAX_SUB_TREE_EXTRACTION_DEPTH) { assert(subtrees < MAX_NUM_SUB_TREES); subTrees[subtrees++] = ref; return; } if (ref.isAlignedNode()) { AlignedNode* node = ref.alignedNode(); for (size_t i=0; i<N; i++) { NodeRef& child = node->child(i); if (unlikely(child == BVH::emptyNode)) continue; gather_subtree_refs(child,subtrees,depth+1); } } }
void BVHN<N>::layoutLargeNodes(size_t num) { struct NodeArea { __forceinline NodeArea() {} __forceinline NodeArea(NodeRef& node, const BBox3fa& bounds) : node(&node), A(node.isLeaf() ? float(neg_inf) : area(bounds)) {} __forceinline bool operator< (const NodeArea& other) const { return this->A < other.A; } NodeRef* node; float A; }; std::vector<NodeArea> lst; lst.reserve(num); lst.push_back(NodeArea(root,empty)); while (lst.size() < num) { std::pop_heap(lst.begin(), lst.end()); NodeArea n = lst.back(); lst.pop_back(); if (!n.node->isAlignedNode()) break; AlignedNode* node = n.node->alignedNode(); for (size_t i=0; i<N; i++) { if (node->child(i) == BVHN::emptyNode) continue; lst.push_back(NodeArea(node->child(i),node->bounds(i))); std::push_heap(lst.begin(), lst.end()); } } for (size_t i=0; i<lst.size(); i++) lst[i].node->setBarrier(); root = layoutLargeNodesRecursion(root,*alloc.threadLocal2()->alloc0); }
BBox3fa BVHNRefitter<N>::recurse_bottom(NodeRef& ref) { /* this is a leaf node */ if (unlikely(ref.isLeaf())) return leafBounds.leafBounds(ref); /* recurse if this is an internal node */ AlignedNode* node = ref.alignedNode(); /* enable exclusive prefetch for >= AVX platforms */ #if defined(__AVX__) ref.prefetchW(); #endif BBox3fa bounds[N]; for (size_t i=0; i<N; i++) if (unlikely(node->child(i) == BVH::emptyNode)) { bounds[i] = BBox3fa(empty); } else bounds[i] = recurse_bottom(node->child(i)); /* AOS to SOA transform */ BBox3vf<N> boundsT = transpose<N>(bounds); /* set new bounds */ node->lower_x = boundsT.lower.x; node->lower_y = boundsT.lower.y; node->lower_z = boundsT.lower.z; node->upper_x = boundsT.upper.x; node->upper_y = boundsT.upper.y; node->upper_z = boundsT.upper.z; return merge<N>(bounds); }
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 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; } }
void BVH4Statistics::statistics(NodeRef node, const float A, size_t& depth) { if (node.isNode()) { hash += 0x1234; numAlignedNodes++; AlignedNode* n = node.node(); bvhSAH += A*BVH4::travCostAligned; depth = 0; for (size_t i=0; i<BVH4::N; i++) { if (n->child(i) == BVH4::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++; hash += 0x76767*depth; } else if (node.isUnalignedNode()) { hash += 0x1232344; numUnalignedNodes++; UnalignedNode* n = node.unalignedNode(); bvhSAH += A*BVH4::travCostUnaligned; depth = 0; for (size_t i=0; i<BVH4::N; i++) { if (n->child(i) == BVH4::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++; hash += 0x76767*depth; } else if (node.isNodeMB()) { hash += 0xEF343; numAlignedNodesMB++; BVH4::NodeMB* n = node.nodeMB(); bvhSAH += A*BVH4::travCostAligned; depth = 0; for (size_t i=0; i<BVH4::N; i++) { if (n->child(i) == BVH4::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++; hash += 0x76767*depth; } else if (node.isUnalignedNodeMB()) { hash += 0x1EEF4; numUnalignedNodesMB++; BVH4::UnalignedNodeMB* n = node.unalignedNodeMB(); bvhSAH += A*BVH4::travCostUnaligned; depth = 0; for (size_t i=0; i<BVH4::N; i++) { if (n->child(i) == BVH4::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++; hash += 0x76767*depth; } else { depth = 0; size_t num; const char* tri = node.leaf(num); hash += 0xDD776*num+0x878; if (!num) return; hash += bvh->primTy.hash(tri,num); numLeaves++; numPrims += num; float sah = A * BVH4::intCost * num; bvhSAH += sah; } }