RebarTransientMemoryPool.cpp 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  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. #include <AnKi/GpuMemory/RebarTransientMemoryPool.h>
  6. #include <AnKi/Util/Tracer.h>
  7. #include <AnKi/Gr/GrManager.h>
  8. #include <AnKi/Gr/Buffer.h>
  9. namespace anki {
  10. ANKI_SVAR(RebarUserMemory, StatCategory::kGpuMem, "ReBAR used mem", StatFlag::kBytes | StatFlag::kMainThreadUpdates)
  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 = g_cvarCoreRebarGpuMemorySize;
  22. buffInit.m_usage = BufferUsageBit::kAllConstant | BufferUsageBit::kAllUav | BufferUsageBit::kAllSrv | BufferUsageBit::kVertexOrIndex
  23. | BufferUsageBit::kShaderBindingTable | BufferUsageBit::kAllIndirect | BufferUsageBit::kCopySource
  24. | BufferUsageBit::kAccelerationStructureBuild;
  25. m_buffer = GrManager::getSingleton().newBuffer(buffInit);
  26. m_bufferSize = buffInit.m_size;
  27. if(!GrManager::getSingleton().getDeviceCapabilities().m_structuredBufferNaturalAlignment)
  28. {
  29. m_structuredBufferAlignment = GrManager::getSingleton().getDeviceCapabilities().m_structuredBufferBindOffsetAlignment;
  30. }
  31. m_mappedMem = static_cast<U8*>(m_buffer->map(0, kMaxPtrSize, BufferMapAccessBit::kWrite));
  32. }
  33. BufferView RebarTransientMemoryPool::allocateInternal(PtrSize origSize, U32 alignment, void*& mappedMem)
  34. {
  35. ANKI_ASSERT(origSize > 0);
  36. ANKI_ASSERT(alignment > 0);
  37. const PtrSize size = origSize + alignment;
  38. // Try in a loop because we may end up with an allocation its offset crosses the buffer's end
  39. PtrSize offset;
  40. Bool done = false;
  41. do
  42. {
  43. offset = m_offset.fetchAdd(size) % m_bufferSize;
  44. const PtrSize end = (offset + size) % (m_bufferSize + 1);
  45. done = offset < end;
  46. } while(!done);
  47. const PtrSize alignedOffset = getAlignedRoundUp(alignment, offset);
  48. ANKI_ASSERT(alignedOffset + origSize <= offset + size);
  49. mappedMem = m_mappedMem + alignedOffset;
  50. return BufferView(m_buffer.get(), alignedOffset, origSize);
  51. }
  52. void RebarTransientMemoryPool::endFrame()
  53. {
  54. const PtrSize crntOffset = m_offset.getNonAtomically();
  55. const PtrSize usedMemory = crntOffset - m_previousFrameEndOffset;
  56. m_previousFrameEndOffset = crntOffset;
  57. if(usedMemory >= PtrSize(0.8 * F64(m_bufferSize / kMaxFramesInFlight)))
  58. {
  59. ANKI_CORE_LOGW("Frame used more that 80%% of its safe limit of ReBAR memory");
  60. }
  61. ANKI_TRACE_INC_COUNTER(ReBarUsedMemory, usedMemory);
  62. g_svarRebarUserMemory.set(usedMemory);
  63. }
  64. } // end namespace anki