DiffuseProbeGridPreparePass.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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 <AzCore/Memory/SystemAllocator.h>
  9. #include <Atom/RHI/CommandList.h>
  10. #include <Atom/RHI/DevicePipelineState.h>
  11. #include <Atom/RHI/FrameGraphInterface.h>
  12. #include <Atom/RPI.Public/RenderPipeline.h>
  13. #include <Atom/RPI.Public/RPIUtils.h>
  14. #include <Atom/RPI.Public/Scene.h>
  15. #include <DiffuseProbeGrid_Traits_Platform.h>
  16. #include <Render/DiffuseProbeGridPreparePass.h>
  17. namespace AZ
  18. {
  19. namespace Render
  20. {
  21. constexpr AZStd::string_view DiffuseProbeGridPrepareShaderProductAssetPath =
  22. "shaders/diffuseglobalillumination/diffuseprobegridprepare.azshader";
  23. RPI::Ptr<DiffuseProbeGridPreparePass> DiffuseProbeGridPreparePass::Create(const RPI::PassDescriptor& descriptor)
  24. {
  25. RPI::Ptr<DiffuseProbeGridPreparePass> pass = aznew DiffuseProbeGridPreparePass(descriptor);
  26. return AZStd::move(pass);
  27. }
  28. DiffuseProbeGridPreparePass::DiffuseProbeGridPreparePass(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();
  39. }
  40. }
  41. void DiffuseProbeGridPreparePass::LoadShader()
  42. {
  43. // load shader
  44. // Note: the shader may not be available on all platforms
  45. m_shader = RPI::LoadCriticalShader(DiffuseProbeGridPrepareShaderProductAssetPath);
  46. if (m_shader == nullptr)
  47. {
  48. return;
  49. }
  50. // load pipeline state
  51. RHI::PipelineStateDescriptorForDispatch pipelineStateDescriptor;
  52. const auto& shaderVariant = m_shader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId);
  53. shaderVariant.ConfigurePipelineState(pipelineStateDescriptor);
  54. m_pipelineState = m_shader->AcquirePipelineState(pipelineStateDescriptor);
  55. // load Pass Srg asset
  56. m_srgLayout = m_shader->FindShaderResourceGroupLayout(RPI::SrgBindingSlot::Pass);
  57. // retrieve the number of threads per thread group from the shader
  58. const auto outcome = RPI::GetComputeShaderNumThreads(m_shader->GetAsset(), m_dispatchArgs);
  59. if (!outcome.IsSuccess())
  60. {
  61. AZ_Error("PassSystem", false,
  62. "[DiffuseProbeGridPreparePass '%s']: Shader '" AZ_STRING_FORMAT "' contains invalid numthreads arguments:\n%s",
  63. GetPathName().GetCStr(),
  64. AZ_STRING_ARG(DiffuseProbeGridPrepareShaderProductAssetPath),
  65. outcome.GetError().c_str());
  66. }
  67. }
  68. bool DiffuseProbeGridPreparePass::IsEnabled() const
  69. {
  70. if (!RenderPass::IsEnabled())
  71. {
  72. return false;
  73. }
  74. RPI::Scene* scene = m_pipeline->GetScene();
  75. if (!scene)
  76. {
  77. return false;
  78. }
  79. DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
  80. if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids().empty())
  81. {
  82. // no diffuse probe grids
  83. return false;
  84. }
  85. return true;
  86. }
  87. void DiffuseProbeGridPreparePass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph)
  88. {
  89. RenderPass::SetupFrameGraphDependencies(frameGraph);
  90. RPI::Scene* scene = m_pipeline->GetScene();
  91. DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
  92. frameGraph.SetEstimatedItemCount(aznumeric_cast<uint32_t>(diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids().size()));
  93. for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids())
  94. {
  95. // grid data buffer
  96. {
  97. [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportBuffer(diffuseProbeGrid->GetGridDataBufferAttachmentId(), diffuseProbeGrid->GetGridDataBuffer());
  98. AZ_Assert(result == RHI::ResultCode::Success, "Failed to import grid data buffer");
  99. RHI::BufferScopeAttachmentDescriptor desc;
  100. desc.m_attachmentId = diffuseProbeGrid->GetGridDataBufferAttachmentId();
  101. desc.m_bufferViewDescriptor = diffuseProbeGrid->GetRenderData()->m_gridDataBufferViewDescriptor;
  102. desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load;
  103. frameGraph.UseShaderAttachment(
  104. desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::ComputeShader);
  105. }
  106. }
  107. }
  108. void DiffuseProbeGridPreparePass::CompileResources([[maybe_unused]] const RHI::FrameGraphCompileContext& context)
  109. {
  110. RPI::Scene* scene = m_pipeline->GetScene();
  111. DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
  112. for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids())
  113. {
  114. // the diffuse probe grid Srg must be updated in the Compile phase in order to successfully bind the ReadWrite shader inputs
  115. // (see ValidateSetImageView() in ShaderResourceGroupData.cpp)
  116. diffuseProbeGrid->UpdatePrepareSrg(m_shader, m_srgLayout);
  117. if (!diffuseProbeGrid->GetPrepareSrg()->IsQueuedForCompile())
  118. {
  119. diffuseProbeGrid->GetPrepareSrg()->Compile();
  120. }
  121. }
  122. }
  123. void DiffuseProbeGridPreparePass::BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context)
  124. {
  125. RHI::CommandList* commandList = context.GetCommandList();
  126. RPI::Scene* scene = m_pipeline->GetScene();
  127. DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
  128. // submit the DispatchItems for each DiffuseProbeGrid in this range
  129. for (uint32_t index = context.GetSubmitRange().m_startIndex; index < context.GetSubmitRange().m_endIndex; ++index)
  130. {
  131. AZStd::shared_ptr<DiffuseProbeGrid> diffuseProbeGrid = diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()[index];
  132. const RHI::ShaderResourceGroup* shaderResourceGroup = diffuseProbeGrid->GetPrepareSrg()->GetRHIShaderResourceGroup();
  133. commandList->SetShaderResourceGroupForDispatch(*shaderResourceGroup->GetDeviceShaderResourceGroup(context.GetDeviceIndex()));
  134. RHI::DeviceDispatchItem dispatchItem;
  135. dispatchItem.m_arguments = m_dispatchArgs;
  136. dispatchItem.m_pipelineState = m_pipelineState->GetDevicePipelineState(context.GetDeviceIndex()).get();
  137. dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsX = 1;
  138. dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsY = 1;
  139. dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsZ = 1;
  140. commandList->Submit(dispatchItem, index);
  141. }
  142. }
  143. } // namespace Render
  144. } // namespace AZ