3
0

RasterPass.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  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/CommandList.h>
  9. #include <Atom/RHI/DrawListTagRegistry.h>
  10. #include <Atom/RHI/RHISystemInterface.h>
  11. #include <Atom/RPI.Public/DynamicDraw/DynamicDrawInterface.h>
  12. #include <Atom/RPI.Public/Pass/RasterPass.h>
  13. #include <Atom/RPI.Public/RenderPipeline.h>
  14. #include <Atom/RPI.Public/RPISystemInterface.h>
  15. #include <Atom/RPI.Public/Scene.h>
  16. #include <Atom/RPI.Public/View.h>
  17. #include <Atom/RPI.Reflect/Asset/AssetUtils.h>
  18. #include <Atom/RPI.Reflect/Pass/RasterPassData.h>
  19. namespace AZ
  20. {
  21. namespace RPI
  22. {
  23. // --- Creation & Initialization ---
  24. Ptr<RasterPass> RasterPass::Create(const PassDescriptor& descriptor)
  25. {
  26. Ptr<RasterPass> pass = aznew RasterPass(descriptor);
  27. return pass;
  28. }
  29. RasterPass::RasterPass(const PassDescriptor& descriptor)
  30. : RenderPass(descriptor)
  31. {
  32. const RasterPassData* rasterData = PassUtils::GetPassData<RasterPassData>(descriptor);
  33. // If we successfully retrieved our custom data, use it to set the DrawListTag
  34. if (rasterData == nullptr)
  35. {
  36. return;
  37. }
  38. SetDrawListTag(rasterData->m_drawListTag);
  39. m_drawListSortType = rasterData->m_drawListSortType;
  40. RHI::RHISystemInterface::Get()->SetDrawListTagEnabledByDefault(m_drawListTag, rasterData->m_enableDrawItemsByDefault);
  41. // Get the shader asset that contains the SRG Layout.
  42. Data::Asset<ShaderAsset> shaderAsset;
  43. if (rasterData->m_passSrgShaderReference.m_assetId.IsValid())
  44. {
  45. shaderAsset = AssetUtils::LoadAssetById<ShaderAsset>(rasterData->m_passSrgShaderReference.m_assetId, AssetUtils::TraceLevel::Error);
  46. }
  47. else if (!rasterData->m_passSrgShaderReference.m_filePath.empty())
  48. {
  49. shaderAsset = AssetUtils::LoadAssetByProductPath<ShaderAsset>(
  50. rasterData->m_passSrgShaderReference.m_filePath.c_str(), AssetUtils::TraceLevel::Error);
  51. }
  52. if (shaderAsset)
  53. {
  54. const auto srgLayout = shaderAsset->FindShaderResourceGroupLayout(SrgBindingSlot::Pass);
  55. if (srgLayout)
  56. {
  57. m_shaderResourceGroup = ShaderResourceGroup::Create(shaderAsset, srgLayout->GetName());
  58. AZ_Assert(
  59. m_shaderResourceGroup, "[RasterPass '%s']: Failed to create SRG from shader asset '%s'", GetPathName().GetCStr(),
  60. rasterData->m_passSrgShaderReference.m_filePath.data());
  61. PassUtils::BindDataMappingsToSrg(descriptor, m_shaderResourceGroup.get());
  62. }
  63. }
  64. if (!rasterData->m_overrideScissor.IsNull())
  65. {
  66. m_scissorState = rasterData->m_overrideScissor;
  67. m_overrideScissorSate = true;
  68. }
  69. if (!rasterData->m_overrideViewport.IsNull())
  70. {
  71. m_viewportState = rasterData->m_overrideViewport;
  72. m_overrideViewportState = true;
  73. }
  74. m_viewportAndScissorTargetOutputIndex = rasterData->m_viewportAndScissorTargetOutputIndex;
  75. }
  76. RasterPass::~RasterPass()
  77. {
  78. if (m_drawListTag != RHI::DrawListTag::Null)
  79. {
  80. RHI::RHISystemInterface* rhiSystem = RHI::RHISystemInterface::Get();
  81. rhiSystem->GetDrawListTagRegistry()->ReleaseTag(m_drawListTag);
  82. }
  83. }
  84. void RasterPass::SetDrawListTag(Name drawListName)
  85. {
  86. // Use AcquireTag to register a draw list tag if it doesn't exist.
  87. RHI::RHISystemInterface* rhiSystem = RHI::RHISystemInterface::Get();
  88. m_drawListTag = rhiSystem->GetDrawListTagRegistry()->AcquireTag(drawListName);
  89. m_flags.m_hasDrawListTag = true;
  90. }
  91. void RasterPass::SetPipelineStateDataIndex(uint32_t index)
  92. {
  93. m_pipelineStateDataIndex.m_index = index;
  94. }
  95. ShaderResourceGroup* RasterPass::GetShaderResourceGroup()
  96. {
  97. return m_shaderResourceGroup.get();
  98. }
  99. uint32_t RasterPass::GetDrawItemCount()
  100. {
  101. return m_drawItemCount;
  102. }
  103. // --- Pass behaviour overrides ---
  104. void RasterPass::Validate(PassValidationResults& validationResults)
  105. {
  106. AZ_RPI_PASS_ERROR(m_drawListTag.IsValid(), "DrawListTag for RasterPass [%s] is invalid", GetPathName().GetCStr());
  107. AZ_RPI_PASS_ERROR(!GetPipelineViewTag().IsEmpty(), "ViewTag for RasterPass [%s] is invalid", GetPathName().GetCStr());
  108. RenderPass::Validate(validationResults);
  109. }
  110. void RasterPass::FrameBeginInternal(FramePrepareParams params)
  111. {
  112. // Binding to use for viewport and scissor calculations
  113. PassAttachmentBinding* viewportTarget = nullptr;
  114. // If a target binding for viewport calculation is specified
  115. if (m_viewportAndScissorTargetOutputIndex >= 0)
  116. {
  117. u32 idx = u32(m_viewportAndScissorTargetOutputIndex);
  118. // First check outputs
  119. if (GetOutputCount() > idx)
  120. {
  121. viewportTarget = &GetOutputBinding(idx);
  122. }
  123. // If not an output, check input/outputs
  124. else if (GetInputOutputCount() > idx)
  125. {
  126. viewportTarget = &GetInputOutputBinding(idx);
  127. }
  128. }
  129. // Build viewport and scissor from target binding if specified
  130. if (viewportTarget)
  131. {
  132. u32 targetWidth = viewportTarget->GetAttachment()->m_descriptor.m_image.m_size.m_width;
  133. u32 targetHeight = viewportTarget->GetAttachment()->m_descriptor.m_image.m_size.m_height;
  134. m_scissorState = RHI::Scissor(0, 0, targetWidth, targetHeight);
  135. m_viewportState = RHI::Viewport(0, static_cast<float>(targetWidth), 0, static_cast<float>(targetHeight));
  136. }
  137. // Otherwise check whether viewport/scissor overrides were manually provided
  138. else
  139. {
  140. if (!m_overrideScissorSate)
  141. {
  142. m_scissorState = params.m_scissorState;
  143. }
  144. if (!m_overrideViewportState)
  145. {
  146. m_viewportState = params.m_viewportState;
  147. }
  148. }
  149. UpdateDrawList();
  150. RenderPass::FrameBeginInternal(params);
  151. }
  152. void RasterPass::UpdateDrawList()
  153. {
  154. // DrawLists from dynamic draw
  155. AZStd::vector<RHI::DrawListView> drawLists = DynamicDrawInterface::Get()->GetDrawListsForPass(this);
  156. // Get DrawList from view
  157. const AZStd::vector<ViewPtr>& views = m_pipeline->GetViews(GetPipelineViewTag());
  158. RHI::DrawListView viewDrawList;
  159. if (!views.empty())
  160. {
  161. const ViewPtr& view = views.front();
  162. // Draw List. May return an empty list, and that's ok.
  163. viewDrawList = view->GetDrawList(m_drawListTag);
  164. }
  165. // clean up data
  166. m_drawListView = {};
  167. m_combinedDrawList.clear();
  168. m_drawItemCount = 0;
  169. // draw list from view was sorted and if it's the only draw list then we can use it directly
  170. if (viewDrawList.size() > 0 && drawLists.size() == 0)
  171. {
  172. m_drawListView = viewDrawList;
  173. m_drawItemCount += static_cast<uint32_t>(viewDrawList.size());
  174. PassSystemInterface::Get()->IncrementFrameDrawItemCount(m_drawItemCount);
  175. return;
  176. }
  177. // add view's draw list to drawLists too
  178. drawLists.push_back(viewDrawList);
  179. // combine draw items from mutiple draw lists to one draw list and sort it.
  180. for (auto drawList : drawLists)
  181. {
  182. m_drawItemCount += static_cast<uint32_t>(drawList.size());
  183. }
  184. PassSystemInterface::Get()->IncrementFrameDrawItemCount(m_drawItemCount);
  185. m_combinedDrawList.resize(m_drawItemCount);
  186. RHI::DrawItemProperties* currentBuffer = m_combinedDrawList.data();
  187. for (auto drawList : drawLists)
  188. {
  189. memcpy(currentBuffer, drawList.data(), drawList.size()*sizeof(RHI::DrawItemProperties));
  190. currentBuffer += drawList.size();
  191. }
  192. SortDrawList(m_combinedDrawList);
  193. // have the final draw list point to the combined draw list.
  194. m_drawListView = m_combinedDrawList;
  195. }
  196. // --- DrawList and PipelineView Tags ---
  197. RHI::DrawListTag RasterPass::GetDrawListTag() const
  198. {
  199. return m_drawListTag;
  200. }
  201. // --- Scope producer functions ---
  202. void RasterPass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph)
  203. {
  204. RenderPass::SetupFrameGraphDependencies(frameGraph);
  205. frameGraph.SetEstimatedItemCount(static_cast<uint32_t>(m_drawListView.size()));
  206. }
  207. void RasterPass::CompileResources(const RHI::FrameGraphCompileContext& context)
  208. {
  209. if (m_shaderResourceGroup == nullptr)
  210. {
  211. return;
  212. }
  213. BindPassSrg(context, m_shaderResourceGroup);
  214. m_shaderResourceGroup->Compile();
  215. }
  216. void RasterPass::SubmitDrawItems(const RHI::FrameGraphExecuteContext& context, uint32_t startIndex, uint32_t endIndex, uint32_t indexOffset) const
  217. {
  218. RHI::CommandList* commandList = context.GetCommandList();
  219. uint32_t clampedEndIndex = AZStd::GetMin<uint32_t>(endIndex, static_cast<uint32_t>(m_drawListView.size()));
  220. for (uint32_t index = startIndex; index < clampedEndIndex; ++index)
  221. {
  222. const RHI::DrawItemProperties& drawItemProperties = m_drawListView[index];
  223. if (drawItemProperties.m_drawFilterMask & m_pipeline->GetDrawFilterMask())
  224. {
  225. commandList->Submit(drawItemProperties.m_Item->GetDeviceDrawItem(context.GetDeviceIndex()), index + indexOffset);
  226. }
  227. }
  228. }
  229. void RasterPass::BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context)
  230. {
  231. RHI::CommandList* commandList = context.GetCommandList();
  232. if (context.GetSubmitRange().m_startIndex != context.GetSubmitRange().m_endIndex)
  233. {
  234. commandList->SetViewport(m_viewportState);
  235. commandList->SetScissor(m_scissorState);
  236. SetSrgsForDraw(context);
  237. SubmitDrawItems(context, context.GetSubmitRange().m_startIndex, context.GetSubmitRange().m_endIndex, 0);
  238. }
  239. }
  240. } // namespace RPI
  241. } // namespace AZ