RebarTransientMemoryPool.cpp 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  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. #include <AnKi/Core/GpuMemory/RebarTransientMemoryPool.h>
  6. #include <AnKi/Core/ConfigSet.h>
  7. #include <AnKi/Util/Tracer.h>
  8. #include <AnKi/Gr/GrManager.h>
  9. #include <AnKi/Gr/Buffer.h>
  10. namespace anki {
  11. RebarTransientMemoryPool::~RebarTransientMemoryPool()
  12. {
  13. GrManager::getSingleton().finish();
  14. m_buffer->unmap();
  15. m_buffer.reset(nullptr);
  16. }
  17. void RebarTransientMemoryPool::init()
  18. {
  19. BufferInitInfo buffInit("ReBar");
  20. buffInit.m_mapAccess = BufferMapAccessBit::kWrite;
  21. buffInit.m_size = ConfigSet::getSingleton().getCoreRebarGpuMemorySize();
  22. buffInit.m_usage = BufferUsageBit::kAllUniform | BufferUsageBit::kAllStorage | BufferUsageBit::kVertex | BufferUsageBit::kIndex
  23. | BufferUsageBit::kShaderBindingTable;
  24. m_buffer = GrManager::getSingleton().newBuffer(buffInit);
  25. m_bufferSize = buffInit.m_size;
  26. m_alignment = GrManager::getSingleton().getDeviceCapabilities().m_uniformBufferBindOffsetAlignment;
  27. m_alignment = max(m_alignment, GrManager::getSingleton().getDeviceCapabilities().m_storageBufferBindOffsetAlignment);
  28. m_alignment = max(m_alignment, GrManager::getSingleton().getDeviceCapabilities().m_sbtRecordAlignment);
  29. m_mappedMem = static_cast<U8*>(m_buffer->map(0, kMaxPtrSize, BufferMapAccessBit::kWrite));
  30. }
  31. void* RebarTransientMemoryPool::allocateFrame(PtrSize size, RebarAllocation& token)
  32. {
  33. void* address = tryAllocateFrame(size, token);
  34. if(address == nullptr) [[unlikely]]
  35. {
  36. ANKI_CORE_LOGF("Out of ReBAR GPU memory");
  37. }
  38. return address;
  39. }
  40. void* RebarTransientMemoryPool::tryAllocateFrame(PtrSize origSize, RebarAllocation& token)
  41. {
  42. const PtrSize size = getAlignedRoundUp(m_alignment, origSize);
  43. // Try in a loop because we may end up with an allocation its offset crosses the buffer's end
  44. PtrSize offset;
  45. Bool done = false;
  46. do
  47. {
  48. offset = m_offset.fetchAdd(size) % m_bufferSize;
  49. const PtrSize end = (offset + origSize) % (m_bufferSize + 1);
  50. done = offset < end;
  51. } while(!done);
  52. void* address = m_mappedMem + offset;
  53. token.m_offset = offset;
  54. token.m_range = origSize;
  55. return address;
  56. }
  57. PtrSize RebarTransientMemoryPool::endFrame()
  58. {
  59. const PtrSize crntOffset = m_offset.getNonAtomically();
  60. const PtrSize usedMemory = crntOffset - m_previousFrameEndOffset;
  61. m_previousFrameEndOffset = crntOffset;
  62. if(usedMemory >= PtrSize(0.8 * F64(m_bufferSize / kMaxFramesInFlight)))
  63. {
  64. ANKI_CORE_LOGW("Frame used more that 80%% of its safe limit of ReBAR memory");
  65. }
  66. ANKI_TRACE_INC_COUNTER(ReBarUsedMemory, usedMemory);
  67. return usedMemory;
  68. }
  69. } // end namespace anki