RebarTransientMemoryPool.cpp 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  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. m_buffer = GrManager::getSingleton().newBuffer(buffInit);
  25. m_bufferSize = buffInit.m_size;
  26. if(!GrManager::getSingleton().getDeviceCapabilities().m_structuredBufferNaturalAlignment)
  27. {
  28. m_structuredBufferAlignment = GrManager::getSingleton().getDeviceCapabilities().m_structuredBufferBindOffsetAlignment;
  29. }
  30. m_mappedMem = static_cast<U8*>(m_buffer->map(0, kMaxPtrSize, BufferMapAccessBit::kWrite));
  31. }
  32. BufferView RebarTransientMemoryPool::allocateInternal(PtrSize origSize, U32 alignment, void*& mappedMem)
  33. {
  34. ANKI_ASSERT(origSize > 0);
  35. ANKI_ASSERT(alignment > 0);
  36. const PtrSize size = origSize + alignment;
  37. // Try in a loop because we may end up with an allocation its offset crosses the buffer's end
  38. PtrSize offset;
  39. Bool done = false;
  40. do
  41. {
  42. offset = m_offset.fetchAdd(size) % m_bufferSize;
  43. const PtrSize end = (offset + size) % (m_bufferSize + 1);
  44. done = offset < end;
  45. } while(!done);
  46. const PtrSize alignedOffset = getAlignedRoundUp(alignment, offset);
  47. ANKI_ASSERT(alignedOffset + origSize <= offset + size);
  48. mappedMem = m_mappedMem + alignedOffset;
  49. return BufferView(m_buffer.get(), alignedOffset, origSize);
  50. }
  51. void RebarTransientMemoryPool::endFrame()
  52. {
  53. const PtrSize crntOffset = m_offset.getNonAtomically();
  54. const PtrSize usedMemory = crntOffset - m_previousFrameEndOffset;
  55. m_previousFrameEndOffset = crntOffset;
  56. if(usedMemory >= PtrSize(0.8 * F64(m_bufferSize / kMaxFramesInFlight)))
  57. {
  58. ANKI_CORE_LOGW("Frame used more that 80%% of its safe limit of ReBAR memory");
  59. }
  60. ANKI_TRACE_INC_COUNTER(ReBarUsedMemory, usedMemory);
  61. g_svarRebarUserMemory.set(usedMemory);
  62. }
  63. } // end namespace anki