UnifiedGeometryBuffer.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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. namespace anki {
  10. /// @addtogroup gpu_memory
  11. /// @{
  12. ANKI_CVAR(NumericCVar<PtrSize>, Core, UnifiedGeometryBufferSize, 512_MB, 16_MB, 2_GB, "Global index and vertex buffer size")
  13. /// @memberof UnifiedGeometryBuffer
  14. class UnifiedGeometryBufferAllocation
  15. {
  16. friend class UnifiedGeometryBuffer;
  17. public:
  18. UnifiedGeometryBufferAllocation() = default;
  19. UnifiedGeometryBufferAllocation(const UnifiedGeometryBufferAllocation&) = delete;
  20. UnifiedGeometryBufferAllocation(UnifiedGeometryBufferAllocation&& b)
  21. {
  22. *this = std::move(b);
  23. }
  24. ~UnifiedGeometryBufferAllocation();
  25. UnifiedGeometryBufferAllocation& operator=(const UnifiedGeometryBufferAllocation&) = delete;
  26. UnifiedGeometryBufferAllocation& operator=(UnifiedGeometryBufferAllocation&& b)
  27. {
  28. ANKI_ASSERT(!isValid() && "Forgot to delete");
  29. m_token = b.m_token;
  30. m_fakeOffset = b.m_fakeOffset;
  31. m_fakeAllocatedSize = b.m_fakeAllocatedSize;
  32. b.m_token = {};
  33. b.m_fakeAllocatedSize = 0;
  34. b.m_fakeOffset = kMaxU32;
  35. return *this;
  36. }
  37. operator BufferView() const;
  38. /// This will return an exaggerated view compared to the above that it's properly aligned.
  39. BufferView getCompleteBufferView() const;
  40. Bool isValid() const
  41. {
  42. return m_token.m_offset != kMaxPtrSize;
  43. }
  44. /// Get offset in the Unified Geometry Buffer buffer.
  45. U32 getOffset() const
  46. {
  47. ANKI_ASSERT(isValid());
  48. return m_fakeOffset;
  49. }
  50. U32 getAllocatedSize() const
  51. {
  52. ANKI_ASSERT(isValid());
  53. return m_fakeAllocatedSize;
  54. }
  55. private:
  56. SegregatedListsGpuMemoryPoolToken m_token;
  57. U32 m_fakeOffset = kMaxU32; ///< In some allocations with weird alignments we need a different offset.
  58. U32 m_fakeAllocatedSize = 0;
  59. };
  60. /// Manages vertex and index memory for the WHOLE application.
  61. class UnifiedGeometryBuffer : public MakeSingleton<UnifiedGeometryBuffer>
  62. {
  63. template<typename>
  64. friend class MakeSingleton;
  65. public:
  66. UnifiedGeometryBuffer(const UnifiedGeometryBuffer&) = delete; // Non-copyable
  67. UnifiedGeometryBuffer& operator=(const UnifiedGeometryBuffer&) = delete; // Non-copyable
  68. void init();
  69. /// The alignment doesn't need to be power of 2 unlike other allocators.
  70. UnifiedGeometryBufferAllocation allocate(PtrSize size, U32 alignment)
  71. {
  72. ANKI_ASSERT(size && alignment);
  73. const U32 fixedAlignment = max(4u, nextPowerOfTwo(alignment)); // Fix the alignment and make sure it's at least 4
  74. const U32 fixedSize = getAlignedRoundUp(4u, U32(size) + alignment); // Over-allocate and align to 4 because some cmd buffer ops need it
  75. ANKI_ASSERT(fixedSize >= size);
  76. UnifiedGeometryBufferAllocation out;
  77. m_pool.allocate(fixedSize, fixedAlignment, out.m_token);
  78. const U32 remainder = out.m_token.m_offset % alignment;
  79. out.m_fakeOffset = U32(out.m_token.m_offset + (alignment - remainder));
  80. ANKI_ASSERT(isAligned(alignment, out.m_fakeOffset));
  81. out.m_fakeAllocatedSize = U32(size);
  82. ANKI_ASSERT(PtrSize(out.m_fakeOffset) + out.m_fakeAllocatedSize <= out.m_token.m_offset + out.m_token.m_size);
  83. return out;
  84. }
  85. /// Allocate a vertex buffer.
  86. UnifiedGeometryBufferAllocation allocateFormat(Format format, U32 count)
  87. {
  88. const U32 texelSize = getFormatInfo(format).m_texelSize;
  89. return allocate(texelSize * count, texelSize);
  90. }
  91. void deferredFree(UnifiedGeometryBufferAllocation& alloc)
  92. {
  93. m_pool.deferredFree(alloc.m_token);
  94. alloc.m_fakeAllocatedSize = 0;
  95. alloc.m_fakeOffset = kMaxU32;
  96. }
  97. void endFrame()
  98. {
  99. m_pool.endFrame();
  100. #if ANKI_STATS_ENABLED
  101. updateStats();
  102. #endif
  103. }
  104. Buffer& getBuffer() const
  105. {
  106. return m_pool.getGpuBuffer();
  107. }
  108. BufferView getBufferView() const
  109. {
  110. return BufferView(&m_pool.getGpuBuffer());
  111. }
  112. private:
  113. SegregatedListsGpuMemoryPool m_pool;
  114. UnifiedGeometryBuffer() = default;
  115. ~UnifiedGeometryBuffer() = default;
  116. void updateStats() const;
  117. };
  118. inline UnifiedGeometryBufferAllocation::~UnifiedGeometryBufferAllocation()
  119. {
  120. UnifiedGeometryBuffer::getSingleton().deferredFree(*this);
  121. }
  122. inline UnifiedGeometryBufferAllocation::operator BufferView() const
  123. {
  124. return {&UnifiedGeometryBuffer::getSingleton().getBuffer(), getOffset(), getAllocatedSize()};
  125. }
  126. inline BufferView UnifiedGeometryBufferAllocation::getCompleteBufferView() const
  127. {
  128. return {&UnifiedGeometryBuffer::getSingleton().getBuffer(), m_token.m_offset, m_token.m_size};
  129. }
  130. /// @}
  131. } // end namespace anki