DiffuseProbeGridClassificationPass.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  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/DevicePipelineState.h>
  11. #include <Atom/RHI/FrameGraphInterface.h>
  12. #include <Atom/RHI/FrameGraphAttachmentInterface.h>
  13. #include <Atom/RHI/Device.h>
  14. #include <Atom/RPI.Public/Pass/PassUtils.h>
  15. #include <Atom/RPI.Public/RenderPipeline.h>
  16. #include <Atom/RPI.Public/RPIUtils.h>
  17. #include <Atom/RPI.Reflect/Pass/PassTemplate.h>
  18. #include <Atom/RPI.Public/View.h>
  19. #include <Atom/RPI.Public/Scene.h>
  20. #include <DiffuseProbeGrid_Traits_Platform.h>
  21. #include <Render/DiffuseProbeGridClassificationPass.h>
  22. namespace AZ
  23. {
  24. namespace Render
  25. {
  26. RPI::Ptr<DiffuseProbeGridClassificationPass> DiffuseProbeGridClassificationPass::Create(const RPI::PassDescriptor& descriptor)
  27. {
  28. RPI::Ptr<DiffuseProbeGridClassificationPass> pass = aznew DiffuseProbeGridClassificationPass(descriptor);
  29. return AZStd::move(pass);
  30. }
  31. DiffuseProbeGridClassificationPass::DiffuseProbeGridClassificationPass(const RPI::PassDescriptor& descriptor)
  32. : RPI::RenderPass(descriptor)
  33. {
  34. if (!AZ_TRAIT_DIFFUSE_GI_PASSES_SUPPORTED)
  35. {
  36. // GI is not supported on this platform
  37. SetEnabled(false);
  38. }
  39. else
  40. {
  41. LoadShader();
  42. }
  43. }
  44. void DiffuseProbeGridClassificationPass::LoadShader()
  45. {
  46. // load shaders, each supervariant handles a different number of rays per probe
  47. // Note: the raytracing shaders may not be available on all platforms
  48. m_shaders.reserve(DiffuseProbeGridNumRaysPerProbeArraySize);
  49. for (uint32_t index = 0; index < DiffuseProbeGridNumRaysPerProbeArraySize; ++index)
  50. {
  51. AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridClassification.azshader";
  52. Data::Instance<RPI::Shader> shader = RPI::LoadCriticalShader(shaderFilePath, DiffuseProbeGridNumRaysPerProbeArray[index].m_supervariant);
  53. if (shader == nullptr)
  54. {
  55. return;
  56. }
  57. RHI::PipelineStateDescriptorForDispatch pipelineStateDescriptor;
  58. const auto& shaderVariant = shader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId);
  59. shaderVariant.ConfigurePipelineState(pipelineStateDescriptor);
  60. const RHI::PipelineState* pipelineState = shader->AcquirePipelineState(pipelineStateDescriptor);
  61. AZ_Assert(pipelineState, "Failed to acquire pipeline state");
  62. RHI::Ptr<RHI::ShaderResourceGroupLayout> srgLayout = shader->FindShaderResourceGroupLayout(RPI::SrgBindingSlot::Pass);
  63. AZ_Assert(srgLayout.get(), "Failed to find Srg layout");
  64. RHI::DispatchDirect dispatchArgs;
  65. const auto outcome = RPI::GetComputeShaderNumThreads(shader->GetAsset(), dispatchArgs);
  66. if (!outcome.IsSuccess())
  67. {
  68. AZ_Error("PassSystem", false, "[DiffuseProbeBlendIrradiancePass '%s']: Shader '%s' contains invalid numthreads arguments:\n%s", GetPathName().GetCStr(), shaderFilePath.c_str(), outcome.GetError().c_str());
  69. }
  70. m_shaders.push_back({ shader, pipelineState, srgLayout, dispatchArgs });
  71. }
  72. }
  73. bool DiffuseProbeGridClassificationPass::IsEnabled() const
  74. {
  75. if (!RenderPass::IsEnabled())
  76. {
  77. return false;
  78. }
  79. RPI::Scene* scene = m_pipeline->GetScene();
  80. if (!scene)
  81. {
  82. return false;
  83. }
  84. auto* rayTracingFeatureProcessor = scene->GetFeatureProcessor<RayTracingFeatureProcessorInterface>();
  85. if (!rayTracingFeatureProcessor || !rayTracingFeatureProcessor->GetSubMeshCount())
  86. {
  87. // empty scene
  88. return false;
  89. }
  90. DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
  91. if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().empty())
  92. {
  93. // no diffuse probe grids
  94. return false;
  95. }
  96. return true;
  97. }
  98. void DiffuseProbeGridClassificationPass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph)
  99. {
  100. RenderPass::SetupFrameGraphDependencies(frameGraph);
  101. RPI::Scene* scene = m_pipeline->GetScene();
  102. DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
  103. frameGraph.SetEstimatedItemCount(aznumeric_cast<uint32_t>(diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().size()));
  104. for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids())
  105. {
  106. // grid data
  107. {
  108. RHI::BufferScopeAttachmentDescriptor desc;
  109. desc.m_attachmentId = diffuseProbeGrid->GetGridDataBufferAttachmentId();
  110. desc.m_bufferViewDescriptor = diffuseProbeGrid->GetRenderData()->m_gridDataBufferViewDescriptor;
  111. desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load;
  112. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Read, RHI::ScopeAttachmentStage::ComputeShader);
  113. }
  114. // probe raytrace image
  115. {
  116. RHI::ImageScopeAttachmentDescriptor desc;
  117. desc.m_attachmentId = diffuseProbeGrid->GetRayTraceImageAttachmentId();
  118. desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeRayTraceImageViewDescriptor;
  119. desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load;
  120. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::ComputeShader);
  121. }
  122. // probe data image
  123. {
  124. RHI::ImageScopeAttachmentDescriptor desc;
  125. desc.m_attachmentId = diffuseProbeGrid->GetProbeDataImageAttachmentId();
  126. desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeDataImageViewDescriptor;
  127. desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load;
  128. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::ComputeShader);
  129. }
  130. }
  131. }
  132. void DiffuseProbeGridClassificationPass::CompileResources([[maybe_unused]] const RHI::FrameGraphCompileContext& context)
  133. {
  134. RPI::Scene* scene = m_pipeline->GetScene();
  135. DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
  136. for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids())
  137. {
  138. // the diffuse probe grid Srg must be updated in the Compile phase in order to successfully bind the ReadWrite shader inputs
  139. // (see ValidateSetImageView() in ShaderResourceGroupData.cpp)
  140. DiffuseProbeGridShader& shader = m_shaders[diffuseProbeGrid->GetNumRaysPerProbe().m_index];
  141. diffuseProbeGrid->UpdateClassificationSrg(shader.m_shader, shader.m_srgLayout);
  142. if (!diffuseProbeGrid->GetClassificationSrg()->IsQueuedForCompile())
  143. {
  144. diffuseProbeGrid->GetClassificationSrg()->Compile();
  145. }
  146. }
  147. }
  148. void DiffuseProbeGridClassificationPass::BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context)
  149. {
  150. RHI::CommandList* commandList = context.GetCommandList();
  151. RPI::Scene* scene = m_pipeline->GetScene();
  152. DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
  153. // submit the DispatchItems for each DiffuseProbeGrid in this range
  154. for (uint32_t index = context.GetSubmitRange().m_startIndex; index < context.GetSubmitRange().m_endIndex; ++index)
  155. {
  156. AZStd::shared_ptr<DiffuseProbeGrid> diffuseProbeGrid = diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids()[index];
  157. DiffuseProbeGridShader& shader = m_shaders[diffuseProbeGrid->GetNumRaysPerProbe().m_index];
  158. const RHI::ShaderResourceGroup* shaderResourceGroup = diffuseProbeGrid->GetClassificationSrg()->GetRHIShaderResourceGroup();
  159. commandList->SetShaderResourceGroupForDispatch(*shaderResourceGroup->GetDeviceShaderResourceGroup(context.GetDeviceIndex()));
  160. RHI::DeviceDispatchItem dispatchItem;
  161. dispatchItem.m_arguments = shader.m_dispatchArgs;
  162. dispatchItem.m_pipelineState = shader.m_pipelineState->GetDevicePipelineState(context.GetDeviceIndex()).get();
  163. dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsX = AZ::DivideAndRoundUp(diffuseProbeGrid->GetTotalProbeCount(), diffuseProbeGrid->GetFrameUpdateCount());
  164. dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsY = 1;
  165. dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsZ = 1;
  166. commandList->Submit(dispatchItem, index);
  167. }
  168. }
  169. } // namespace Render
  170. } // namespace AZ