UnifiedGeometryBuffer.h 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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. namespace anki {
  9. /// @addtogroup core
  10. /// @{
  11. /// @memberof UnifiedGeometryBuffer
  12. class UnifiedGeometryBufferAllocation
  13. {
  14. friend class UnifiedGeometryBuffer;
  15. public:
  16. UnifiedGeometryBufferAllocation() = default;
  17. UnifiedGeometryBufferAllocation(const UnifiedGeometryBufferAllocation&) = delete;
  18. UnifiedGeometryBufferAllocation(UnifiedGeometryBufferAllocation&& b)
  19. {
  20. *this = std::move(b);
  21. }
  22. ~UnifiedGeometryBufferAllocation();
  23. UnifiedGeometryBufferAllocation& operator=(const UnifiedGeometryBufferAllocation&) = delete;
  24. UnifiedGeometryBufferAllocation& operator=(UnifiedGeometryBufferAllocation&& b)
  25. {
  26. ANKI_ASSERT(!isValid() && "Forgot to delete");
  27. m_token = b.m_token;
  28. m_realOffset = b.m_realOffset;
  29. m_realAllocatedSize = b.m_realAllocatedSize;
  30. b.m_token = {};
  31. b.m_realAllocatedSize = 0;
  32. b.m_realOffset = kMaxU32;
  33. return *this;
  34. }
  35. operator BufferOffsetRange() const;
  36. Bool isValid() const
  37. {
  38. return m_token.m_offset != kMaxPtrSize;
  39. }
  40. /// Get offset in the Unified Geometry Buffer buffer.
  41. U32 getOffset() const
  42. {
  43. ANKI_ASSERT(isValid());
  44. return m_realOffset;
  45. }
  46. U32 getAllocatedSize() const
  47. {
  48. ANKI_ASSERT(isValid());
  49. return m_realAllocatedSize;
  50. }
  51. private:
  52. SegregatedListsGpuMemoryPoolToken m_token;
  53. U32 m_realOffset = kMaxU32; ///< In some allocations with weird alignments we need a different offset.
  54. U32 m_realAllocatedSize = 0;
  55. };
  56. /// Manages vertex and index memory for the WHOLE application.
  57. class UnifiedGeometryBuffer : public MakeSingleton<UnifiedGeometryBuffer>
  58. {
  59. template<typename>
  60. friend class MakeSingleton;
  61. public:
  62. UnifiedGeometryBuffer(const UnifiedGeometryBuffer&) = delete; // Non-copyable
  63. UnifiedGeometryBuffer& operator=(const UnifiedGeometryBuffer&) = delete; // Non-copyable
  64. void init();
  65. UnifiedGeometryBufferAllocation allocate(PtrSize size, U32 alignment)
  66. {
  67. UnifiedGeometryBufferAllocation out;
  68. m_pool.allocate(size, alignment, out.m_token);
  69. out.m_realOffset = U32(out.m_token.m_offset);
  70. out.m_realAllocatedSize = U32(size);
  71. return out;
  72. }
  73. /// Allocate a vertex buffer.
  74. UnifiedGeometryBufferAllocation allocateFormat(Format format, U32 count)
  75. {
  76. const U32 texelSize = getFormatInfo(format).m_texelSize;
  77. const U32 alignment = max(4u, nextPowerOfTwo(texelSize));
  78. const U32 size = count * texelSize + alignment; // Over-allocate
  79. UnifiedGeometryBufferAllocation out;
  80. m_pool.allocate(size, alignment, out.m_token);
  81. const U32 remainder = out.m_token.m_offset % texelSize;
  82. out.m_realOffset = U32(out.m_token.m_offset + (texelSize - remainder));
  83. out.m_realAllocatedSize = count * texelSize;
  84. ANKI_ASSERT(isAligned(texelSize, out.m_realOffset));
  85. ANKI_ASSERT(out.m_realOffset + out.m_realAllocatedSize <= out.m_token.m_offset + out.m_token.m_size);
  86. return out;
  87. }
  88. void deferredFree(UnifiedGeometryBufferAllocation& alloc)
  89. {
  90. m_pool.deferredFree(alloc.m_token);
  91. alloc.m_realAllocatedSize = 0;
  92. alloc.m_realOffset = kMaxU32;
  93. }
  94. void endFrame()
  95. {
  96. m_pool.endFrame();
  97. #if ANKI_STATS_ENABLED
  98. updateStats();
  99. #endif
  100. }
  101. Buffer& getBuffer() const
  102. {
  103. return m_pool.getGpuBuffer();
  104. }
  105. BufferOffsetRange getBufferOffsetRange() const
  106. {
  107. return {&m_pool.getGpuBuffer(), 0, kMaxPtrSize};
  108. }
  109. private:
  110. SegregatedListsGpuMemoryPool m_pool;
  111. UnifiedGeometryBuffer() = default;
  112. ~UnifiedGeometryBuffer() = default;
  113. void updateStats() const;
  114. };
  115. inline UnifiedGeometryBufferAllocation::~UnifiedGeometryBufferAllocation()
  116. {
  117. UnifiedGeometryBuffer::getSingleton().deferredFree(*this);
  118. }
  119. inline UnifiedGeometryBufferAllocation::operator BufferOffsetRange() const
  120. {
  121. return {&UnifiedGeometryBuffer::getSingleton().getBuffer(), getOffset(), getAllocatedSize()};
  122. }
  123. /// @}
  124. } // end namespace anki