GpuSceneArray.h 5.1 KB

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