priminfo.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. // Copyright 2009-2021 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #pragma once
  4. #include "../common/default.h"
  5. #include "../common/primref.h"
  6. #include "../common/primref_mb.h"
  7. namespace embree
  8. {
  9. // FIXME: maybe there's a better place for this util fct
  10. __forceinline float areaProjectedTriangle(const Vec3fa& v0, const Vec3fa& v1, const Vec3fa& v2)
  11. {
  12. const Vec3fa e0 = v1-v0;
  13. const Vec3fa e1 = v2-v0;
  14. const Vec3fa d = cross(e0,e1);
  15. return fabs(d.x) + fabs(d.y) + fabs(d.z);
  16. }
  17. //namespace isa
  18. //{
  19. template<typename BBox>
  20. class CentGeom
  21. {
  22. public:
  23. __forceinline CentGeom () {}
  24. __forceinline CentGeom (EmptyTy)
  25. : geomBounds(empty), centBounds(empty) {}
  26. __forceinline CentGeom (const BBox& geomBounds, const BBox3fa& centBounds)
  27. : geomBounds(geomBounds), centBounds(centBounds) {}
  28. template<typename PrimRef>
  29. __forceinline void extend_primref(const PrimRef& prim)
  30. {
  31. BBox bounds; Vec3fa center;
  32. prim.binBoundsAndCenter(bounds,center);
  33. geomBounds.extend(bounds);
  34. centBounds.extend(center);
  35. }
  36. template<typename PrimRef>
  37. __forceinline void extend_center2(const PrimRef& prim)
  38. {
  39. BBox3fa bounds = prim.bounds();
  40. geomBounds.extend(bounds);
  41. centBounds.extend(bounds.center2());
  42. }
  43. __forceinline void extend(const BBox& geomBounds_) {
  44. geomBounds.extend(geomBounds_);
  45. centBounds.extend(center2(geomBounds_));
  46. }
  47. __forceinline void merge(const CentGeom& other)
  48. {
  49. geomBounds.extend(other.geomBounds);
  50. centBounds.extend(other.centBounds);
  51. }
  52. static __forceinline const CentGeom merge2(const CentGeom& a, const CentGeom& b) {
  53. CentGeom r = a; r.merge(b); return r;
  54. }
  55. public:
  56. BBox geomBounds; //!< geometry bounds of primitives
  57. BBox3fa centBounds; //!< centroid bounds of primitives
  58. };
  59. typedef CentGeom<BBox3fa> CentGeomBBox3fa;
  60. /*! stores bounding information for a set of primitives */
  61. template<typename BBox>
  62. class PrimInfoT : public CentGeom<BBox>
  63. {
  64. public:
  65. using CentGeom<BBox>::geomBounds;
  66. using CentGeom<BBox>::centBounds;
  67. __forceinline PrimInfoT () {}
  68. __forceinline PrimInfoT (EmptyTy)
  69. : CentGeom<BBox>(empty), begin(0), end(0) {}
  70. __forceinline PrimInfoT (size_t begin, size_t end, const CentGeomBBox3fa& centGeomBounds)
  71. : CentGeom<BBox>(centGeomBounds), begin(begin), end(end) {}
  72. template<typename PrimRef>
  73. __forceinline void add_primref(const PrimRef& prim)
  74. {
  75. CentGeom<BBox>::extend_primref(prim);
  76. end++;
  77. }
  78. template<typename PrimRef>
  79. __forceinline void add_center2(const PrimRef& prim) {
  80. CentGeom<BBox>::extend_center2(prim);
  81. end++;
  82. }
  83. template<typename PrimRef>
  84. __forceinline void add_center2(const PrimRef& prim, const size_t i) {
  85. CentGeom<BBox>::extend_center2(prim);
  86. end+=i;
  87. }
  88. /*__forceinline void add(const BBox& geomBounds_) {
  89. CentGeom<BBox>::extend(geomBounds_);
  90. end++;
  91. }
  92. __forceinline void add(const BBox& geomBounds_, const size_t i) {
  93. CentGeom<BBox>::extend(geomBounds_);
  94. end+=i;
  95. }*/
  96. __forceinline void merge(const PrimInfoT& other)
  97. {
  98. CentGeom<BBox>::merge(other);
  99. begin += other.begin;
  100. end += other.end;
  101. }
  102. static __forceinline const PrimInfoT merge(const PrimInfoT& a, const PrimInfoT& b) {
  103. PrimInfoT r = a; r.merge(b); return r;
  104. }
  105. /*! returns the number of primitives */
  106. __forceinline size_t size() const {
  107. return end-begin;
  108. }
  109. __forceinline float halfArea() {
  110. return expectedApproxHalfArea(geomBounds);
  111. }
  112. __forceinline float leafSAH() const {
  113. return expectedApproxHalfArea(geomBounds)*float(size());
  114. //return halfArea(geomBounds)*blocks(num);
  115. }
  116. __forceinline float leafSAH(size_t block_shift) const {
  117. return expectedApproxHalfArea(geomBounds)*float((size()+(size_t(1)<<block_shift)-1) >> block_shift);
  118. //return halfArea(geomBounds)*float((num+3) >> 2);
  119. //return halfArea(geomBounds)*blocks(num);
  120. }
  121. /*! stream output */
  122. friend embree_ostream operator<<(embree_ostream cout, const PrimInfoT& pinfo) {
  123. return cout << "PrimInfo { begin = " << pinfo.begin << ", end = " << pinfo.end << ", geomBounds = " << pinfo.geomBounds << ", centBounds = " << pinfo.centBounds << "}";
  124. }
  125. public:
  126. size_t begin,end; //!< number of primitives
  127. };
  128. typedef PrimInfoT<BBox3fa> PrimInfo;
  129. //typedef PrimInfoT<LBBox3fa> PrimInfoMB;
  130. /*! stores bounding information for a set of primitives */
  131. template<typename BBox>
  132. class PrimInfoMBT : public CentGeom<BBox>
  133. {
  134. public:
  135. using CentGeom<BBox>::geomBounds;
  136. using CentGeom<BBox>::centBounds;
  137. __forceinline PrimInfoMBT () {
  138. }
  139. __forceinline PrimInfoMBT (EmptyTy)
  140. : CentGeom<BBox>(empty), object_range(0,0), num_time_segments(0), max_num_time_segments(0), max_time_range(0.0f,1.0f), time_range(1.0f,0.0f) {}
  141. __forceinline PrimInfoMBT (size_t begin, size_t end)
  142. : CentGeom<BBox>(empty), object_range(begin,end), num_time_segments(0), max_num_time_segments(0), max_time_range(0.0f,1.0f), time_range(1.0f,0.0f) {}
  143. template<typename PrimRef>
  144. __forceinline void add_primref(const PrimRef& prim)
  145. {
  146. CentGeom<BBox>::extend_primref(prim);
  147. time_range.extend(prim.time_range);
  148. object_range._end++;
  149. num_time_segments += prim.size();
  150. if (max_num_time_segments < prim.totalTimeSegments()) {
  151. max_num_time_segments = prim.totalTimeSegments();
  152. max_time_range = prim.time_range;
  153. }
  154. }
  155. __forceinline void merge(const PrimInfoMBT& other)
  156. {
  157. CentGeom<BBox>::merge(other);
  158. time_range.extend(other.time_range);
  159. object_range._begin += other.object_range.begin();
  160. object_range._end += other.object_range.end();
  161. num_time_segments += other.num_time_segments;
  162. if (max_num_time_segments < other.max_num_time_segments) {
  163. max_num_time_segments = other.max_num_time_segments;
  164. max_time_range = other.max_time_range;
  165. }
  166. }
  167. static __forceinline const PrimInfoMBT merge2(const PrimInfoMBT& a, const PrimInfoMBT& b) {
  168. PrimInfoMBT r = a; r.merge(b); return r;
  169. }
  170. __forceinline size_t begin() const {
  171. return object_range.begin();
  172. }
  173. __forceinline size_t end() const {
  174. return object_range.end();
  175. }
  176. /*! returns the number of primitives */
  177. __forceinline size_t size() const {
  178. return object_range.size();
  179. }
  180. __forceinline float halfArea() const {
  181. return time_range.size()*expectedApproxHalfArea(geomBounds);
  182. }
  183. __forceinline float leafSAH() const {
  184. return time_range.size()*expectedApproxHalfArea(geomBounds)*float(num_time_segments);
  185. }
  186. __forceinline float leafSAH(size_t block_shift) const {
  187. return time_range.size()*expectedApproxHalfArea(geomBounds)*float((num_time_segments+(size_t(1)<<block_shift)-1) >> block_shift);
  188. }
  189. __forceinline float align_time(float ct) const
  190. {
  191. //return roundf(ct * float(numTimeSegments)) / float(numTimeSegments);
  192. float t0 = (ct-max_time_range.lower)/max_time_range.size();
  193. float t1 = roundf(t0 * float(max_num_time_segments)) / float(max_num_time_segments);
  194. return t1*max_time_range.size()+max_time_range.lower;
  195. }
  196. /*! stream output */
  197. friend embree_ostream operator<<(embree_ostream cout, const PrimInfoMBT& pinfo)
  198. {
  199. return cout << "PrimInfo { " <<
  200. "object_range = " << pinfo.object_range <<
  201. ", time_range = " << pinfo.time_range <<
  202. ", time_segments = " << pinfo.num_time_segments <<
  203. ", geomBounds = " << pinfo.geomBounds <<
  204. ", centBounds = " << pinfo.centBounds <<
  205. "}";
  206. }
  207. public:
  208. range<size_t> object_range; //!< primitive range
  209. size_t num_time_segments; //!< total number of time segments of all added primrefs
  210. size_t max_num_time_segments; //!< maximum number of time segments of a primitive
  211. BBox1f max_time_range; //!< time range of primitive with max_num_time_segments
  212. BBox1f time_range; //!< merged time range of primitives when merging prims, or additionally clipped with build time range when used in SetMB
  213. };
  214. typedef PrimInfoMBT<typename PrimRefMB::BBox> PrimInfoMB;
  215. struct SetMB : public PrimInfoMB
  216. {
  217. static const size_t PARALLEL_THRESHOLD = 3 * 1024;
  218. static const size_t PARALLEL_FIND_BLOCK_SIZE = 1024;
  219. static const size_t PARALLEL_PARTITION_BLOCK_SIZE = 128;
  220. typedef mvector<PrimRefMB>* PrimRefVector;
  221. __forceinline SetMB() {}
  222. __forceinline SetMB(const PrimInfoMB& pinfo_i, PrimRefVector prims)
  223. : PrimInfoMB(pinfo_i), prims(prims) {}
  224. __forceinline SetMB(const PrimInfoMB& pinfo_i, PrimRefVector prims, range<size_t> object_range_in, BBox1f time_range_in)
  225. : PrimInfoMB(pinfo_i), prims(prims)
  226. {
  227. object_range = object_range_in;
  228. time_range = intersect(time_range,time_range_in);
  229. }
  230. __forceinline SetMB(const PrimInfoMB& pinfo_i, PrimRefVector prims, BBox1f time_range_in)
  231. : PrimInfoMB(pinfo_i), prims(prims)
  232. {
  233. time_range = intersect(time_range,time_range_in);
  234. }
  235. void deterministic_order() const
  236. {
  237. /* required as parallel partition destroys original primitive order */
  238. PrimRefMB* prim = prims->data();
  239. std::sort(&prim[object_range.begin()],&prim[object_range.end()]);
  240. }
  241. template<typename RecalculatePrimRef>
  242. __forceinline LBBox3fa linearBounds(const RecalculatePrimRef& recalculatePrimRef) const
  243. {
  244. auto reduce = [&](const range<size_t>& r) -> LBBox3fa
  245. {
  246. LBBox3fa cbounds(empty);
  247. for (size_t j = r.begin(); j < r.end(); j++)
  248. {
  249. PrimRefMB& ref = (*prims)[j];
  250. const LBBox3fa bn = recalculatePrimRef.linearBounds(ref, time_range);
  251. cbounds.extend(bn);
  252. };
  253. return cbounds;
  254. };
  255. return parallel_reduce(object_range.begin(), object_range.end(), PARALLEL_FIND_BLOCK_SIZE, PARALLEL_THRESHOLD, LBBox3fa(empty),
  256. reduce,
  257. [&](const LBBox3fa& b0, const LBBox3fa& b1) -> LBBox3fa { return embree::merge(b0, b1); });
  258. }
  259. template<typename RecalculatePrimRef>
  260. __forceinline LBBox3fa linearBounds(const RecalculatePrimRef& recalculatePrimRef, const LinearSpace3fa& space) const
  261. {
  262. auto reduce = [&](const range<size_t>& r) -> LBBox3fa
  263. {
  264. LBBox3fa cbounds(empty);
  265. for (size_t j = r.begin(); j < r.end(); j++)
  266. {
  267. PrimRefMB& ref = (*prims)[j];
  268. const LBBox3fa bn = recalculatePrimRef.linearBounds(ref, time_range, space);
  269. cbounds.extend(bn);
  270. };
  271. return cbounds;
  272. };
  273. return parallel_reduce(object_range.begin(), object_range.end(), PARALLEL_FIND_BLOCK_SIZE, PARALLEL_THRESHOLD, LBBox3fa(empty),
  274. reduce,
  275. [&](const LBBox3fa& b0, const LBBox3fa& b1) -> LBBox3fa { return embree::merge(b0, b1); });
  276. }
  277. template<typename RecalculatePrimRef>
  278. const SetMB primInfo(const RecalculatePrimRef& recalculatePrimRef, const LinearSpace3fa& space) const
  279. {
  280. auto computePrimInfo = [&](const range<size_t>& r) -> PrimInfoMB
  281. {
  282. PrimInfoMB pinfo(empty);
  283. for (size_t j=r.begin(); j<r.end(); j++)
  284. {
  285. PrimRefMB& ref = (*prims)[j];
  286. PrimRefMB ref1 = recalculatePrimRef(ref,time_range,space);
  287. pinfo.add_primref(ref1);
  288. };
  289. return pinfo;
  290. };
  291. const PrimInfoMB pinfo = parallel_reduce(object_range.begin(), object_range.end(), PARALLEL_FIND_BLOCK_SIZE, PARALLEL_THRESHOLD,
  292. PrimInfoMB(empty), computePrimInfo, PrimInfoMB::merge2);
  293. return SetMB(pinfo,prims,object_range,time_range);
  294. }
  295. public:
  296. PrimRefVector prims;
  297. };
  298. //}
  299. }