GpuSceneBuffer.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. // Copyright (C) 2009-2023, 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/Core/Common.h>
  7. #include <AnKi/Gr/Utils/SegregatedListsGpuMemoryPool.h>
  8. #include <AnKi/Resource/ShaderProgramResource.h>
  9. namespace anki {
  10. /// @addtogroup core
  11. /// @{
  12. /// @memberof GpuSceneBuffer
  13. class GpuSceneBufferAllocation
  14. {
  15. friend class GpuSceneBuffer;
  16. public:
  17. GpuSceneBufferAllocation() = default;
  18. GpuSceneBufferAllocation(const GpuSceneBufferAllocation&) = delete;
  19. GpuSceneBufferAllocation(GpuSceneBufferAllocation&& b)
  20. {
  21. *this = std::move(b);
  22. }
  23. ~GpuSceneBufferAllocation();
  24. GpuSceneBufferAllocation& operator=(const GpuSceneBufferAllocation&) = delete;
  25. GpuSceneBufferAllocation& operator=(GpuSceneBufferAllocation&& b)
  26. {
  27. ANKI_ASSERT(!isValid() && "Forgot to delete");
  28. m_token = b.m_token;
  29. b.m_token = {};
  30. return *this;
  31. }
  32. Bool isValid() const
  33. {
  34. return m_token.m_offset != kMaxPtrSize;
  35. }
  36. /// Get offset in the Unified Geometry Buffer buffer.
  37. U32 getOffset() const
  38. {
  39. ANKI_ASSERT(isValid());
  40. return U32(m_token.m_offset);
  41. }
  42. U32 getAllocatedSize() const
  43. {
  44. ANKI_ASSERT(isValid());
  45. return U32(m_token.m_size);
  46. }
  47. private:
  48. SegregatedListsGpuMemoryPoolToken m_token;
  49. };
  50. /// Memory pool for the GPU scene.
  51. class GpuSceneBuffer : public MakeSingleton<GpuSceneBuffer>
  52. {
  53. template<typename>
  54. friend class MakeSingleton;
  55. public:
  56. GpuSceneBuffer(const GpuSceneBuffer&) = delete; // Non-copyable
  57. GpuSceneBuffer& operator=(const GpuSceneBuffer&) = delete; // Non-copyable
  58. void init();
  59. GpuSceneBufferAllocation allocate(PtrSize size, U32 alignment)
  60. {
  61. GpuSceneBufferAllocation alloc;
  62. m_pool.allocate(size, alignment, alloc.m_token);
  63. return alloc;
  64. }
  65. void deferredFree(GpuSceneBufferAllocation& alloc)
  66. {
  67. m_pool.deferredFree(alloc.m_token);
  68. }
  69. void endFrame()
  70. {
  71. m_pool.endFrame();
  72. #if ANKI_STATS_ENABLED
  73. updateStats();
  74. #endif
  75. }
  76. Buffer& getBuffer() const
  77. {
  78. return m_pool.getGpuBuffer();
  79. }
  80. private:
  81. SegregatedListsGpuMemoryPool m_pool;
  82. GpuSceneBuffer() = default;
  83. ~GpuSceneBuffer() = default;
  84. void updateStats() const;
  85. };
  86. inline GpuSceneBufferAllocation::~GpuSceneBufferAllocation()
  87. {
  88. GpuSceneBuffer::getSingleton().deferredFree(*this);
  89. }
  90. /// Creates the copy jobs that will patch the GPU Scene.
  91. class GpuSceneMicroPatcher : public MakeSingleton<GpuSceneMicroPatcher>
  92. {
  93. template<typename>
  94. friend class MakeSingleton;
  95. public:
  96. GpuSceneMicroPatcher(const GpuSceneMicroPatcher&) = delete;
  97. GpuSceneMicroPatcher& operator=(const GpuSceneMicroPatcher&) = delete;
  98. Error init();
  99. /// Copy data for the GPU scene to a staging buffer.
  100. /// @note It's thread-safe.
  101. void newCopy(StackMemoryPool& frameCpuPool, PtrSize gpuSceneDestOffset, PtrSize dataSize, const void* data);
  102. template<typename T>
  103. void newCopy(StackMemoryPool& frameCpuPool, PtrSize gpuSceneDestOffset, const T& value)
  104. {
  105. newCopy(frameCpuPool, gpuSceneDestOffset, sizeof(value), &value);
  106. }
  107. /// @see newCopy
  108. void newCopy(StackMemoryPool& frameCpuPool, const GpuSceneBufferAllocation& dest, PtrSize dataSize, const void* data)
  109. {
  110. ANKI_ASSERT(dataSize <= dest.getAllocatedSize());
  111. newCopy(frameCpuPool, dest.getOffset(), dataSize, data);
  112. }
  113. /// @see newCopy
  114. template<typename T>
  115. void newCopy(StackMemoryPool& frameCpuPool, const GpuSceneBufferAllocation& dest, const T& value)
  116. {
  117. ANKI_ASSERT(sizeof(value) <= dest.getAllocatedSize());
  118. newCopy(frameCpuPool, dest.getOffset(), sizeof(value), &value);
  119. }
  120. /// Check if there is a need to call patchGpuScene or if no copies are needed.
  121. /// @note Not thread-safe. Nothing else should be happening before calling it.
  122. Bool patchingIsNeeded() const
  123. {
  124. return m_crntFramePatchHeaders.getSize() > 0;
  125. }
  126. /// Copy the data to the GPU scene buffer.
  127. /// @note Not thread-safe. Nothing else should be happening before calling it.
  128. void patchGpuScene(CommandBuffer& cmdb);
  129. private:
  130. static constexpr U32 kDwordsPerPatch = 64;
  131. class PatchHeader;
  132. DynamicArray<PatchHeader, MemoryPoolPtrWrapper<StackMemoryPool>> m_crntFramePatchHeaders;
  133. DynamicArray<U32, MemoryPoolPtrWrapper<StackMemoryPool>> m_crntFramePatchData;
  134. Mutex m_mtx;
  135. ShaderProgramResourcePtr m_copyProgram;
  136. ShaderProgramPtr m_grProgram;
  137. GpuSceneMicroPatcher();
  138. ~GpuSceneMicroPatcher();
  139. };
  140. /// @}
  141. } // end namespace anki