GpuSceneBuffer.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  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/Util/CVarSet.h>
  7. #include <AnKi/Core/StatsSet.h>
  8. #include <AnKi/Gr/Utils/SegregatedListsGpuMemoryPool.h>
  9. #include <AnKi/Resource/ShaderProgramResource.h>
  10. #include <AnKi/Gr/GrManager.h>
  11. #include <AnKi/Util/Assert.h>
  12. namespace anki {
  13. ANKI_CVAR(NumericCVar<PtrSize>, Core, GpuSceneInitialSize, 64_MB, 16_MB, 2_GB, "Global memory for the GPU scene")
  14. class GpuSceneBufferAllocation
  15. {
  16. friend class GpuSceneBuffer;
  17. public:
  18. GpuSceneBufferAllocation() = default;
  19. GpuSceneBufferAllocation(const GpuSceneBufferAllocation&) = delete;
  20. GpuSceneBufferAllocation(GpuSceneBufferAllocation&& b)
  21. {
  22. *this = std::move(b);
  23. }
  24. ~GpuSceneBufferAllocation();
  25. GpuSceneBufferAllocation& operator=(const GpuSceneBufferAllocation&) = delete;
  26. GpuSceneBufferAllocation& operator=(GpuSceneBufferAllocation&& b)
  27. {
  28. ANKI_ASSERT(!isValid() && "Forgot to delete");
  29. m_token = b.m_token;
  30. b.m_token = {};
  31. return *this;
  32. }
  33. explicit operator Bool() const
  34. {
  35. return isValid();
  36. }
  37. Bool isValid() const
  38. {
  39. return m_token.m_offset != kMaxPtrSize;
  40. }
  41. // Get offset in the Unified Geometry Buffer buffer.
  42. U32 getOffset() const
  43. {
  44. ANKI_ASSERT(isValid());
  45. return U32(m_token.m_offset);
  46. }
  47. U32 getAllocatedSize() const
  48. {
  49. ANKI_ASSERT(isValid());
  50. return U32(m_token.m_size);
  51. }
  52. private:
  53. SegregatedListsGpuMemoryPoolToken m_token;
  54. };
  55. // Memory pool for the GPU scene.
  56. class GpuSceneBuffer : public MakeSingleton<GpuSceneBuffer>
  57. {
  58. template<typename>
  59. friend class MakeSingleton;
  60. public:
  61. GpuSceneBuffer(const GpuSceneBuffer&) = delete; // Non-copyable
  62. GpuSceneBuffer& operator=(const GpuSceneBuffer&) = delete; // Non-copyable
  63. void init();
  64. GpuSceneBufferAllocation allocate(PtrSize size, U32 alignment)
  65. {
  66. GpuSceneBufferAllocation alloc;
  67. m_pool.allocate(size, alignment, alloc.m_token);
  68. return alloc;
  69. }
  70. template<typename T>
  71. GpuSceneBufferAllocation allocateStructuredBuffer(U32 count)
  72. {
  73. const U32 alignment = (GrManager::getSingleton().getDeviceCapabilities().m_structuredBufferNaturalAlignment)
  74. ? sizeof(T)
  75. : GrManager::getSingleton().getDeviceCapabilities().m_structuredBufferBindOffsetAlignment;
  76. GpuSceneBufferAllocation alloc;
  77. m_pool.allocate(count * sizeof(T), alignment, alloc.m_token);
  78. return alloc;
  79. }
  80. void deferredFree(GpuSceneBufferAllocation& alloc)
  81. {
  82. m_pool.deferredFree(alloc.m_token);
  83. }
  84. void endFrame()
  85. {
  86. m_pool.endFrame();
  87. #if ANKI_STATS_ENABLED
  88. updateStats();
  89. #endif
  90. }
  91. Buffer& getBuffer() const
  92. {
  93. return m_pool.getGpuBuffer();
  94. }
  95. BufferView getBufferView() const
  96. {
  97. return BufferView(&m_pool.getGpuBuffer());
  98. }
  99. private:
  100. SegregatedListsGpuMemoryPool m_pool;
  101. GpuSceneBuffer() = default;
  102. ~GpuSceneBuffer() = default;
  103. void updateStats() const;
  104. };
  105. inline GpuSceneBufferAllocation::~GpuSceneBufferAllocation()
  106. {
  107. GpuSceneBuffer::getSingleton().deferredFree(*this);
  108. }
  109. // Creates the copy jobs that will patch the GPU Scene.
  110. class GpuSceneMicroPatcher : public MakeSingleton<GpuSceneMicroPatcher>
  111. {
  112. template<typename>
  113. friend class MakeSingleton;
  114. public:
  115. GpuSceneMicroPatcher(const GpuSceneMicroPatcher&) = delete;
  116. GpuSceneMicroPatcher& operator=(const GpuSceneMicroPatcher&) = delete;
  117. Error init();
  118. // 1st thing to call before any calls to newCopy
  119. // Note: Not thread-safe
  120. void beginPatching();
  121. // 2nd thing to call
  122. // Copy data for the GPU scene to a staging buffer.
  123. // Note: It's thread-safe against other newCopy()
  124. void newCopy(PtrSize gpuSceneDestOffset, PtrSize dataSize, const void* data);
  125. // See newCopy
  126. template<typename T>
  127. void newCopy(PtrSize gpuSceneDestOffset, const T& value)
  128. {
  129. newCopy(gpuSceneDestOffset, sizeof(value), &value);
  130. }
  131. // See newCopy
  132. void newCopy(const GpuSceneBufferAllocation& dest, PtrSize dataSize, const void* data)
  133. {
  134. ANKI_ASSERT(dataSize <= dest.getAllocatedSize());
  135. newCopy(dest.getOffset(), dataSize, data);
  136. }
  137. // See newCopy
  138. template<typename T>
  139. void newCopy(const GpuSceneBufferAllocation& dest, const T& value)
  140. {
  141. ANKI_ASSERT(sizeof(value) <= dest.getAllocatedSize());
  142. newCopy(dest.getOffset(), sizeof(value), &value);
  143. }
  144. // 3rd thing to call after all newCopy() calls have be done
  145. // Note: Not thread-safe
  146. void endPatching()
  147. {
  148. ANKI_ASSERT(m_bPatchingMode.fetchSub(1) == 1);
  149. }
  150. // 4th optional thing to call. Check if there is a need to call patchGpuScene or if no copies are needed
  151. // Note: Not thread-safe
  152. Bool patchingIsNeeded() const
  153. {
  154. ANKI_ASSERT(m_bPatchingMode.load() == 0);
  155. return m_crntFramePatchHeaders.getSize() > 0;
  156. }
  157. // 5th thing to call to copy all scratch data to the GPU scene buffer
  158. // Note: Not thread-safe
  159. void patchGpuScene(CommandBuffer& cmdb);
  160. private:
  161. static constexpr U32 kDwordsPerPatch = 64; // If you change this change the bellow as well
  162. static constexpr U32 kDwordsPerPatchBitCount = 6;
  163. class PatchHeader;
  164. DynamicArray<PatchHeader, MemoryPoolPtrWrapper<StackMemoryPool>> m_crntFramePatchHeaders;
  165. DynamicArray<U32, MemoryPoolPtrWrapper<StackMemoryPool>> m_crntFramePatchData;
  166. Mutex m_mtx;
  167. ShaderProgramResourcePtr m_copyProgram;
  168. ShaderProgramPtr m_grProgram;
  169. StackMemoryPool m_stackMemPool;
  170. #if ANKI_ASSERTIONS_ENABLED
  171. Atomic<U32> m_bPatchingMode = {0};
  172. #endif
  173. GpuSceneMicroPatcher();
  174. ~GpuSceneMicroPatcher();
  175. };
  176. } // end namespace anki