SegregatedListsGpuMemoryPool.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  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/SegregatedListsAllocatorBuilder.h>
  7. #include <AnKi/Gr/Buffer.h>
  8. namespace anki {
  9. /// @addtogroup graphics
  10. /// @{
  11. /// The result of an allocation of SegregatedListsGpuMemoryPool.
  12. /// @memberof SegregatedListsGpuMemoryPool
  13. class SegregatedListsGpuMemoryPoolToken
  14. {
  15. friend class SegregatedListsGpuMemoryPool;
  16. public:
  17. /// The offset in the SegregatedListsGpuMemoryPoolToken::getBuffer() buffer.
  18. PtrSize m_offset = kMaxPtrSize;
  19. PtrSize m_size = kMaxPtrSize;
  20. Bool operator==(const SegregatedListsGpuMemoryPoolToken& b) const
  21. {
  22. return m_offset == b.m_offset && m_chunk == b.m_chunk && m_chunkOffset == b.m_chunkOffset && m_size == b.m_size;
  23. }
  24. Bool isValid() const
  25. {
  26. return m_chunk != nullptr;
  27. }
  28. private:
  29. void* m_chunk = nullptr;
  30. PtrSize m_chunkOffset = kMaxPtrSize;
  31. };
  32. /// GPU memory allocator based on segregated lists. It allocates a GPU buffer with some initial size. If there is a need to grow it allocates a bigger
  33. /// buffer and copies contents of the old one to the new (CoW).
  34. class SegregatedListsGpuMemoryPool
  35. {
  36. public:
  37. SegregatedListsGpuMemoryPool() = default;
  38. ~SegregatedListsGpuMemoryPool()
  39. {
  40. destroy();
  41. }
  42. SegregatedListsGpuMemoryPool(const SegregatedListsGpuMemoryPool&) = delete;
  43. SegregatedListsGpuMemoryPool& operator=(const SegregatedListsGpuMemoryPool&) = delete;
  44. void init(BufferUsageBit gpuBufferUsage, ConstWeakArray<PtrSize> classUpperSizes, PtrSize initialGpuBufferSize, CString bufferName,
  45. Bool allowCoWs, BufferMapAccessBit map = BufferMapAccessBit::kNone);
  46. void destroy();
  47. /// Allocate memory.
  48. /// @note It's thread-safe.
  49. void allocate(PtrSize size, U32 alignment, SegregatedListsGpuMemoryPoolToken& token);
  50. /// Free memory a few frames down the line.
  51. /// @note It's thread-safe.
  52. void deferredFree(SegregatedListsGpuMemoryPoolToken& token);
  53. /// @note It's thread-safe.
  54. void endFrame();
  55. /// Need to be checking this constantly to get the updated buffer in case of CoWs.
  56. /// @note It's not thread-safe.
  57. Buffer& getGpuBuffer() const
  58. {
  59. ANKI_ASSERT(m_gpuBuffer.isCreated() && "The buffer hasn't been created yet");
  60. return *m_gpuBuffer;
  61. }
  62. void* getGpuBufferMappedMemory() const
  63. {
  64. ANKI_ASSERT(m_mappedGpuBufferMemory);
  65. return m_mappedGpuBufferMemory;
  66. }
  67. /// @note It's thread-safe.
  68. void getStats(F32& externalFragmentation, PtrSize& userAllocatedSize, PtrSize& totalSize) const;
  69. private:
  70. class BuilderInterface;
  71. class Chunk;
  72. using Builder = SegregatedListsAllocatorBuilder<Chunk, BuilderInterface, DummyMutex, SingletonMemoryPoolWrapper<GrMemoryPool>>;
  73. BufferUsageBit m_bufferUsage = BufferUsageBit::kNone;
  74. GrDynamicArray<PtrSize> m_classes;
  75. PtrSize m_initialBufferSize = 0;
  76. GrString m_bufferName;
  77. mutable Mutex m_lock;
  78. Builder* m_builder = nullptr;
  79. BufferPtr m_gpuBuffer;
  80. void* m_mappedGpuBufferMemory = nullptr;
  81. PtrSize m_allocatedSize = 0;
  82. GrDynamicArray<Chunk*> m_deletedChunks;
  83. Array<GrDynamicArray<SegregatedListsGpuMemoryPoolToken>, kMaxFramesInFlight> m_garbage;
  84. U8 m_frame = 0;
  85. Bool m_allowCoWs = true;
  86. BufferMapAccessBit m_mapAccess = BufferMapAccessBit::kNone;
  87. Error allocateChunk(Chunk*& newChunk, PtrSize& chunkSize);
  88. void deleteChunk(Chunk* chunk);
  89. Bool isInitialized() const
  90. {
  91. return m_bufferUsage != BufferUsageBit::kNone;
  92. }
  93. };
  94. /// @}
  95. } // end namespace anki