DiffuseProbeGridBorderUpdatePass.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  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/Feature/RayTracing/RayTracingFeatureProcessorInterface.h>
  9. #include <Atom/RHI/Factory.h>
  10. #include <Atom/RHI/FrameGraphInterface.h>
  11. #include <Atom/RHI/FrameGraphAttachmentInterface.h>
  12. #include <Atom/RHI/Device.h>
  13. #include <Atom/RPI.Public/Pass/PassUtils.h>
  14. #include <Atom/RPI.Public/RenderPipeline.h>
  15. #include <Atom/RPI.Public/RPIUtils.h>
  16. #include <DiffuseProbeGrid_Traits_Platform.h>
  17. #include <Render/DiffuseProbeGridFeatureProcessor.h>
  18. #include <Render/DiffuseProbeGridBorderUpdatePass.h>
  19. namespace AZ
  20. {
  21. namespace Render
  22. {
  23. RPI::Ptr<DiffuseProbeGridBorderUpdatePass> DiffuseProbeGridBorderUpdatePass::Create(const RPI::PassDescriptor& descriptor)
  24. {
  25. RPI::Ptr<DiffuseProbeGridBorderUpdatePass> pass = aznew DiffuseProbeGridBorderUpdatePass(descriptor);
  26. return AZStd::move(pass);
  27. }
  28. DiffuseProbeGridBorderUpdatePass::DiffuseProbeGridBorderUpdatePass(const RPI::PassDescriptor& descriptor)
  29. : RPI::RenderPass(descriptor)
  30. {
  31. if (!AZ_TRAIT_DIFFUSE_GI_PASSES_SUPPORTED)
  32. {
  33. // GI is not supported on this platform
  34. SetEnabled(false);
  35. }
  36. else
  37. {
  38. LoadShader("Shaders/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdateRow.azshader",
  39. m_rowShader,
  40. m_rowPipelineState,
  41. m_rowSrgLayout,
  42. m_rowDispatchArgs);
  43. LoadShader("Shaders/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdateColumn.azshader",
  44. m_columnShader,
  45. m_columnPipelineState,
  46. m_columnSrgLayout,
  47. m_columnDispatchArgs);
  48. }
  49. }
  50. void DiffuseProbeGridBorderUpdatePass::LoadShader(AZStd::string shaderFilePath,
  51. Data::Instance<RPI::Shader>& shader,
  52. const RHI::PipelineState*& pipelineState,
  53. RHI::Ptr<RHI::ShaderResourceGroupLayout>& srgLayout,
  54. RHI::DispatchDirect& dispatchArgs)
  55. {
  56. // load shader
  57. // Note: the shader may not be available on all platforms
  58. shader = RPI::LoadCriticalShader(shaderFilePath);
  59. if (shader == nullptr)
  60. {
  61. return;
  62. }
  63. // load pipeline state
  64. RHI::PipelineStateDescriptorForDispatch pipelineStateDescriptor;
  65. const auto& shaderVariant = shader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId);
  66. shaderVariant.ConfigurePipelineState(pipelineStateDescriptor);
  67. pipelineState = shader->AcquirePipelineState(pipelineStateDescriptor);
  68. // load Pass Srg asset
  69. srgLayout = shader->FindShaderResourceGroupLayout(RPI::SrgBindingSlot::Pass);
  70. // retrieve the number of threads per thread group from the shader
  71. const auto outcome = RPI::GetComputeShaderNumThreads(shader->GetAsset(), dispatchArgs);
  72. if (!outcome.IsSuccess())
  73. {
  74. AZ_Error("PassSystem", false, "[DiffuseProbeGridBorderUpdatePass '%s']: Shader '%s' contains invalid numthreads arguments:\n%s", GetPathName().GetCStr(), shaderFilePath.c_str(), outcome.GetError().c_str());
  75. }
  76. }
  77. bool DiffuseProbeGridBorderUpdatePass::IsEnabled() const
  78. {
  79. if (!RenderPass::IsEnabled())
  80. {
  81. return false;
  82. }
  83. RPI::Scene* scene = m_pipeline->GetScene();
  84. if (!scene)
  85. {
  86. return false;
  87. }
  88. auto* rayTracingFeatureProcessor = scene->GetFeatureProcessor<RayTracingFeatureProcessorInterface>();
  89. if (!rayTracingFeatureProcessor || !rayTracingFeatureProcessor->GetSubMeshCount())
  90. {
  91. // empty scene
  92. return false;
  93. }
  94. DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
  95. if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().empty())
  96. {
  97. // no diffuse probe grids
  98. return false;
  99. }
  100. return true;
  101. }
  102. void DiffuseProbeGridBorderUpdatePass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph)
  103. {
  104. RenderPass::SetupFrameGraphDependencies(frameGraph);
  105. RPI::Scene* scene = m_pipeline->GetScene();
  106. DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
  107. // there are 4 submits per grid
  108. uint32_t totalSubmits = aznumeric_cast<uint32_t>(diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().size() * 4);
  109. frameGraph.SetEstimatedItemCount(totalSubmits);
  110. m_submitItems.reserve(totalSubmits);
  111. for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids())
  112. {
  113. // probe irradiance image
  114. {
  115. RHI::ImageScopeAttachmentDescriptor desc;
  116. desc.m_attachmentId = diffuseProbeGrid->GetIrradianceImageAttachmentId();
  117. desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeIrradianceImageViewDescriptor;
  118. desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load;
  119. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::ComputeShader);
  120. }
  121. // probe distance image
  122. {
  123. RHI::ImageScopeAttachmentDescriptor desc;
  124. desc.m_attachmentId = diffuseProbeGrid->GetDistanceImageAttachmentId();
  125. desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeDistanceImageViewDescriptor;
  126. desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load;
  127. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::ComputeShader);
  128. }
  129. }
  130. }
  131. void DiffuseProbeGridBorderUpdatePass::CompileResources([[maybe_unused]] const RHI::FrameGraphCompileContext& context)
  132. {
  133. RPI::Scene* scene = m_pipeline->GetScene();
  134. DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
  135. for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids())
  136. {
  137. // the diffuse probe grid Srg must be updated in the Compile phase in order to successfully bind the ReadWrite shader inputs
  138. // (see line ValidateSetImageView() in ShaderResourceGroupData.cpp)
  139. diffuseProbeGrid->UpdateBorderUpdateSrgs(m_rowShader, m_rowSrgLayout, m_columnShader, m_columnSrgLayout);
  140. if (!diffuseProbeGrid->GetBorderUpdateRowIrradianceSrg()->IsQueuedForCompile())
  141. {
  142. diffuseProbeGrid->GetBorderUpdateRowIrradianceSrg()->Compile();
  143. }
  144. if(!diffuseProbeGrid->GetBorderUpdateColumnIrradianceSrg()->IsQueuedForCompile())
  145. {
  146. diffuseProbeGrid->GetBorderUpdateColumnIrradianceSrg()->Compile();
  147. }
  148. if (!diffuseProbeGrid->GetBorderUpdateRowDistanceSrg()->IsQueuedForCompile())
  149. {
  150. diffuseProbeGrid->GetBorderUpdateRowDistanceSrg()->Compile();
  151. }
  152. if (!diffuseProbeGrid->GetBorderUpdateColumnDistanceSrg()->IsQueuedForCompile())
  153. {
  154. diffuseProbeGrid->GetBorderUpdateColumnDistanceSrg()->Compile();
  155. }
  156. // setup the submit items now to properly handle submitting on multiple threads
  157. uint32_t probeCountX;
  158. uint32_t probeCountY;
  159. diffuseProbeGrid->GetTexture2DProbeCount(probeCountX, probeCountY);
  160. // row irradiance
  161. {
  162. SubmitItem& submitItem = m_submitItems.emplace_back();
  163. submitItem.m_shaderResourceGroup = diffuseProbeGrid->GetBorderUpdateRowIrradianceSrg()->GetRHIShaderResourceGroup();
  164. auto arguments = m_columnDispatchArgs;
  165. arguments.m_totalNumberOfThreadsX = probeCountX * (DiffuseProbeGrid::DefaultNumIrradianceTexels + 2);
  166. arguments.m_totalNumberOfThreadsY = probeCountY;
  167. arguments.m_totalNumberOfThreadsZ = 1;
  168. submitItem.m_dispatchItem.SetPipelineState(m_rowPipelineState);
  169. submitItem.m_dispatchItem.SetArguments(arguments);
  170. }
  171. // column irradiance
  172. {
  173. SubmitItem& submitItem = m_submitItems.emplace_back();
  174. submitItem.m_shaderResourceGroup = diffuseProbeGrid->GetBorderUpdateColumnIrradianceSrg()->GetRHIShaderResourceGroup();
  175. auto arguments = m_columnDispatchArgs;
  176. arguments.m_totalNumberOfThreadsX = probeCountX;
  177. arguments.m_totalNumberOfThreadsY = probeCountY * (DiffuseProbeGrid::DefaultNumIrradianceTexels + 2);
  178. arguments.m_totalNumberOfThreadsZ = 1;
  179. submitItem.m_dispatchItem.SetPipelineState(m_columnPipelineState);
  180. submitItem.m_dispatchItem.SetArguments(arguments);
  181. }
  182. // row distance
  183. {
  184. SubmitItem& submitItem = m_submitItems.emplace_back();
  185. submitItem.m_shaderResourceGroup = diffuseProbeGrid->GetBorderUpdateRowDistanceSrg()->GetRHIShaderResourceGroup();
  186. auto arguments = m_columnDispatchArgs;
  187. arguments.m_totalNumberOfThreadsX = probeCountX * (DiffuseProbeGrid::DefaultNumDistanceTexels + 2);
  188. arguments.m_totalNumberOfThreadsY = probeCountY;
  189. arguments.m_totalNumberOfThreadsZ = 1;
  190. submitItem.m_dispatchItem.SetPipelineState(m_rowPipelineState);
  191. submitItem.m_dispatchItem.SetArguments(arguments);
  192. }
  193. // column distance
  194. {
  195. SubmitItem& submitItem = m_submitItems.emplace_back();
  196. submitItem.m_shaderResourceGroup = diffuseProbeGrid->GetBorderUpdateColumnDistanceSrg()->GetRHIShaderResourceGroup();
  197. auto arguments = m_columnDispatchArgs;
  198. arguments.m_totalNumberOfThreadsX = probeCountX;
  199. arguments.m_totalNumberOfThreadsY = probeCountY * (DiffuseProbeGrid::DefaultNumDistanceTexels + 2);
  200. arguments.m_totalNumberOfThreadsZ = 1;
  201. submitItem.m_dispatchItem.SetPipelineState(m_columnPipelineState);
  202. submitItem.m_dispatchItem.SetArguments(arguments);
  203. }
  204. }
  205. }
  206. void DiffuseProbeGridBorderUpdatePass::BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context)
  207. {
  208. RHI::CommandList* commandList = context.GetCommandList();
  209. // submit the DispatchItems for each DiffuseProbeGrid in this range
  210. uint32_t index = context.GetSubmitRange().m_startIndex;
  211. while (index < context.GetSubmitRange().m_endIndex)
  212. {
  213. SubmitItem& submitItem = m_submitItems[index];
  214. commandList->SetShaderResourceGroupForDispatch(*submitItem.m_shaderResourceGroup->GetDeviceShaderResourceGroup(context.GetDeviceIndex()));
  215. commandList->Submit(submitItem.m_dispatchItem.GetDeviceDispatchItem(context.GetDeviceIndex()), index++);
  216. }
  217. }
  218. void DiffuseProbeGridBorderUpdatePass::FrameEndInternal()
  219. {
  220. m_submitItems.clear();
  221. RenderPass::FrameEndInternal();
  222. }
  223. } // namespace Render
  224. } // namespace AZ