From d36827be4eb3c76693c27e04abe1aacd577d502d Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Mon, 11 Oct 2010 10:09:39 +0200 Subject: [PATCH] do a better job at keeping track of node statistics --- include/mitsuba/render/gkdtree.h | 164 ++++++++++++++++++++++++++----- 1 file changed, 137 insertions(+), 27 deletions(-) diff --git a/include/mitsuba/render/gkdtree.h b/include/mitsuba/render/gkdtree.h index 8f6541d5..92c8a72f 100644 --- a/include/mitsuba/render/gkdtree.h +++ b/include/mitsuba/render/gkdtree.h @@ -25,19 +25,23 @@ /// Compile-time KD-tree depth limit #define MTS_KD_MAX_DEPTH 48 + /// Collect statistics during building/traversal #define MTS_KD_STATISTICS 1 + /// Min-max bin count #define MTS_KD_MINMAX_BINS 32 + /// BlockedMemoryAllocator: don't create chunks smaller than 512KiB #define MTS_KD_MIN_ALLOC 512*1024 + /// Allocate nodes & index lists in chunks of 512 KiB #define MTS_KD_BLOCKSIZE_KD (512*1024/sizeof(KDNode)) #define MTS_KD_BLOCKSIZE_IDX (512*1024/sizeof(uint32_t)) + /// Allocate indirection lists in chunks of 1 KiB #define MTS_KD_BLOCKSIZE_IND (1024/sizeof(KDNode *)) - #if MTS_KD_DEBUG #define KDAssert(expr) Assert(expr) #define KDAssertEx(expr, text) AssertEx(expr, text) @@ -441,8 +445,8 @@ public: m_clip = true; m_stopPrims = 4; m_maxBadRefines = 2; - m_exactPrimThreshold = 4096; - m_maxDepth = 0; + m_exactPrimThreshold = 1409600; + m_maxDepth = 1024; m_retract = true; m_parallel = false; } @@ -549,7 +553,9 @@ public: } Log(EDebug, ""); - Log(EDebug, "Flattening node and index data structures .."); + timer->reset(); + Log(EDebug, "Optimizing node and index data structures .."); + Log(EDebug, "Finished -- took %i ms.", timer->getMilliseconds()); ctx.nodes.clear(); ctx.indices.clear(); @@ -567,7 +573,7 @@ public: Log(EDebug, ""); - Float rootSA = m_aabb.getSurfaceArea(); +// Float rootSA = m_aabb.getSurfaceArea(); // expTraversalSteps /= rootSA; // expLeavesVisited /= rootSA; // expPrimitivesIntersected /= rootSA; @@ -984,20 +990,114 @@ protected: * Thread-specific build context containing allocators etc. * \param node * KD-tree node entry to be filled + * \param eventStart + * Start pointer of an edge event list + * \param eventEnd + * End pointer of an edge event list * \param primCount * Total primitive count for the current node */ - void createLeaf(BuildContext &ctx, KDNode *node, const AABB &nodeAABB, size_type primCount) { - node->initLeafNode(0, primCount); + void createLeaf(BuildContext &ctx, KDNode *node, EdgeEvent *eventStart, + EdgeEvent *eventEnd, size_type primCount) { + node->initLeafNode(ctx.indices.size(), primCount); if (primCount > 0) { + size_type seenPrims = 0; ctx.nonemptyLeafNodeCount++; - - //OrderedChunkAllocator &alloc = ctx.indexAlloc; - //index_type *alloc = alloc.allocate(primCount); + for (EdgeEvent *event = eventStart; event != eventEnd + && event->axis == 0; ++event) { + if (event->type == EdgeEvent::EEdgeStart || + event->type == EdgeEvent::EEdgePlanar) { + ctx.indices.push_back(event->index); + seenPrims++; + } + } + KDAssert(seenPrims == primCount); } ctx.leafNodeCount++; } - + + /** + * \brief Leaf node creation helper function + * + * \param ctx + * Thread-specific build context containing allocators etc. + * \param node + * KD-tree node entry to be filled + * \param indices + * Start pointer of an index list + * \param primCount + * Total primitive count for the current node + */ + void createLeaf(BuildContext &ctx, KDNode *node, size_type *indices, + size_type primCount) { + node->initLeafNode(ctx.indices.size(), primCount); + if (primCount > 0) { + ctx.nonemptyLeafNodeCount++; + for (size_type i=0; iinitLeafNode(start, primCount); + size_t actualCount = ctx.indices.size() - start; + + if (actualCount != primCount) { + KDAssert(primCount > 0); + ctx.nonemptyLeafNodeCount++; + OrderedChunkAllocator &alloc = ctx.leftAlloc; + + /* Create a unique index list */ + index_type *tempStart = alloc.allocate(actualCount); + index_type *tempEnd = tempStart; + + cout << endl; + cout << "Before (" << actualCount << ") = "; + + for (size_type i=start, end = start + actualCount; i()); + index_type *ptr = tempStart; + cout << "After (" << primCount << ") = "; + + for (size_type i=0; i= m_maxDepth) { - createLeaf(ctx, node, nodeAABB, primCount); + createLeaf(ctx, node, indices, primCount); return leafCost; } @@ -1072,7 +1172,7 @@ protected: if ((bestSplit.sahCost > 4 * leafCost && primCount < 16) || bestSplit.sahCost == std::numeric_limits::infinity() || badRefines >= m_maxBadRefines) { - createLeaf(ctx, node, nodeAABB, primCount); + createLeaf(ctx, node, indices, primCount); return leafCost; } ++badRefines; @@ -1092,9 +1192,13 @@ protected: KDNode *children = ctx.nodes.allocate(2); - size_t nodePosBeforeSplit = ctx.nodes.size(); - size_t indexPosBeforeSplit = ctx.indices.size(); - size_t indirectionsPosBeforeSplit = ctx.indirections.size(); + size_type nodePosBeforeSplit = ctx.nodes.size(); + size_type indexPosBeforeSplit = ctx.indices.size(); + size_type indirectionsPosBeforeSplit = ctx.indirections.size(); + size_type leafNodeCountBeforeSplit = ctx.leafNodeCount; + size_type nonemptyLeafNodeCountBeforeSplit = ctx.nonemptyLeafNodeCount; + size_type innerNodeCountBeforeSplit = ctx.innerNodeCount; + if (!node->initInnerNode(bestSplit.axis, bestSplit.pos, children-node)) { ctx.indirections.push_back(children); /* Unable to store relative offset -- create an indirection @@ -1143,11 +1247,12 @@ protected: Tear up everything below this node and create a leaf */ ctx.nodes.resize(nodePosBeforeSplit); - ctx.indices.resize(indexPosBeforeSplit); ctx.indirections.resize(indirectionsPosBeforeSplit); - ctx.retractedSplits++; - createLeaf(ctx, node, nodeAABB, primCount); + ctx.leafNodeCount = leafNodeCountBeforeSplit; + ctx.nonemptyLeafNodeCount = nonemptyLeafNodeCountBeforeSplit; + ctx.innerNodeCount = innerNodeCountBeforeSplit; + createLeafAfterRetraction(ctx, node, indexPosBeforeSplit, primCount); return leafCost; } } @@ -1187,7 +1292,7 @@ protected: Float leafCost = primCount * m_intersectionCost; if (primCount <= m_stopPrims || depth >= m_maxDepth) { - createLeaf(ctx, node, nodeAABB, primCount); + createLeaf(ctx, node, eventStart, eventEnd, primCount); return leafCost; } @@ -1311,7 +1416,7 @@ protected: if ((bestSplit.sahCost > 4 * leafCost && primCount < 16) || badRefines >= m_maxBadRefines || bestSplit.sahCost == std::numeric_limits::infinity()) { - createLeaf(ctx, node, nodeAABB, primCount); + createLeaf(ctx, node, eventStart, eventEnd, primCount); return leafCost; } ++badRefines; @@ -1522,9 +1627,13 @@ protected: KDNode *children = ctx.nodes.allocate(2); - size_t nodePosBeforeSplit = ctx.nodes.size(); - size_t indexPosBeforeSplit = ctx.indices.size(); - size_t indirectionsPosBeforeSplit = ctx.indirections.size(); + size_type nodePosBeforeSplit = ctx.nodes.size(); + size_type indexPosBeforeSplit = ctx.indices.size(); + size_type indirectionsPosBeforeSplit = ctx.indirections.size(); + size_type leafNodeCountBeforeSplit = ctx.leafNodeCount; + size_type nonemptyLeafNodeCountBeforeSplit = ctx.nonemptyLeafNodeCount; + size_type innerNodeCountBeforeSplit = ctx.innerNodeCount; + if (!node->initInnerNode(bestSplit.axis, bestSplit.pos, children-node)) { ctx.indirections.push_back(children); @@ -1568,11 +1677,12 @@ protected: Tear up everything below this node and create a leaf */ ctx.nodes.resize(nodePosBeforeSplit); - ctx.indices.resize(indexPosBeforeSplit); ctx.indirections.resize(indirectionsPosBeforeSplit); - ctx.retractedSplits++; - createLeaf(ctx, node, nodeAABB, primCount); + ctx.leafNodeCount = leafNodeCountBeforeSplit; + ctx.nonemptyLeafNodeCount = nonemptyLeafNodeCountBeforeSplit; + ctx.innerNodeCount = innerNodeCountBeforeSplit; + createLeafAfterRetraction(ctx, node, indexPosBeforeSplit, primCount); return leafCost; }