bvh_statistics.cpp 6.8 KB

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