3
0

DynamicBufferAllocator.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <Atom/RPI.Public/DynamicDraw/DynamicBuffer.h>
  9. #include <Atom/RPI.Public/DynamicDraw/DynamicBufferAllocator.h>
  10. namespace AZ
  11. {
  12. namespace RPI
  13. {
  14. void DynamicBufferAllocator::Init(uint32_t ringBufferSize)
  15. {
  16. if (m_bufferData.IsCurrentBufferValid())
  17. {
  18. AZ_Assert(false, "DynamicBufferAllocator was already initialized");
  19. return;
  20. }
  21. m_ringBufferSize = ringBufferSize;
  22. for (unsigned i{ 0 }; i < m_bufferData.GetElementCount(); i++)
  23. {
  24. m_bufferData.CreateOrResizeCurrentBuffer(m_ringBufferSize);
  25. m_bufferStartAddresses.GetCurrentElement() = m_bufferData.GetCurrentElement()->Map(m_ringBufferSize, 0);
  26. m_bufferData.AdvanceCurrentElement();
  27. m_bufferStartAddresses.AdvanceCurrentElement();
  28. }
  29. }
  30. void DynamicBufferAllocator::Shutdown()
  31. {
  32. for (unsigned i{ 0 }; i < m_bufferData.GetElementCount(); i++)
  33. {
  34. m_bufferData.AdvanceCurrentElement()->Unmap();
  35. m_bufferStartAddresses.AdvanceCurrentElement().clear();
  36. }
  37. }
  38. // [GFX TODO][ATOM-13182] Add unit tests for DynamicBufferAllocator's Allocate function
  39. RHI::Ptr<DynamicBuffer> DynamicBufferAllocator::Allocate(uint32_t size, uint32_t alignment)
  40. {
  41. // m_bufferData can be invalid for Null back end
  42. if (m_bufferStartAddresses.GetCurrentElement().empty() || !m_bufferStartAddresses.GetCurrentElement().begin()->second)
  43. {
  44. return nullptr;
  45. }
  46. m_currentPosition = RHI::AlignUp(m_currentPosition, alignment);
  47. if (size > m_ringBufferSize)
  48. {
  49. AZ_WarningOnce(
  50. "RPI",
  51. !m_enableAllocationWarning,
  52. "DynamicBufferAllocator::Allocate: try to allocate buffer which size is larger than the ring buffer size");
  53. return nullptr;
  54. }
  55. // Return if the allocation of current frame has reached limit
  56. if (m_currentPosition + size > m_ringBufferSize)
  57. {
  58. AZ_WarningOnce("RPI", !m_enableAllocationWarning, "DynamicBufferAllocator::Allocate: no more buffer space is available");
  59. return nullptr;
  60. }
  61. RHI::Ptr<DynamicBuffer> allocatedBuffer = aznew DynamicBuffer();
  62. for(auto [deviceIndex, address] : m_bufferStartAddresses.GetCurrentElement())
  63. {
  64. allocatedBuffer->m_address[deviceIndex] = (uint8_t*)address + m_currentPosition;
  65. }
  66. allocatedBuffer->m_size = size;
  67. allocatedBuffer->m_allocator = this;
  68. m_currentPosition += size;
  69. return allocatedBuffer;
  70. }
  71. RHI::IndexBufferView DynamicBufferAllocator::GetIndexBufferView(RHI::Ptr<DynamicBuffer> dynamicBuffer, RHI::IndexFormat format)
  72. {
  73. return RHI::IndexBufferView(
  74. *m_bufferData.GetCurrentElement()->GetRHIBuffer(), GetBufferAddressOffset(dynamicBuffer), dynamicBuffer->m_size, format);
  75. }
  76. RHI::StreamBufferView DynamicBufferAllocator::GetStreamBufferView(RHI::Ptr<DynamicBuffer> dynamicBuffer, uint32_t strideByteCount)
  77. {
  78. return RHI::StreamBufferView(
  79. *m_bufferData.GetCurrentElement()->GetRHIBuffer(),
  80. GetBufferAddressOffset(dynamicBuffer),
  81. dynamicBuffer->m_size,
  82. strideByteCount);
  83. }
  84. uint32_t DynamicBufferAllocator::GetBufferAddressOffset(RHI::Ptr<DynamicBuffer> dynamicBuffer)
  85. {
  86. auto it = m_bufferStartAddresses.GetCurrentElement().begin();
  87. return aznumeric_cast<uint32_t>((uint8_t*)dynamicBuffer->m_address[it->first] - (uint8_t*)it->second);
  88. }
  89. void DynamicBufferAllocator::SetEnableAllocationWarning(bool enable)
  90. {
  91. m_enableAllocationWarning = enable;
  92. }
  93. void DynamicBufferAllocator::FrameEnd()
  94. {
  95. m_bufferData.AdvanceCurrentElement();
  96. m_bufferStartAddresses.AdvanceCurrentElement();
  97. m_currentPosition = 0;
  98. }
  99. } // namespace RPI
  100. } // namespace AZ