bvh_statistics.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. // Copyright 2009-2021 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #pragma once
  4. #include "bvh.h"
  5. #include <sstream>
  6. namespace embree
  7. {
  8. template<int N>
  9. class BVHNStatistics
  10. {
  11. typedef BVHN<N> BVH;
  12. typedef typename BVH::AABBNode AABBNode;
  13. typedef typename BVH::OBBNode OBBNode;
  14. typedef typename BVH::AABBNodeMB AABBNodeMB;
  15. typedef typename BVH::AABBNodeMB4D AABBNodeMB4D;
  16. typedef typename BVH::OBBNodeMB OBBNodeMB;
  17. typedef typename BVH::QuantizedNode QuantizedNode;
  18. typedef typename BVH::NodeRef NodeRef;
  19. struct Statistics
  20. {
  21. template<typename Node>
  22. struct NodeStat
  23. {
  24. NodeStat ( double nodeSAH = 0,
  25. size_t numNodes = 0,
  26. size_t numChildren = 0)
  27. : nodeSAH(nodeSAH),
  28. numNodes(numNodes),
  29. numChildren(numChildren) {}
  30. double sah(BVH* bvh) const {
  31. return nodeSAH/bvh->getLinearBounds().expectedHalfArea();
  32. }
  33. size_t bytes() const {
  34. return numNodes*sizeof(Node);
  35. }
  36. size_t size() const {
  37. return numNodes;
  38. }
  39. double fillRateNom () const { return double(numChildren); }
  40. double fillRateDen () const { return double(numNodes*N); }
  41. double fillRate () const { return fillRateNom()/fillRateDen(); }
  42. __forceinline friend NodeStat operator+ ( const NodeStat& a, const NodeStat& b)
  43. {
  44. return NodeStat(a.nodeSAH + b.nodeSAH,
  45. a.numNodes+b.numNodes,
  46. a.numChildren+b.numChildren);
  47. }
  48. std::string toString(BVH* bvh, double sahTotal, size_t bytesTotal) const
  49. {
  50. std::ostringstream stream;
  51. stream.setf(std::ios::fixed, std::ios::floatfield);
  52. stream << "sah = " << std::setw(7) << std::setprecision(3) << sah(bvh);
  53. stream << " (" << std::setw(6) << std::setprecision(2) << 100.0*sah(bvh)/sahTotal << "%), ";
  54. stream << "#bytes = " << std::setw(7) << std::setprecision(2) << bytes()/1E6 << " MB ";
  55. stream << "(" << std::setw(6) << std::setprecision(2) << 100.0*double(bytes())/double(bytesTotal) << "%), ";
  56. stream << "#nodes = " << std::setw(7) << numNodes << " (" << std::setw(6) << std::setprecision(2) << 100.0*fillRate() << "% filled), ";
  57. stream << "#bytes/prim = " << std::setw(6) << std::setprecision(2) << double(bytes())/double(bvh->numPrimitives);
  58. return stream.str();
  59. }
  60. public:
  61. double nodeSAH;
  62. size_t numNodes;
  63. size_t numChildren;
  64. };
  65. struct LeafStat
  66. {
  67. static const int NHIST = 8;
  68. LeafStat ( double leafSAH = 0.0f,
  69. size_t numLeaves = 0,
  70. size_t numPrimsActive = 0,
  71. size_t numPrimsTotal = 0,
  72. size_t numPrimBlocks = 0,
  73. size_t numBytes = 0)
  74. : leafSAH(leafSAH),
  75. numLeaves(numLeaves),
  76. numPrimsActive(numPrimsActive),
  77. numPrimsTotal(numPrimsTotal),
  78. numPrimBlocks(numPrimBlocks),
  79. numBytes(numBytes)
  80. {
  81. for (size_t i=0; i<NHIST; i++)
  82. numPrimBlocksHistogram[i] = 0;
  83. }
  84. double sah(BVH* bvh) const {
  85. return leafSAH/bvh->getLinearBounds().expectedHalfArea();
  86. }
  87. size_t bytes(BVH* bvh) const {
  88. return numBytes;
  89. }
  90. size_t size() const {
  91. return numLeaves;
  92. }
  93. double fillRateNom (BVH* bvh) const { return double(numPrimsActive); }
  94. double fillRateDen (BVH* bvh) const { return double(numPrimsTotal); }
  95. double fillRate (BVH* bvh) const { return fillRateNom(bvh)/fillRateDen(bvh); }
  96. __forceinline friend LeafStat operator+ ( const LeafStat& a, const LeafStat& b)
  97. {
  98. LeafStat stat(a.leafSAH + b.leafSAH,
  99. a.numLeaves+b.numLeaves,
  100. a.numPrimsActive+b.numPrimsActive,
  101. a.numPrimsTotal+b.numPrimsTotal,
  102. a.numPrimBlocks+b.numPrimBlocks,
  103. a.numBytes+b.numBytes);
  104. for (size_t i=0; i<NHIST; i++) {
  105. stat.numPrimBlocksHistogram[i] += a.numPrimBlocksHistogram[i];
  106. stat.numPrimBlocksHistogram[i] += b.numPrimBlocksHistogram[i];
  107. }
  108. return stat;
  109. }
  110. std::string toString(BVH* bvh, double sahTotal, size_t bytesTotal) const
  111. {
  112. std::ostringstream stream;
  113. stream.setf(std::ios::fixed, std::ios::floatfield);
  114. stream << "sah = " << std::setw(7) << std::setprecision(3) << sah(bvh);
  115. stream << " (" << std::setw(6) << std::setprecision(2) << 100.0*sah(bvh)/sahTotal << "%), ";
  116. stream << "#bytes = " << std::setw(7) << std::setprecision(2) << double(bytes(bvh))/1E6 << " MB ";
  117. stream << "(" << std::setw(6) << std::setprecision(2) << 100.0*double(bytes(bvh))/double(bytesTotal) << "%), ";
  118. stream << "#nodes = " << std::setw(7) << numLeaves << " (" << std::setw(6) << std::setprecision(2) << 100.0*fillRate(bvh) << "% filled), ";
  119. stream << "#bytes/prim = " << std::setw(6) << std::setprecision(2) << double(bytes(bvh))/double(bvh->numPrimitives);
  120. return stream.str();
  121. }
  122. std::string histToString() const
  123. {
  124. std::ostringstream stream;
  125. stream.setf(std::ios::fixed, std::ios::floatfield);
  126. for (size_t i=0; i<NHIST; i++)
  127. stream << std::setw(6) << std::setprecision(2) << 100.0f*float(numPrimBlocksHistogram[i])/float(numLeaves) << "% ";
  128. return stream.str();
  129. }
  130. public:
  131. double leafSAH; //!< SAH of the leaves only
  132. size_t numLeaves; //!< Number of leaf nodes.
  133. size_t numPrimsActive; //!< Number of active primitives (
  134. size_t numPrimsTotal; //!< Number of active and inactive primitives
  135. size_t numPrimBlocks; //!< Number of primitive blocks.
  136. size_t numBytes; //!< Number of bytes of leaves.
  137. size_t numPrimBlocksHistogram[8];
  138. };
  139. public:
  140. Statistics (size_t depth = 0,
  141. LeafStat statLeaf = LeafStat(),
  142. NodeStat<AABBNode> statAABBNodes = NodeStat<AABBNode>(),
  143. NodeStat<OBBNode> statOBBNodes = NodeStat<OBBNode>(),
  144. NodeStat<AABBNodeMB> statAABBNodesMB = NodeStat<AABBNodeMB>(),
  145. NodeStat<AABBNodeMB4D> statAABBNodesMB4D = NodeStat<AABBNodeMB4D>(),
  146. NodeStat<OBBNodeMB> statOBBNodesMB = NodeStat<OBBNodeMB>(),
  147. NodeStat<QuantizedNode> statQuantizedNodes = NodeStat<QuantizedNode>())
  148. : depth(depth),
  149. statLeaf(statLeaf),
  150. statAABBNodes(statAABBNodes),
  151. statOBBNodes(statOBBNodes),
  152. statAABBNodesMB(statAABBNodesMB),
  153. statAABBNodesMB4D(statAABBNodesMB4D),
  154. statOBBNodesMB(statOBBNodesMB),
  155. statQuantizedNodes(statQuantizedNodes) {}
  156. double sah(BVH* bvh) const
  157. {
  158. return statLeaf.sah(bvh) +
  159. statAABBNodes.sah(bvh) +
  160. statOBBNodes.sah(bvh) +
  161. statAABBNodesMB.sah(bvh) +
  162. statAABBNodesMB4D.sah(bvh) +
  163. statOBBNodesMB.sah(bvh) +
  164. statQuantizedNodes.sah(bvh);
  165. }
  166. size_t bytes(BVH* bvh) const {
  167. return statLeaf.bytes(bvh) +
  168. statAABBNodes.bytes() +
  169. statOBBNodes.bytes() +
  170. statAABBNodesMB.bytes() +
  171. statAABBNodesMB4D.bytes() +
  172. statOBBNodesMB.bytes() +
  173. statQuantizedNodes.bytes();
  174. }
  175. size_t size() const
  176. {
  177. return statLeaf.size() +
  178. statAABBNodes.size() +
  179. statOBBNodes.size() +
  180. statAABBNodesMB.size() +
  181. statAABBNodesMB4D.size() +
  182. statOBBNodesMB.size() +
  183. statQuantizedNodes.size();
  184. }
  185. double fillRate (BVH* bvh) const
  186. {
  187. double nom = statLeaf.fillRateNom(bvh) +
  188. statAABBNodes.fillRateNom() +
  189. statOBBNodes.fillRateNom() +
  190. statAABBNodesMB.fillRateNom() +
  191. statAABBNodesMB4D.fillRateNom() +
  192. statOBBNodesMB.fillRateNom() +
  193. statQuantizedNodes.fillRateNom();
  194. double den = statLeaf.fillRateDen(bvh) +
  195. statAABBNodes.fillRateDen() +
  196. statOBBNodes.fillRateDen() +
  197. statAABBNodesMB.fillRateDen() +
  198. statAABBNodesMB4D.fillRateDen() +
  199. statOBBNodesMB.fillRateDen() +
  200. statQuantizedNodes.fillRateDen();
  201. return nom/den;
  202. }
  203. friend Statistics operator+ ( const Statistics& a, const Statistics& b )
  204. {
  205. return Statistics(max(a.depth,b.depth),
  206. a.statLeaf + b.statLeaf,
  207. a.statAABBNodes + b.statAABBNodes,
  208. a.statOBBNodes + b.statOBBNodes,
  209. a.statAABBNodesMB + b.statAABBNodesMB,
  210. a.statAABBNodesMB4D + b.statAABBNodesMB4D,
  211. a.statOBBNodesMB + b.statOBBNodesMB,
  212. a.statQuantizedNodes + b.statQuantizedNodes);
  213. }
  214. static Statistics add ( const Statistics& a, const Statistics& b ) {
  215. return a+b;
  216. }
  217. public:
  218. size_t depth;
  219. LeafStat statLeaf;
  220. NodeStat<AABBNode> statAABBNodes;
  221. NodeStat<OBBNode> statOBBNodes;
  222. NodeStat<AABBNodeMB> statAABBNodesMB;
  223. NodeStat<AABBNodeMB4D> statAABBNodesMB4D;
  224. NodeStat<OBBNodeMB> statOBBNodesMB;
  225. NodeStat<QuantizedNode> statQuantizedNodes;
  226. };
  227. public:
  228. /* Constructor gathers statistics. */
  229. BVHNStatistics (BVH* bvh);
  230. /*! Convert statistics into a string */
  231. std::string str();
  232. double sah() const {
  233. return stat.sah(bvh);
  234. }
  235. size_t bytesUsed() const {
  236. return stat.bytes(bvh);
  237. }
  238. private:
  239. Statistics statistics(NodeRef node, const double A, const BBox1f dt);
  240. private:
  241. BVH* bvh;
  242. Statistics stat;
  243. };
  244. typedef BVHNStatistics<4> BVH4Statistics;
  245. typedef BVHNStatistics<8> BVH8Statistics;
  246. }