GpuSceneArray.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include <AnKi/Scene/Common.h>
  7. #include <AnKi/GpuMemory/GpuSceneBuffer.h>
  8. #include <AnKi/Scene/SceneGraph.h>
  9. #include <AnKi/Util/Thread.h>
  10. namespace anki {
  11. // Forward
  12. template<typename TGpuSceneObject, U32 kId>
  13. class GpuSceneArray;
  14. /// @addtogroup scene
  15. /// @{
  16. /// @memberof GpuSceneArray
  17. template<typename TGpuSceneObject, U32 kId>
  18. class GpuSceneArrayAllocation
  19. {
  20. friend class GpuSceneArray<TGpuSceneObject, kId>;
  21. public:
  22. GpuSceneArrayAllocation() = default;
  23. GpuSceneArrayAllocation(const GpuSceneArrayAllocation& b) = delete;
  24. GpuSceneArrayAllocation(GpuSceneArrayAllocation&& b)
  25. {
  26. *this = std::move(b);
  27. }
  28. ~GpuSceneArrayAllocation()
  29. {
  30. free();
  31. }
  32. GpuSceneArrayAllocation& operator=(const GpuSceneArrayAllocation&) = delete;
  33. GpuSceneArrayAllocation& operator=(GpuSceneArrayAllocation&& b)
  34. {
  35. free();
  36. m_index = b.m_index;
  37. b.invalidate();
  38. return *this;
  39. }
  40. explicit operator Bool() const
  41. {
  42. return isValid();
  43. }
  44. U32 getIndex() const
  45. {
  46. ANKI_ASSERT(isValid());
  47. return m_index;
  48. }
  49. Bool isValid() const
  50. {
  51. return m_index != kMaxU32;
  52. }
  53. /// Offset in the GPU scene.
  54. U32 getGpuSceneOffset() const;
  55. void uploadToGpuScene(const TGpuSceneObject& data) const
  56. {
  57. GpuSceneMicroPatcher::getSingleton().newCopy(getGpuSceneOffset(), data);
  58. }
  59. /// Allocate an element into the appropriate array. See GpuSceneArray::allocate()
  60. void allocate();
  61. /// Free the allocation. See GpuSceneArray::free()
  62. void free();
  63. private:
  64. U32 m_index = kMaxU32;
  65. void invalidate()
  66. {
  67. m_index = kMaxU32;
  68. }
  69. };
  70. /// Contains a number an array that hold GPU scene objects of a specific type.
  71. template<typename TGpuSceneObject, U32 kId>
  72. class GpuSceneArray : public MakeSingleton<GpuSceneArray<TGpuSceneObject, kId>>
  73. {
  74. template<typename>
  75. friend class MakeSingleton;
  76. friend class GpuSceneArrayAllocation<TGpuSceneObject, kId>;
  77. public:
  78. using Allocation = GpuSceneArrayAllocation<TGpuSceneObject, kId>;
  79. /// @note Thread-safe
  80. PtrSize getGpuSceneOffsetOfArrayBase() const
  81. {
  82. return m_gpuSceneAllocation.getOffset();
  83. }
  84. /// @note Thread-safe
  85. PtrSize getBufferRange() const
  86. {
  87. return getElementCount() * getElementSize();
  88. }
  89. /// This count contains elements that may be innactive after a free. Frees in the middle of the array will not re-arrange other elements.
  90. /// @note Thread-safe
  91. U32 getElementCount() const
  92. {
  93. LockGuard lock(m_mtx);
  94. return (m_inUseIndicesCount) ? m_maxInUseIndex + 1 : 0;
  95. }
  96. constexpr static U32 getElementSize()
  97. {
  98. return sizeof(TGpuSceneObject);
  99. }
  100. /// @note Thread-safe
  101. BufferView getBufferView() const
  102. {
  103. return {&GpuSceneBuffer::getSingleton().getBuffer(), getGpuSceneOffsetOfArrayBase(), getBufferRange()};
  104. }
  105. /// @note Thread-safe
  106. BufferView getBufferViewSafe() const
  107. {
  108. PtrSize range = getBufferRange();
  109. if(range == 0)
  110. {
  111. // Just set something
  112. range = getElementSize();
  113. }
  114. return {&GpuSceneBuffer::getSingleton().getBuffer(), getGpuSceneOffsetOfArrayBase(), range};
  115. }
  116. /// Some bookeeping. Needs to be called once per frame.
  117. /// @note Thread-safe
  118. void flush()
  119. {
  120. flushInternal(true);
  121. }
  122. private:
  123. using SubMask = BitSet<64, U64>;
  124. GpuSceneBufferAllocation m_gpuSceneAllocation;
  125. SceneDynamicArray<SubMask> m_inUseIndicesMask;
  126. U32 m_inUseIndicesCount = 0; ///< Doesn't count null elements.
  127. U32 m_maxInUseIndex = 0; ///< Counts null elements.
  128. SceneDynamicArray<U32> m_freedAllocations;
  129. mutable SpinLock m_mtx;
  130. GpuSceneArray(U32 maxArraySize);
  131. ~GpuSceneArray();
  132. void validate() const;
  133. U32 getGpuSceneOffset(const Allocation& idx) const
  134. {
  135. ANKI_ASSERT(idx.isValid());
  136. return U32(getGpuSceneOffsetOfArrayBase() + sizeof(TGpuSceneObject) * idx.m_index);
  137. }
  138. /// @note Thread-safe
  139. Allocation allocate();
  140. /// The free will not resize the array if an element is somewhere in the middle. Resizing requires moves and will also invalidate pointers.
  141. /// Instead, the freed elements will stay as a dangling stale data inside their array. Nevertheless, the class will go and nullify those elements
  142. /// so they won't take part in visibility tests.
  143. /// @note Thread-safe
  144. void free(Allocation& alloc);
  145. void flushInternal(Bool nullifyElements);
  146. };
  147. template<typename TGpuSceneObject, U32 kId>
  148. inline void GpuSceneArrayAllocation<TGpuSceneObject, kId>::free()
  149. {
  150. GpuSceneArray<TGpuSceneObject, kId>::getSingleton().free(*this);
  151. }
  152. template<typename TGpuSceneObject, U32 kId>
  153. inline void GpuSceneArrayAllocation<TGpuSceneObject, kId>::allocate()
  154. {
  155. auto newAlloc = GpuSceneArray<TGpuSceneObject, kId>::getSingleton().allocate();
  156. *this = std::move(newAlloc);
  157. }
  158. template<typename TGpuSceneObject, U32 kId>
  159. inline U32 GpuSceneArrayAllocation<TGpuSceneObject, kId>::getGpuSceneOffset() const
  160. {
  161. return GpuSceneArray<TGpuSceneObject, kId>::getSingleton().getGpuSceneOffset(*this);
  162. }
  163. class GpuSceneArrays
  164. {
  165. public:
  166. #define ANKI_CAT_TYPE(arrayName, gpuSceneType, id, cvarName) using arrayName = GpuSceneArray<gpuSceneType, id>;
  167. #include <AnKi/Scene/GpuSceneArrays.def.h>
  168. };
  169. /// @}
  170. } // end namespace anki
  171. #include <AnKi/Scene/GpuSceneArray.inl.h>