RebarTransientMemoryPool.cpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  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/Core/GpuMemory/RebarTransientMemoryPool.h>
  6. #include <AnKi/Core/CVarSet.h>
  7. #include <AnKi/Core/StatsSet.h>
  8. #include <AnKi/Util/Tracer.h>
  9. #include <AnKi/Gr/GrManager.h>
  10. #include <AnKi/Gr/Buffer.h>
  11. namespace anki {
  12. static StatCounter g_rebarUserMemoryStatVar(StatCategory::kGpuMem, "ReBAR used mem", StatFlag::kBytes | StatFlag::kMainThreadUpdates);
  13. static NumericCVar<PtrSize> g_rebarGpuMemorySizeCvar(CVarSubsystem::kCore, "RebarGpuMemorySize", 24_MB, 1_MB, 1_GB,
  14. "ReBAR: always mapped GPU memory");
  15. RebarTransientMemoryPool::~RebarTransientMemoryPool()
  16. {
  17. GrManager::getSingleton().finish();
  18. m_buffer->unmap();
  19. m_buffer.reset(nullptr);
  20. }
  21. void RebarTransientMemoryPool::init()
  22. {
  23. BufferInitInfo buffInit("ReBar");
  24. buffInit.m_mapAccess = BufferMapAccessBit::kWrite;
  25. buffInit.m_size = g_rebarGpuMemorySizeCvar.get();
  26. buffInit.m_usage = BufferUsageBit::kAllConstant | BufferUsageBit::kAllUav | BufferUsageBit::kAllSrv | BufferUsageBit::kVertex
  27. | BufferUsageBit::kIndex | BufferUsageBit::kShaderBindingTable | BufferUsageBit::kAllIndirect | BufferUsageBit::kCopySource;
  28. m_buffer = GrManager::getSingleton().newBuffer(buffInit);
  29. m_bufferSize = buffInit.m_size;
  30. if(!GrManager::getSingleton().getDeviceCapabilities().m_structuredBufferNaturalAlignment)
  31. {
  32. m_structuredBufferAlignment = GrManager::getSingleton().getDeviceCapabilities().m_structuredBufferBindOffsetAlignment;
  33. }
  34. m_mappedMem = static_cast<U8*>(m_buffer->map(0, kMaxPtrSize, BufferMapAccessBit::kWrite));
  35. }
  36. BufferView RebarTransientMemoryPool::allocateInternal(PtrSize origSize, U32 alignment, void*& mappedMem)
  37. {
  38. ANKI_ASSERT(origSize > 0);
  39. ANKI_ASSERT(alignment > 0);
  40. const PtrSize size = origSize + alignment;
  41. // Try in a loop because we may end up with an allocation its offset crosses the buffer's end
  42. PtrSize offset;
  43. Bool done = false;
  44. do
  45. {
  46. offset = m_offset.fetchAdd(size) % m_bufferSize;
  47. const PtrSize end = (offset + size) % (m_bufferSize + 1);
  48. done = offset < end;
  49. } while(!done);
  50. const PtrSize alignedOffset = getAlignedRoundUp(alignment, offset);
  51. ANKI_ASSERT(alignedOffset + origSize <= offset + size);
  52. mappedMem = m_mappedMem + alignedOffset;
  53. return BufferView(m_buffer.get(), alignedOffset, origSize);
  54. }
  55. void RebarTransientMemoryPool::endFrame()
  56. {
  57. const PtrSize crntOffset = m_offset.getNonAtomically();
  58. const PtrSize usedMemory = crntOffset - m_previousFrameEndOffset;
  59. m_previousFrameEndOffset = crntOffset;
  60. if(usedMemory >= PtrSize(0.8 * F64(m_bufferSize / kMaxFramesInFlight)))
  61. {
  62. ANKI_CORE_LOGW("Frame used more that 80%% of its safe limit of ReBAR memory");
  63. }
  64. ANKI_TRACE_INC_COUNTER(ReBarUsedMemory, usedMemory);
  65. g_rebarUserMemoryStatVar.set(usedMemory);
  66. }
  67. } // end namespace anki