TransferGpuAllocator.h 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. // Copyright (C) 2009-2021, 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/Resource/Common.h>
  7. #include <AnKi/Gr/Utils/StackGpuAllocator.h>
  8. #include <AnKi/Util/List.h>
  9. namespace anki
  10. {
  11. /// @addtogroup resource
  12. /// @{
  13. /// Memory handle.
  14. class TransferGpuAllocatorHandle
  15. {
  16. friend class TransferGpuAllocator;
  17. public:
  18. TransferGpuAllocatorHandle()
  19. {
  20. }
  21. TransferGpuAllocatorHandle(const TransferGpuAllocatorHandle&) = delete;
  22. TransferGpuAllocatorHandle(TransferGpuAllocatorHandle&& b)
  23. {
  24. *this = std::move(b);
  25. }
  26. ~TransferGpuAllocatorHandle()
  27. {
  28. ANKI_ASSERT(!valid() && "Forgot to release");
  29. }
  30. TransferGpuAllocatorHandle& operator=(TransferGpuAllocatorHandle&& b)
  31. {
  32. m_handle = b.m_handle;
  33. m_range = b.m_range;
  34. m_frame = b.m_frame;
  35. b.invalidate();
  36. return *this;
  37. }
  38. BufferPtr getBuffer() const;
  39. void* getMappedMemory() const;
  40. PtrSize getOffset() const
  41. {
  42. ANKI_ASSERT(m_handle);
  43. return m_handle.m_offset;
  44. }
  45. PtrSize getRange() const
  46. {
  47. ANKI_ASSERT(m_handle);
  48. ANKI_ASSERT(m_range != 0);
  49. return m_range;
  50. }
  51. private:
  52. StackGpuAllocatorHandle m_handle;
  53. PtrSize m_range = 0;
  54. U8 m_frame = MAX_U8;
  55. Bool valid() const
  56. {
  57. return m_range != 0 && m_frame < MAX_U8;
  58. }
  59. void invalidate()
  60. {
  61. m_handle.m_memory = nullptr;
  62. m_handle.m_offset = 0;
  63. m_range = 0;
  64. m_frame = MAX_U8;
  65. }
  66. };
  67. /// GPU memory allocator for GPU buffers used in transfer operations.
  68. class TransferGpuAllocator
  69. {
  70. friend class TransferGpuAllocatorHandle;
  71. public:
  72. /// Choose an alignment that satisfies 16 bytes and 3 bytes. RGB8 formats require 3 bytes alignment for the source
  73. /// of the buffer to image copies.
  74. static constexpr U32 GPU_BUFFER_ALIGNMENT = 16 * 3;
  75. static const U32 FRAME_COUNT = 3;
  76. static const PtrSize CHUNK_INITIAL_SIZE = 64_MB;
  77. static constexpr Second MAX_FENCE_WAIT_TIME = 500.0_ms;
  78. TransferGpuAllocator();
  79. ~TransferGpuAllocator();
  80. ANKI_USE_RESULT Error init(PtrSize maxSize, GrManager* gr, ResourceAllocator<U8> alloc);
  81. /// Allocate some transfer memory. If there is not enough memory it will block until some is releaced. It's
  82. /// threadsafe.
  83. ANKI_USE_RESULT Error allocate(PtrSize size, TransferGpuAllocatorHandle& handle);
  84. /// Release the memory. It will not be recycled before the fence is signaled. It's threadsafe.
  85. void release(TransferGpuAllocatorHandle& handle, FencePtr fence);
  86. private:
  87. class Interface;
  88. class Memory;
  89. ResourceAllocator<U8> m_alloc;
  90. GrManager* m_gr = nullptr;
  91. PtrSize m_maxAllocSize = 0;
  92. UniquePtr<Interface> m_interface;
  93. class Frame
  94. {
  95. public:
  96. StackGpuAllocator m_stackAlloc;
  97. List<FencePtr> m_fences;
  98. U32 m_pendingReleases = 0;
  99. };
  100. Mutex m_mtx; ///< Protect all members bellow.
  101. ConditionVariable m_condVar;
  102. Array<Frame, FRAME_COUNT> m_frames;
  103. U8 m_frameCount = 0;
  104. PtrSize m_crntFrameAllocatedSize = 0;
  105. };
  106. /// @}
  107. } // end namespace anki