DrawPacketBuilder.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  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/LinearAllocator.h>
  9. #include <Atom/RHI/DrawPacketBuilder.h>
  10. #include <Atom/RHI/RHISystemInterface.h>
  11. #include <AzCore/Casting/numeric_cast.h>
  12. #include <AzCore/Memory/Memory.h>
  13. #include <AzCore/Memory/SystemAllocator.h>
  14. namespace AZ::RHI
  15. {
  16. DeviceDrawPacketBuilder::DeviceDrawRequest DrawPacketBuilder::DrawRequest::
  17. GetDeviceDrawRequest(int deviceIndex)
  18. {
  19. if (!m_deviceStreamBufferViews.contains(deviceIndex))
  20. {
  21. // We need to hold the memory for the single-device StreamBufferViews
  22. AZStd::vector<DeviceStreamBufferView> deviceStreamBufferView;
  23. for (auto& mdStreamBufferView : m_streamBufferViews)
  24. {
  25. deviceStreamBufferView.emplace_back(mdStreamBufferView.GetDeviceStreamBufferView(deviceIndex));
  26. }
  27. m_deviceStreamBufferViews.emplace(deviceIndex, AZStd::move(deviceStreamBufferView));
  28. }
  29. return DeviceDrawPacketBuilder::DeviceDrawRequest{
  30. m_listTag,
  31. m_stencilRef,
  32. m_deviceStreamBufferViews.at(deviceIndex),
  33. m_uniqueShaderResourceGroup ? m_uniqueShaderResourceGroup->GetDeviceShaderResourceGroup(deviceIndex).get() : nullptr,
  34. m_pipelineState ? m_pipelineState->GetDevicePipelineState(deviceIndex).get() : nullptr,
  35. m_sortKey,
  36. m_drawFilterMask };
  37. }
  38. DrawPacketBuilder::DrawPacketBuilder(const DrawPacketBuilder& other)
  39. {
  40. m_deviceMask = other.m_deviceMask;
  41. m_drawRequests = other.m_drawRequests;
  42. m_drawPacketInFlight = aznew DrawPacket;
  43. if (other.m_drawPacketInFlight)
  44. {
  45. m_drawPacketInFlight->m_drawListMask = other.m_drawPacketInFlight->m_drawListMask;
  46. }
  47. m_deviceDrawPacketBuilders = other.m_deviceDrawPacketBuilders;
  48. }
  49. DrawPacketBuilder& DrawPacketBuilder::operator=(const DrawPacketBuilder& other)
  50. {
  51. m_deviceMask = other.m_deviceMask;
  52. m_drawRequests = other.m_drawRequests;
  53. m_drawPacketInFlight = aznew DrawPacket;
  54. if (other.m_drawPacketInFlight)
  55. {
  56. m_drawPacketInFlight->m_drawListMask = other.m_drawPacketInFlight->m_drawListMask;
  57. }
  58. m_deviceDrawPacketBuilders = other.m_deviceDrawPacketBuilders;
  59. return *this;
  60. }
  61. void DrawPacketBuilder::Begin(IAllocator* allocator)
  62. {
  63. AZ_Error(
  64. "DrawPacketBuilder",
  65. m_deviceMask != MultiDevice::DeviceMask{ 0u },
  66. "DrawPacketBuilder not initialized");
  67. m_drawPacketInFlight = aznew DrawPacket;
  68. for (auto& [_, deviceDrawPacketBuilder] : m_deviceDrawPacketBuilders)
  69. {
  70. deviceDrawPacketBuilder.Begin(allocator);
  71. }
  72. }
  73. void DrawPacketBuilder::SetDrawArguments(const DrawArguments& drawArguments)
  74. {
  75. for (auto& [deviceIndex, deviceDrawPacketBuilder] : m_deviceDrawPacketBuilders)
  76. {
  77. deviceDrawPacketBuilder.SetDrawArguments(drawArguments.GetDeviceDrawArguments(deviceIndex));
  78. }
  79. }
  80. void DrawPacketBuilder::SetIndexBufferView(const IndexBufferView& indexBufferView)
  81. {
  82. for (auto& [deviceIndex, deviceDrawPacketBuilder] : m_deviceDrawPacketBuilders)
  83. {
  84. deviceDrawPacketBuilder.SetIndexBufferView(indexBufferView.GetDeviceIndexBufferView(deviceIndex));
  85. }
  86. }
  87. void DrawPacketBuilder::SetRootConstants(AZStd::span<const uint8_t> rootConstants)
  88. {
  89. for (auto& [_, deviceDrawPacketBuilder] : m_deviceDrawPacketBuilders)
  90. {
  91. deviceDrawPacketBuilder.SetRootConstants(rootConstants);
  92. }
  93. }
  94. void DrawPacketBuilder::SetScissors(AZStd::span<const Scissor> scissors)
  95. {
  96. for (auto& [_, deviceDrawPacketBuilder] : m_deviceDrawPacketBuilders)
  97. {
  98. deviceDrawPacketBuilder.SetScissors(scissors);
  99. }
  100. }
  101. void DrawPacketBuilder::SetScissor(const Scissor& scissor)
  102. {
  103. SetScissors(AZStd::span<const Scissor>(&scissor, 1));
  104. }
  105. void DrawPacketBuilder::SetViewports(AZStd::span<const Viewport> viewports)
  106. {
  107. for (auto& [_, deviceDrawPacketBuilder] : m_deviceDrawPacketBuilders)
  108. {
  109. deviceDrawPacketBuilder.SetViewports(viewports);
  110. }
  111. }
  112. void DrawPacketBuilder::SetViewport(const Viewport& viewport)
  113. {
  114. SetViewports(AZStd::span<const Viewport>(&viewport, 1));
  115. }
  116. void DrawPacketBuilder::AddShaderResourceGroup(const ShaderResourceGroup* shaderResourceGroup)
  117. {
  118. if (shaderResourceGroup)
  119. {
  120. for (auto& [deviceIndex, deviceDrawPacketBuilder] : m_deviceDrawPacketBuilders)
  121. {
  122. deviceDrawPacketBuilder.AddShaderResourceGroup(shaderResourceGroup->GetDeviceShaderResourceGroup(deviceIndex).get());
  123. }
  124. }
  125. }
  126. void DrawPacketBuilder::AddDrawItem(DrawRequest& request)
  127. {
  128. if (request.m_listTag.IsValid())
  129. {
  130. m_drawRequests.push_back(request);
  131. m_drawPacketInFlight->m_drawListMask.set(request.m_listTag.GetIndex());
  132. for (auto& [deviceIndex, deviceDrawPacketBuilder] : m_deviceDrawPacketBuilders)
  133. {
  134. deviceDrawPacketBuilder.AddDrawItem(m_drawRequests.back().GetDeviceDrawRequest(deviceIndex));
  135. }
  136. }
  137. else
  138. {
  139. AZ_Warning("DeviceDrawPacketBuilder", false, "Attempted to add a draw item to draw packet with no draw list tag assigned. Skipping.");
  140. }
  141. }
  142. RHI::Ptr<DrawPacket> DrawPacketBuilder::End()
  143. {
  144. if (m_drawRequests.empty())
  145. {
  146. return nullptr;
  147. }
  148. for (auto& [deviceIndex, deviceDrawPacketBuilder] : m_deviceDrawPacketBuilders)
  149. {
  150. m_drawPacketInFlight->m_deviceDrawPackets[deviceIndex] = deviceDrawPacketBuilder.End();
  151. }
  152. m_drawPacketInFlight->m_drawListTags.resize_no_construct(m_drawRequests.size());
  153. m_drawPacketInFlight->m_drawFilterMasks.resize_no_construct(m_drawRequests.size());
  154. m_drawPacketInFlight->m_drawItemSortKeys.resize_no_construct(m_drawRequests.size());
  155. m_drawPacketInFlight->m_drawItems.reserve(m_drawRequests.size());
  156. // Setup single-device DrawItems
  157. for (auto drawItemIndex{ 0 }; drawItemIndex < m_drawRequests.size(); ++drawItemIndex)
  158. {
  159. AZStd::unordered_map<int, DeviceDrawItem*> deviceDrawItemPtrs;
  160. for (auto& [deviceIndex, deviceDrawPacketBuilder] : m_deviceDrawPacketBuilders)
  161. {
  162. deviceDrawItemPtrs.emplace(deviceIndex, m_drawPacketInFlight->m_deviceDrawPackets[deviceIndex]->GetDrawItem(drawItemIndex));
  163. }
  164. m_drawPacketInFlight->m_drawItems.emplace_back(DrawItem{ m_deviceMask, AZStd::move(deviceDrawItemPtrs) });
  165. }
  166. const AZStd::vector<DrawListTag>& disabledTags = RHISystemInterface::Get()->GetDrawListTagsDisabledByDefault();
  167. for (size_t i = 0; i < m_drawRequests.size(); ++i)
  168. {
  169. const auto& drawRequest = m_drawRequests[i];
  170. m_drawPacketInFlight->m_drawListTags[i] = drawRequest.m_listTag;
  171. m_drawPacketInFlight->m_drawFilterMasks[i] = drawRequest.m_drawFilterMask;
  172. m_drawPacketInFlight->m_drawItemSortKeys[i] = drawRequest.m_sortKey;
  173. bool drawListTagDisabled = false;
  174. for (const DrawListTag& disabledTag : disabledTags)
  175. {
  176. drawListTagDisabled = drawListTagDisabled || (drawRequest.m_listTag == disabledTag);
  177. }
  178. auto& drawItem = m_drawPacketInFlight->m_drawItems[i];
  179. drawItem.SetEnabled(!drawListTagDisabled);
  180. }
  181. m_drawRequests.clear();
  182. return AZStd::move(m_drawPacketInFlight);
  183. }
  184. RHI::Ptr<DrawPacket> DrawPacketBuilder::Clone(const DrawPacket* original)
  185. {
  186. m_drawPacketInFlight = aznew DrawPacket;
  187. auto drawRequestCount{ original->m_drawListTags.size() };
  188. m_drawPacketInFlight->m_drawListMask = original->m_drawListMask;
  189. m_drawPacketInFlight->m_drawListTags.resize_no_construct(drawRequestCount);
  190. m_drawPacketInFlight->m_drawFilterMasks.resize_no_construct(drawRequestCount);
  191. m_drawPacketInFlight->m_drawItemSortKeys.resize_no_construct(drawRequestCount);
  192. m_drawPacketInFlight->m_drawItems.reserve(drawRequestCount);
  193. for (auto i{ 0 }; i < drawRequestCount; ++i)
  194. {
  195. m_drawPacketInFlight->m_drawListTags[i] = original->m_drawListTags[i];
  196. m_drawPacketInFlight->m_drawFilterMasks[i] = original->m_drawFilterMasks[i];
  197. m_drawPacketInFlight->m_drawItemSortKeys[i] = original->m_drawItemSortKeys[i];
  198. }
  199. for (auto& [deviceIndex, deviceDrawPacketBuilder] : m_deviceDrawPacketBuilders)
  200. {
  201. m_drawPacketInFlight->m_deviceDrawPackets[deviceIndex] =
  202. deviceDrawPacketBuilder.Clone(original->m_deviceDrawPackets.at(deviceIndex).get());
  203. }
  204. // Setup single-device DrawItems
  205. for (auto drawItemIndex{ 0 }; drawItemIndex < drawRequestCount; ++drawItemIndex)
  206. {
  207. AZStd::unordered_map<int, DeviceDrawItem*> deviceDrawItemPtrs;
  208. for (auto& [deviceIndex, deviceDrawPacketBuilder] : m_deviceDrawPacketBuilders)
  209. {
  210. deviceDrawItemPtrs.emplace(deviceIndex, m_drawPacketInFlight->m_deviceDrawPackets[deviceIndex]->GetDrawItem(drawItemIndex));
  211. }
  212. m_drawPacketInFlight->m_drawItems.emplace_back(DrawItem{ m_deviceMask, AZStd::move(deviceDrawItemPtrs) });
  213. }
  214. return AZStd::move(m_drawPacketInFlight);
  215. }
  216. } // namespace AZ::RHI