GpuMemoryPools.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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. #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. ANKI_USE_RESULT Error VertexGpuMemoryPool::allocate(PtrSize size, PtrSize& offset)
  36. {
  37. U32 offset32;
  38. const Bool success = m_buddyAllocator.allocate(size, offset32);
  39. if(ANKI_UNLIKELY(!success))
  40. {
  41. ANKI_CORE_LOGE("Failed to allocate vertex memory of size: %zu", size);
  42. return Error::OUT_OF_MEMORY;
  43. }
  44. offset = offset32;
  45. return Error::NONE;
  46. }
  47. void VertexGpuMemoryPool::free(PtrSize size, PtrSize offset)
  48. {
  49. m_buddyAllocator.free(U32(offset), size);
  50. }
  51. StagingGpuMemoryPool::~StagingGpuMemoryPool()
  52. {
  53. m_gr->finish();
  54. for(auto& it : m_perFrameBuffers)
  55. {
  56. it.m_buff->unmap();
  57. it.m_buff.reset(nullptr);
  58. }
  59. }
  60. Error StagingGpuMemoryPool::init(GrManager* gr, const ConfigSet& cfg)
  61. {
  62. m_gr = gr;
  63. m_perFrameBuffers[StagingGpuMemoryType::UNIFORM].m_size = cfg.getCoreUniformPerFrameMemorySize();
  64. m_perFrameBuffers[StagingGpuMemoryType::STORAGE].m_size = cfg.getCoreStoragePerFrameMemorySize();
  65. m_perFrameBuffers[StagingGpuMemoryType::VERTEX].m_size = cfg.getCoreVertexPerFrameMemorySize();
  66. m_perFrameBuffers[StagingGpuMemoryType::TEXTURE].m_size = cfg.getCoreTextureBufferPerFrameMemorySize();
  67. initBuffer(StagingGpuMemoryType::UNIFORM, gr->getDeviceCapabilities().m_uniformBufferBindOffsetAlignment,
  68. gr->getDeviceCapabilities().m_uniformBufferMaxRange, BufferUsageBit::ALL_UNIFORM, *gr);
  69. initBuffer(StagingGpuMemoryType::STORAGE,
  70. max(gr->getDeviceCapabilities().m_storageBufferBindOffsetAlignment,
  71. gr->getDeviceCapabilities().m_sbtRecordAlignment),
  72. gr->getDeviceCapabilities().m_storageBufferMaxRange, BufferUsageBit::ALL_STORAGE | BufferUsageBit::SBT,
  73. *gr);
  74. initBuffer(StagingGpuMemoryType::VERTEX, 16, MAX_U32, BufferUsageBit::VERTEX | BufferUsageBit::INDEX, *gr);
  75. initBuffer(StagingGpuMemoryType::TEXTURE, gr->getDeviceCapabilities().m_textureBufferBindOffsetAlignment,
  76. gr->getDeviceCapabilities().m_textureBufferMaxRange, BufferUsageBit::ALL_TEXTURE, *gr);
  77. return Error::NONE;
  78. }
  79. void StagingGpuMemoryPool::initBuffer(StagingGpuMemoryType type, U32 alignment, PtrSize maxAllocSize,
  80. BufferUsageBit usage, GrManager& gr)
  81. {
  82. PerFrameBuffer& perframe = m_perFrameBuffers[type];
  83. perframe.m_buff = gr.newBuffer(BufferInitInfo(perframe.m_size, usage, BufferMapAccessBit::WRITE, "Staging"));
  84. perframe.m_alloc.init(perframe.m_size, alignment, maxAllocSize);
  85. perframe.m_mappedMem = static_cast<U8*>(perframe.m_buff->map(0, perframe.m_size, BufferMapAccessBit::WRITE));
  86. }
  87. void* StagingGpuMemoryPool::allocateFrame(PtrSize size, StagingGpuMemoryType usage, StagingGpuMemoryToken& token)
  88. {
  89. PerFrameBuffer& buff = m_perFrameBuffers[usage];
  90. const Error err = buff.m_alloc.allocate(size, token.m_offset);
  91. if(err)
  92. {
  93. ANKI_CORE_LOGF("Out of staging GPU memory. Usage: %u", U32(usage));
  94. }
  95. token.m_buffer = buff.m_buff;
  96. token.m_range = size;
  97. token.m_type = usage;
  98. return buff.m_mappedMem + token.m_offset;
  99. }
  100. void* StagingGpuMemoryPool::tryAllocateFrame(PtrSize size, StagingGpuMemoryType usage, StagingGpuMemoryToken& token)
  101. {
  102. PerFrameBuffer& buff = m_perFrameBuffers[usage];
  103. const Error err = buff.m_alloc.allocate(size, token.m_offset);
  104. if(!err)
  105. {
  106. token.m_buffer = buff.m_buff;
  107. token.m_range = size;
  108. token.m_type = usage;
  109. return buff.m_mappedMem + token.m_offset;
  110. }
  111. else
  112. {
  113. token = {};
  114. return nullptr;
  115. }
  116. }
  117. void StagingGpuMemoryPool::endFrame()
  118. {
  119. for(StagingGpuMemoryType usage = StagingGpuMemoryType::UNIFORM; usage < StagingGpuMemoryType::COUNT; ++usage)
  120. {
  121. PerFrameBuffer& buff = m_perFrameBuffers[usage];
  122. if(buff.m_mappedMem)
  123. {
  124. // Increase the counters
  125. switch(usage)
  126. {
  127. case StagingGpuMemoryType::UNIFORM:
  128. ANKI_TRACE_INC_COUNTER(STAGING_UNIFORMS_SIZE, buff.m_alloc.getUnallocatedMemorySize());
  129. break;
  130. case StagingGpuMemoryType::STORAGE:
  131. ANKI_TRACE_INC_COUNTER(STAGING_STORAGE_SIZE, buff.m_alloc.getUnallocatedMemorySize());
  132. break;
  133. default:
  134. break;
  135. }
  136. buff.m_alloc.endFrame();
  137. }
  138. }
  139. }
  140. } // end namespace anki