1// Copyright 2009-2021 Intel Corporation
2// SPDX-License-Identifier: Apache-2.0
3
4#include "bvh_statistics.h"
5#include "../../common/algorithms/parallel_reduce.h"
6
7namespace embree
8{
9 template<int N>
10 BVHNStatistics<N>::BVHNStatistics (BVH* bvh) : bvh(bvh)
11 {
12 double A = max(0.0f,bvh->getLinearBounds().expectedHalfArea());
13 stat = statistics(bvh->root,A,BBox1f(0.0f,1.0f));
14 }
15
16 template<int N>
17 std::string BVHNStatistics<N>::str()
18 {
19 std::ostringstream stream;
20 stream.setf(std::ios::fixed, std::ios::floatfield);
21 stream << " primitives = " << bvh->numPrimitives << ", vertices = " << bvh->numVertices << ", depth = " << stat.depth << std::endl;
22 size_t totalBytes = stat.bytes(bvh);
23 double totalSAH = stat.sah(bvh);
24 stream << " total : sah = " << std::setw(7) << std::setprecision(3) << totalSAH << " (100.00%), ";
25 stream << "#bytes = " << std::setw(7) << std::setprecision(2) << totalBytes/1E6 << " MB (100.00%), ";
26 stream << "#nodes = " << std::setw(7) << stat.size() << " (" << std::setw(6) << std::setprecision(2) << 100.0*stat.fillRate(bvh) << "% filled), ";
27 stream << "#bytes/prim = " << std::setw(6) << std::setprecision(2) << double(totalBytes)/double(bvh->numPrimitives) << std::endl;
28 if (stat.statAABBNodes.numNodes ) stream << " getAABBNodes : " << stat.statAABBNodes.toString(bvh,totalSAH,totalBytes) << std::endl;
29 if (stat.statOBBNodes.numNodes ) stream << " ungetAABBNodes : " << stat.statOBBNodes.toString(bvh,totalSAH,totalBytes) << std::endl;
30 if (stat.statAABBNodesMB.numNodes ) stream << " getAABBNodesMB : " << stat.statAABBNodesMB.toString(bvh,totalSAH,totalBytes) << std::endl;
31 if (stat.statAABBNodesMB4D.numNodes) stream << " getAABBNodesMB4D : " << stat.statAABBNodesMB4D.toString(bvh,totalSAH,totalBytes) << std::endl;
32 if (stat.statOBBNodesMB.numNodes) stream << " ungetAABBNodesMB : " << stat.statOBBNodesMB.toString(bvh,totalSAH,totalBytes) << std::endl;
33 if (stat.statQuantizedNodes.numNodes ) stream << " quantizedNodes : " << stat.statQuantizedNodes.toString(bvh,totalSAH,totalBytes) << std::endl;
34 if (true) stream << " leaves : " << stat.statLeaf.toString(bvh,totalSAH,totalBytes) << std::endl;
35 if (true) stream << " histogram : " << stat.statLeaf.histToString() << std::endl;
36 return stream.str();
37 }
38
39 template<int N>
40 typename BVHNStatistics<N>::Statistics BVHNStatistics<N>::statistics(NodeRef node, const double A, const BBox1f t0t1)
41 {
42 Statistics s;
43 assert(t0t1.size() > 0.0f);
44 double dt = max(0.0f,t0t1.size());
45 if (node.isAABBNode())
46 {
47 AABBNode* n = node.getAABBNode();
48 s = s + parallel_reduce(0,N,Statistics(),[&] ( const int i ) {
49 if (n->child(i) == BVH::emptyNode) return Statistics();
50 const double Ai = max(0.0f,halfArea(n->extend(i)));
51 Statistics s = statistics(n->child(i),Ai,t0t1);
52 s.statAABBNodes.numChildren++;
53 return s;
54 }, Statistics::add);
55 s.statAABBNodes.numNodes++;
56 s.statAABBNodes.nodeSAH += dt*A;
57 s.depth++;
58 }
59 else if (node.isOBBNode())
60 {
61 OBBNode* n = node.ungetAABBNode();
62 s = s + parallel_reduce(0,N,Statistics(),[&] ( const int i ) {
63 if (n->child(i) == BVH::emptyNode) return Statistics();
64 const double Ai = max(0.0f,halfArea(n->extent(i)));
65 Statistics s = statistics(n->child(i),Ai,t0t1);
66 s.statOBBNodes.numChildren++;
67 return s;
68 }, Statistics::add);
69 s.statOBBNodes.numNodes++;
70 s.statOBBNodes.nodeSAH += dt*A;
71 s.depth++;
72 }
73 else if (node.isAABBNodeMB())
74 {
75 AABBNodeMB* n = node.getAABBNodeMB();
76 s = s + parallel_reduce(0,N,Statistics(),[&] ( const int i ) {
77 if (n->child(i) == BVH::emptyNode) return Statistics();
78 const double Ai = max(0.0f,n->expectedHalfArea(i,t0t1));
79 Statistics s = statistics(n->child(i),Ai,t0t1);
80 s.statAABBNodesMB.numChildren++;
81 return s;
82 }, Statistics::add);
83 s.statAABBNodesMB.numNodes++;
84 s.statAABBNodesMB.nodeSAH += dt*A;
85 s.depth++;
86 }
87 else if (node.isAABBNodeMB4D())
88 {
89 AABBNodeMB4D* n = node.getAABBNodeMB4D();
90 s = s + parallel_reduce(0,N,Statistics(),[&] ( const int i ) {
91 if (n->child(i) == BVH::emptyNode) return Statistics();
92 const BBox1f t0t1i = intersect(t0t1,n->timeRange(i));
93 assert(!t0t1i.empty());
94 const double Ai = n->AABBNodeMB::expectedHalfArea(i,t0t1i);
95 Statistics s = statistics(n->child(i),Ai,t0t1i);
96 s.statAABBNodesMB4D.numChildren++;
97 return s;
98 }, Statistics::add);
99 s.statAABBNodesMB4D.numNodes++;
100 s.statAABBNodesMB4D.nodeSAH += dt*A;
101 s.depth++;
102 }
103 else if (node.isOBBNodeMB())
104 {
105 OBBNodeMB* n = node.ungetAABBNodeMB();
106 s = s + parallel_reduce(0,N,Statistics(),[&] ( const int i ) {
107 if (n->child(i) == BVH::emptyNode) return Statistics();
108 const double Ai = max(0.0f,halfArea(n->extent0(i)));
109 Statistics s = statistics(n->child(i),Ai,t0t1);
110 s.statOBBNodesMB.numChildren++;
111 return s;
112 }, Statistics::add);
113 s.statOBBNodesMB.numNodes++;
114 s.statOBBNodesMB.nodeSAH += dt*A;
115 s.depth++;
116 }
117 else if (node.isQuantizedNode())
118 {
119 QuantizedNode* n = node.quantizedNode();
120 s = s + parallel_reduce(0,N,Statistics(),[&] ( const int i ) {
121 if (n->child(i) == BVH::emptyNode) return Statistics();
122 const double Ai = max(0.0f,halfArea(n->extent(i)));
123 Statistics s = statistics(n->child(i),Ai,t0t1);
124 s.statQuantizedNodes.numChildren++;
125 return s;
126 }, Statistics::add);
127 s.statQuantizedNodes.numNodes++;
128 s.statQuantizedNodes.nodeSAH += dt*A;
129 s.depth++;
130 }
131 else if (node.isLeaf())
132 {
133 size_t num; const char* tri = node.leaf(num);
134 if (num)
135 {
136 for (size_t i=0; i<num; i++)
137 {
138 const size_t bytes = bvh->primTy->getBytes(tri);
139 s.statLeaf.numPrimsActive += bvh->primTy->sizeActive(tri);
140 s.statLeaf.numPrimsTotal += bvh->primTy->sizeTotal(tri);
141 s.statLeaf.numBytes += bytes;
142 tri+=bytes;
143 }
144 s.statLeaf.numLeaves++;
145 s.statLeaf.numPrimBlocks += num;
146 s.statLeaf.leafSAH += dt*A*num;
147 if (num-1 < Statistics::LeafStat::NHIST) {
148 s.statLeaf.numPrimBlocksHistogram[num-1]++;
149 }
150 }
151 }
152 else {
153 // -- GODOT start --
154 // throw std::runtime_error("not supported node type in bvh_statistics");
155 abort();
156 // -- GODOT end --
157 }
158 return s;
159 }
160
161#if defined(__AVX__)
162 template class BVHNStatistics<8>;
163#endif
164
165#if !defined(__AVX__) || (!defined(EMBREE_TARGET_SSE2) && !defined(EMBREE_TARGET_SSE42)) || defined(__aarch64__)
166 template class BVHNStatistics<4>;
167#endif
168}
169