3
0

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