heuristic_binning_array_unaligned.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // ======================================================================== //
  2. // Copyright 2009-2017 Intel Corporation //
  3. // //
  4. // Licensed under the Apache License, Version 2.0 (the "License"); //
  5. // you may not use this file except in compliance with the License. //
  6. // You may obtain a copy of the License at //
  7. // //
  8. // http://www.apache.org/licenses/LICENSE-2.0 //
  9. // //
  10. // Unless required by applicable law or agreed to in writing, software //
  11. // distributed under the License is distributed on an "AS IS" BASIS, //
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
  13. // See the License for the specific language governing permissions and //
  14. // limitations under the License. //
  15. // ======================================================================== //
  16. #pragma once
  17. #include "heuristic_binning.h"
  18. namespace embree
  19. {
  20. namespace isa
  21. {
  22. /*! Performs standard object binning */
  23. template<typename PrimRef, size_t BINS>
  24. struct UnalignedHeuristicArrayBinningSAH
  25. {
  26. typedef BinSplit<BINS> Split;
  27. typedef BinInfoT<BINS,PrimRef,BBox3fa> Binner;
  28. typedef range<size_t> Set;
  29. __forceinline UnalignedHeuristicArrayBinningSAH () // FIXME: required?
  30. : scene(nullptr), prims(nullptr) {}
  31. /*! remember prim array */
  32. __forceinline UnalignedHeuristicArrayBinningSAH (Scene* scene, PrimRef* prims)
  33. : scene(scene), prims(prims) {}
  34. const LinearSpace3fa computeAlignedSpace(const range<size_t>& set)
  35. {
  36. /*! find first curve that defines valid direction */
  37. Vec3fa axis(0,0,1);
  38. for (size_t i=set.begin(); i<set.end(); i++)
  39. {
  40. NativeCurves* mesh = (NativeCurves*) scene->get(prims[i].geomID());
  41. const unsigned vtxID = mesh->curve(prims[i].primID());
  42. const Vec3fa v0 = mesh->vertex(vtxID+0);
  43. const Vec3fa v1 = mesh->vertex(vtxID+1);
  44. const Vec3fa v2 = mesh->vertex(vtxID+2);
  45. const Vec3fa v3 = mesh->vertex(vtxID+3);
  46. const Curve3fa curve(v0,v1,v2,v3);
  47. const Vec3fa p0 = curve.begin();
  48. const Vec3fa p3 = curve.end();
  49. const Vec3fa axis1 = normalize(p3 - p0);
  50. if (sqr_length(p3-p0) > 1E-18f) {
  51. axis = axis1;
  52. break;
  53. }
  54. }
  55. return frame(axis).transposed();
  56. }
  57. const PrimInfo computePrimInfo(const range<size_t>& set, const LinearSpace3fa& space)
  58. {
  59. auto computeBounds = [&](const range<size_t>& r) -> CentGeomBBox3fa
  60. {
  61. CentGeomBBox3fa bounds(empty);
  62. for (size_t i=r.begin(); i<r.end(); i++) {
  63. NativeCurves* mesh = (NativeCurves*) scene->get(prims[i].geomID());
  64. bounds.extend(mesh->bounds(space,prims[i].primID()));
  65. }
  66. return bounds;
  67. };
  68. const CentGeomBBox3fa bounds = parallel_reduce(set.begin(), set.end(), size_t(1024), size_t(4096),
  69. CentGeomBBox3fa(empty), computeBounds, CentGeomBBox3fa::merge2);
  70. return PrimInfo(set.begin(),set.end(),bounds.geomBounds,bounds.centBounds);
  71. }
  72. /*! finds the best split */
  73. __forceinline const Split find(const PrimInfoRange& pinfo, const size_t logBlockSize, const LinearSpace3fa& space)
  74. {
  75. if (likely(pinfo.size() < 10000))
  76. return find_template<false>(pinfo,logBlockSize,space);
  77. else
  78. return find_template<true>(pinfo,logBlockSize,space);
  79. }
  80. /*! finds the best split */
  81. template<bool parallel>
  82. const Split find_template(const PrimInfoRange& set, const size_t logBlockSize, const LinearSpace3fa& space)
  83. {
  84. Binner binner(empty);
  85. const BinMapping<BINS> mapping(set);
  86. bin_serial_or_parallel<parallel>(binner,prims,set.begin(),set.end(),size_t(4096),mapping,space,scene);
  87. return binner.best(mapping,logBlockSize);
  88. }
  89. /*! array partitioning */
  90. __forceinline void split(const Split& split, const LinearSpace3fa& space, const Set& set, PrimInfoRange& lset, PrimInfoRange& rset)
  91. {
  92. if (likely(set.size() < 10000))
  93. split_template<false>(split,space,set,lset,rset);
  94. else
  95. split_template<true>(split,space,set,lset,rset);
  96. }
  97. /*! array partitioning */
  98. template<bool parallel>
  99. __forceinline void split_template(const Split& split, const LinearSpace3fa& space, const Set& set, PrimInfoRange& lset, PrimInfoRange& rset)
  100. {
  101. if (!split.valid()) {
  102. deterministic_order(set);
  103. return splitFallback(set,lset,rset);
  104. }
  105. const size_t begin = set.begin();
  106. const size_t end = set.end();
  107. CentGeomBBox3fa local_left(empty);
  108. CentGeomBBox3fa local_right(empty);
  109. const int splitPos = split.pos;
  110. const int splitDim = split.dim;
  111. size_t center = 0;
  112. if (likely(set.size() < 10000))
  113. center = serial_partitioning(prims,begin,end,local_left,local_right,
  114. [&] (const PrimRef& ref) { return split.mapping.bin_unsafe(ref,space,scene)[splitDim] < splitPos; },
  115. [] (CentGeomBBox3fa& pinfo,const PrimRef& ref) { pinfo.extend(ref.bounds()); });
  116. else
  117. center = parallel_partitioning(prims,begin,end,EmptyTy(),local_left,local_right,
  118. [&] (const PrimRef& ref) { return split.mapping.bin_unsafe(ref,space,scene)[splitDim] < splitPos; },
  119. [] (CentGeomBBox3fa& pinfo,const PrimRef& ref) { pinfo.extend(ref.bounds()); },
  120. [] (CentGeomBBox3fa& pinfo0,const CentGeomBBox3fa& pinfo1) { pinfo0.merge(pinfo1); },
  121. 128);
  122. new (&lset) PrimInfoRange(begin,center,local_left.geomBounds,local_left.centBounds);
  123. new (&rset) PrimInfoRange(center,end,local_right.geomBounds,local_right.centBounds);
  124. assert(area(lset.geomBounds) >= 0.0f);
  125. assert(area(rset.geomBounds) >= 0.0f);
  126. }
  127. void deterministic_order(const range<size_t>& set)
  128. {
  129. /* required as parallel partition destroys original primitive order */
  130. std::sort(&prims[set.begin()],&prims[set.end()]);
  131. }
  132. void splitFallback(const range<size_t>& set, PrimInfoRange& lset, PrimInfoRange& rset)
  133. {
  134. const size_t begin = set.begin();
  135. const size_t end = set.end();
  136. const size_t center = (begin + end)/2;
  137. CentGeomBBox3fa left; left.reset();
  138. for (size_t i=begin; i<center; i++)
  139. left.extend(prims[i].bounds());
  140. new (&lset) PrimInfoRange(begin,center,left.geomBounds,left.centBounds);
  141. CentGeomBBox3fa right; right.reset();
  142. for (size_t i=center; i<end; i++)
  143. right.extend(prims[i].bounds());
  144. new (&rset) PrimInfoRange(center,end,right.geomBounds,right.centBounds);
  145. }
  146. private:
  147. Scene* const scene;
  148. PrimRef* const prims;
  149. };
  150. }
  151. }