GpuMemoryPools.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // Copyright (C) 2009-2022, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Core/GpuMemoryPools.h>
  6. #include <AnKi/Core/ConfigSet.h>
  7. #include <AnKi/Gr/GrManager.h>
  8. #include <AnKi/Util/Tracer.h>
  9. namespace anki {
  10. VertexGpuMemoryPool::~VertexGpuMemoryPool()
  11. {
  12. // Do nothing
  13. }
  14. Error VertexGpuMemoryPool::init(GenericMemoryPoolAllocator<U8> alloc, GrManager* gr, const ConfigSet& cfg)
  15. {
  16. m_gr = gr;
  17. // Create the GPU buffer.
  18. BufferInitInfo bufferInit("Global vertex & index");
  19. bufferInit.m_size = cfg.getCoreGlobalVertexMemorySize();
  20. if(!isPowerOfTwo(bufferInit.m_size))
  21. {
  22. ANKI_CORE_LOGE("core_globalVertexMemorySize should be a power of two (because of the buddy allocator");
  23. return Error::USER_DATA;
  24. }
  25. bufferInit.m_usage = BufferUsageBit::VERTEX | BufferUsageBit::INDEX | BufferUsageBit::TRANSFER_DESTINATION;
  26. if(gr->getDeviceCapabilities().m_rayTracingEnabled)
  27. {
  28. bufferInit.m_usage |= BufferUsageBit::ACCELERATION_STRUCTURE_BUILD;
  29. }
  30. m_vertBuffer = gr->newBuffer(bufferInit);
  31. // Init the rest
  32. m_buddyAllocator.init(alloc, __builtin_ctzll(bufferInit.m_size));
  33. return Error::NONE;
  34. }
  35. Error VertexGpuMemoryPool::allocate(PtrSize size, PtrSize& offset)
  36. {
  37. U32 offset32;
  38. const Bool success = m_buddyAllocator.allocate(size, 4, offset32);
  39. if(ANKI_UNLIKELY(!success))
  40. {
  41. BuddyAllocatorBuilderStats stats;
  42. m_buddyAllocator.getStats(stats);
  43. ANKI_CORE_LOGE("Failed to allocate vertex memory of size %zu. The allocator has %zu (user requested %zu) out "
  44. "%zu allocated",
  45. size, stats.m_realAllocatedSize, stats.m_userAllocatedSize, m_vertBuffer->getSize());
  46. return Error::OUT_OF_MEMORY;
  47. }
  48. offset = offset32;
  49. return Error::NONE;
  50. }
  51. void VertexGpuMemoryPool::free(PtrSize size, PtrSize offset)
  52. {
  53. m_buddyAllocator.free(U32(offset), size, 4);
  54. }
  55. StagingGpuMemoryPool::~StagingGpuMemoryPool()
  56. {
  57. m_gr->finish();
  58. for(auto& it : m_perFrameBuffers)
  59. {
  60. it.m_buff->unmap();
  61. it.m_buff.reset(nullptr);
  62. }
  63. }
  64. Error StagingGpuMemoryPool::init(GrManager* gr, const ConfigSet& cfg)
  65. {
  66. m_gr = gr;
  67. m_perFrameBuffers[StagingGpuMemoryType::UNIFORM].m_size = cfg.getCoreUniformPerFrameMemorySize();
  68. m_perFrameBuffers[StagingGpuMemoryType::STORAGE].m_size = cfg.getCoreStoragePerFrameMemorySize();
  69. m_perFrameBuffers[StagingGpuMemoryType::VERTEX].m_size = cfg.getCoreVertexPerFrameMemorySize();
  70. m_perFrameBuffers[StagingGpuMemoryType::TEXTURE].m_size = cfg.getCoreTextureBufferPerFrameMemorySize();
  71. initBuffer(StagingGpuMemoryType::UNIFORM, gr->getDeviceCapabilities().m_uniformBufferBindOffsetAlignment,
  72. gr->getDeviceCapabilities().m_uniformBufferMaxRange, BufferUsageBit::ALL_UNIFORM, *gr);
  73. initBuffer(StagingGpuMemoryType::STORAGE,
  74. max(gr->getDeviceCapabilities().m_storageBufferBindOffsetAlignment,
  75. gr->getDeviceCapabilities().m_sbtRecordAlignment),
  76. gr->getDeviceCapabilities().m_storageBufferMaxRange, BufferUsageBit::ALL_STORAGE | BufferUsageBit::SBT,
  77. *gr);
  78. initBuffer(StagingGpuMemoryType::VERTEX, 16, MAX_U32, BufferUsageBit::VERTEX | BufferUsageBit::INDEX, *gr);
  79. initBuffer(StagingGpuMemoryType::TEXTURE, gr->getDeviceCapabilities().m_textureBufferBindOffsetAlignment,
  80. gr->getDeviceCapabilities().m_textureBufferMaxRange, BufferUsageBit::ALL_TEXTURE, *gr);
  81. return Error::NONE;
  82. }
  83. void StagingGpuMemoryPool::initBuffer(StagingGpuMemoryType type, U32 alignment, PtrSize maxAllocSize,
  84. BufferUsageBit usage, GrManager& gr)
  85. {
  86. PerFrameBuffer& perframe = m_perFrameBuffers[type];
  87. perframe.m_buff = gr.newBuffer(BufferInitInfo(perframe.m_size, usage, BufferMapAccessBit::WRITE, "Staging"));
  88. perframe.m_alloc.init(perframe.m_size, alignment, maxAllocSize);
  89. perframe.m_mappedMem = static_cast<U8*>(perframe.m_buff->map(0, perframe.m_size, BufferMapAccessBit::WRITE));
  90. }
  91. void* StagingGpuMemoryPool::allocateFrame(PtrSize size, StagingGpuMemoryType usage, StagingGpuMemoryToken& token)
  92. {
  93. PerFrameBuffer& buff = m_perFrameBuffers[usage];
  94. const Error err = buff.m_alloc.allocate(size, token.m_offset);
  95. if(err)
  96. {
  97. ANKI_CORE_LOGF("Out of staging GPU memory. Usage: %u", U32(usage));
  98. }
  99. token.m_buffer = buff.m_buff;
  100. token.m_range = size;
  101. token.m_type = usage;
  102. return buff.m_mappedMem + token.m_offset;
  103. }
  104. void* StagingGpuMemoryPool::tryAllocateFrame(PtrSize size, StagingGpuMemoryType usage, StagingGpuMemoryToken& token)
  105. {
  106. PerFrameBuffer& buff = m_perFrameBuffers[usage];
  107. const Error err = buff.m_alloc.allocate(size, token.m_offset);
  108. if(!err)
  109. {
  110. token.m_buffer = buff.m_buff;
  111. token.m_range = size;
  112. token.m_type = usage;
  113. return buff.m_mappedMem + token.m_offset;
  114. }
  115. else
  116. {
  117. token = {};
  118. return nullptr;
  119. }
  120. }
  121. void StagingGpuMemoryPool::endFrame()
  122. {
  123. for(StagingGpuMemoryType usage = StagingGpuMemoryType::UNIFORM; usage < StagingGpuMemoryType::COUNT; ++usage)
  124. {
  125. PerFrameBuffer& buff = m_perFrameBuffers[usage];
  126. if(buff.m_mappedMem)
  127. {
  128. // Increase the counters
  129. switch(usage)
  130. {
  131. case StagingGpuMemoryType::UNIFORM:
  132. ANKI_TRACE_INC_COUNTER(STAGING_UNIFORMS_SIZE, buff.m_alloc.getUnallocatedMemorySize());
  133. break;
  134. case StagingGpuMemoryType::STORAGE:
  135. ANKI_TRACE_INC_COUNTER(STAGING_STORAGE_SIZE, buff.m_alloc.getUnallocatedMemorySize());
  136. break;
  137. default:
  138. break;
  139. }
  140. buff.m_alloc.endFrame();
  141. }
  142. }
  143. }
  144. } // end namespace anki