3
0

BufferSystem.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  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/RHI/Factory.h>
  9. #include <Atom/RPI.Public/Buffer/BufferSystem.h>
  10. #include <Atom/RPI.Public/Buffer/Buffer.h>
  11. #include <Atom/RPI.Public/Buffer/BufferPool.h>
  12. #include <Atom/RHI/RHISystemInterface.h>
  13. #include <Atom/RPI.Reflect/Buffer/BufferAssetCreator.h>
  14. #include <Atom/RPI.Reflect/Buffer/BufferAssetView.h>
  15. #include <AtomCore/Instance/InstanceDatabase.h>
  16. #include <AzCore/Interface/Interface.h>
  17. namespace AZ
  18. {
  19. namespace RPI
  20. {
  21. void BufferSystem::Reflect(ReflectContext* context)
  22. {
  23. BufferAsset::Reflect(context);
  24. BufferAssetView::Reflect(context);
  25. }
  26. void BufferSystem::GetAssetHandlers(AssetHandlerPtrList& assetHandlers)
  27. {
  28. assetHandlers.emplace_back(MakeAssetHandler<BufferAssetHandler>());
  29. }
  30. void BufferSystem::Init(RHI::MultiDevice::DeviceMask deviceMask)
  31. {
  32. {
  33. Data::InstanceHandler<Buffer> handler;
  34. handler.m_createFunction = [](Data::AssetData* bufferAsset)
  35. {
  36. return Buffer::CreateInternal(*(azrtti_cast<BufferAsset*>(bufferAsset)));
  37. };
  38. Data::InstanceDatabase<Buffer>::Create(azrtti_typeid<BufferAsset>(), handler);
  39. }
  40. {
  41. Data::InstanceHandler<BufferPool> handler;
  42. handler.m_createFunction = [deviceMask](Data::AssetData* poolAsset)
  43. {
  44. return BufferPool::CreateInternal(deviceMask, *(azrtti_cast<ResourcePoolAsset*>(poolAsset)));
  45. };
  46. Data::InstanceDatabase<BufferPool>::Create(azrtti_typeid<ResourcePoolAsset>(), handler);
  47. }
  48. Interface<BufferSystemInterface>::Register(this);
  49. m_initialized = true;
  50. }
  51. void BufferSystem::Shutdown()
  52. {
  53. if (!m_initialized)
  54. {
  55. return;
  56. }
  57. for (uint8_t index = 0; index < static_cast<uint8_t>(CommonBufferPoolType::Count); index++)
  58. {
  59. m_commonPools[index] = nullptr;
  60. }
  61. Interface<BufferSystemInterface>::Unregister(this);
  62. Data::InstanceDatabase<Buffer>::Destroy();
  63. Data::InstanceDatabase<BufferPool>::Destroy();
  64. m_initialized = false;
  65. }
  66. RHI::Ptr<RHI::BufferPool> BufferSystem::GetCommonBufferPool(CommonBufferPoolType poolType)
  67. {
  68. const uint8_t index = static_cast<uint8_t>(poolType);
  69. if (!m_commonPools[index])
  70. {
  71. CreateCommonBufferPool(poolType);
  72. }
  73. return m_commonPools[index];
  74. }
  75. bool BufferSystem::CreateCommonBufferPool(CommonBufferPoolType poolType)
  76. {
  77. if (!m_initialized)
  78. {
  79. return false;
  80. }
  81. RHI::Ptr<RHI::BufferPool> bufferPool = aznew RHI::BufferPool;
  82. RHI::BufferPoolDescriptor bufferPoolDesc;
  83. switch (poolType)
  84. {
  85. case CommonBufferPoolType::Constant:
  86. bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::Constant;
  87. bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Device;
  88. bufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Write;
  89. break;
  90. case CommonBufferPoolType::StaticInputAssembly:
  91. bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::InputAssembly | RHI::BufferBindFlags::ShaderRead;
  92. bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Device;
  93. bufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Write;
  94. break;
  95. case CommonBufferPoolType::DynamicInputAssembly:
  96. bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::DynamicInputAssembly | RHI::BufferBindFlags::ShaderRead;
  97. bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Host;
  98. bufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Write;
  99. break;
  100. case CommonBufferPoolType::ReadBack:
  101. bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::CopyWrite;
  102. bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Host;
  103. bufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Read;
  104. break;
  105. case CommonBufferPoolType::Staging:
  106. bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::CopyRead;
  107. bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Host;
  108. bufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Write;
  109. break;
  110. case CommonBufferPoolType::ReadWrite:
  111. // Add CopyRead flag too since it's often we need to read back GPU attachment buffers.
  112. bufferPoolDesc.m_bindFlags =
  113. // [To Do] - the following line (and possibly InputAssembly / DynamicInputAssembly) will need to
  114. // be added to support future indirect buffer usage for GPU driven render pipeline
  115. // RHI::BufferBindFlags::Indirect |
  116. RHI::BufferBindFlags::ShaderWrite | RHI::BufferBindFlags::ShaderRead | RHI::BufferBindFlags::CopyRead;
  117. bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Device;
  118. bufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Write;
  119. break;
  120. case CommonBufferPoolType::ReadOnly:
  121. // [To Do] - the following line (and possibly InputAssembly / DynamicInputAssembly) will need to
  122. // be added to support future indirect buffer usage for GPU driven render pipeline
  123. bufferPoolDesc.m_bindFlags = // RHI::BufferBindFlags::Indirect |
  124. RHI::BufferBindFlags::ShaderRead;
  125. bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Device;
  126. bufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Write;
  127. break;
  128. case CommonBufferPoolType::Indirect:
  129. bufferPoolDesc.m_bindFlags = AZ::RHI::BufferBindFlags::ShaderReadWrite | AZ::RHI::BufferBindFlags::Indirect |
  130. AZ::RHI::BufferBindFlags::CopyRead | AZ::RHI::BufferBindFlags::CopyWrite;
  131. bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Device;
  132. bufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Write;
  133. break;
  134. default:
  135. AZ_Error("BufferSystem", false, "Unknown common buffer pool type: %d", poolType);
  136. return false;
  137. }
  138. bufferPool->SetName(Name(AZStd::string::format("RPI::CommonBufferPool_%i", static_cast<uint32_t>(poolType))));
  139. RHI::ResultCode resultCode = bufferPool->Init(RHI::MultiDevice::AllDevices, bufferPoolDesc);
  140. if (resultCode != RHI::ResultCode::Success)
  141. {
  142. AZ_Error("BufferSystem", false, "Failed to create buffer pool: %d", poolType);
  143. return false;
  144. }
  145. m_commonPools[static_cast<uint8_t>(poolType)] = bufferPool;
  146. return true;
  147. }
  148. Data::Instance<Buffer> BufferSystem::CreateBufferFromCommonPool(const CommonBufferDescriptor& descriptor)
  149. {
  150. AZ::Uuid bufferId;
  151. if (descriptor.m_isUniqueName)
  152. {
  153. bufferId = Uuid::CreateName(descriptor.m_bufferName);
  154. // Report error if there is a buffer with same name.
  155. // Note: this shouldn't return the existing buffer because users are expecting a newly created buffer.
  156. if (Data::InstanceDatabase<Buffer>::Instance().Find(Data::InstanceId::CreateUuid(bufferId)))
  157. {
  158. AZ_Error("BufferSystem", false, "Buffer with same name '%s' already exist", descriptor.m_bufferName.c_str());
  159. return nullptr;
  160. }
  161. }
  162. else
  163. {
  164. bufferId = Uuid::CreateRandom();
  165. }
  166. RHI::Ptr<RHI::BufferPool> bufferPool = GetCommonBufferPool(descriptor.m_poolType);
  167. if (!bufferPool)
  168. {
  169. AZ_Error("BufferSystem", false, "Common buffer pool type %d doesn't exist", descriptor.m_poolType);
  170. return nullptr;
  171. }
  172. RHI::BufferDescriptor bufferDesc;
  173. bufferDesc.m_alignment = descriptor.m_elementSize;
  174. bufferDesc.m_bindFlags = bufferPool->GetDescriptor().m_bindFlags;
  175. bufferDesc.m_byteCount = descriptor.m_byteCount;
  176. Data::Asset<BufferAsset> bufferAsset;
  177. BufferAssetCreator creator;
  178. creator.Begin(bufferId);
  179. creator.SetBufferName(descriptor.m_bufferName);
  180. creator.SetBuffer(descriptor.m_bufferData, descriptor.m_bufferData? descriptor.m_byteCount : 0, bufferDesc);
  181. creator.SetUseCommonPool(descriptor.m_poolType);
  182. RHI::BufferViewDescriptor viewDescriptor;
  183. if (descriptor.m_elementFormat != RHI::Format::Unknown)
  184. {
  185. viewDescriptor = RHI::BufferViewDescriptor::CreateTyped(
  186. 0,
  187. aznumeric_cast<uint32_t>(bufferDesc.m_byteCount / descriptor.m_elementSize),
  188. descriptor.m_elementFormat);
  189. }
  190. else
  191. {
  192. viewDescriptor = RHI::BufferViewDescriptor::CreateStructured(
  193. 0, aznumeric_cast<uint32_t>(bufferDesc.m_byteCount / descriptor.m_elementSize), descriptor.m_elementSize);
  194. }
  195. creator.SetBufferViewDescriptor(viewDescriptor);
  196. if (creator.End(bufferAsset))
  197. {
  198. return Data::InstanceDatabase<Buffer>::Instance().FindOrCreate(Data::InstanceId::CreateUuid(bufferId), bufferAsset);
  199. }
  200. return nullptr;
  201. }
  202. Data::Instance<Buffer> BufferSystem::FindCommonBuffer(AZStd::string_view uniqueBufferName)
  203. {
  204. const AZ::Uuid bufferId = Uuid::CreateName(uniqueBufferName);
  205. return Data::InstanceDatabase<Buffer>::Instance().Find(Data::InstanceId::CreateUuid(bufferId));
  206. }
  207. } // namespace RPI
  208. } // namespace AZ