DiffuseProbeGridBlendIrradiancePass.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  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/DiffuseProbeGridBlendIrradiancePass.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. auto* rayTracingFeatureProcessor = scene->GetFeatureProcessor<RayTracingFeatureProcessorInterface>();
  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. // probe irradiance
  127. {
  128. RHI::ImageScopeAttachmentDescriptor desc;
  129. desc.m_attachmentId = diffuseProbeGrid->GetIrradianceImageAttachmentId();
  130. desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeIrradianceImageViewDescriptor;
  131. desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load;
  132. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::ComputeShader);
  133. }
  134. }
  135. }
  136. void DiffuseProbeGridBlendIrradiancePass::CompileResources([[maybe_unused]] const RHI::FrameGraphCompileContext& context)
  137. {
  138. RPI::Scene* scene = m_pipeline->GetScene();
  139. DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
  140. for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids())
  141. {
  142. // the diffuse probe grid Srg must be updated in the Compile phase in order to successfully bind the ReadWrite shader inputs
  143. // (see ValidateSetImageView() in ShaderResourceGroupData.cpp)
  144. DiffuseProbeGridShader& shader = m_shaders[diffuseProbeGrid->GetNumRaysPerProbe().m_index];
  145. diffuseProbeGrid->UpdateBlendIrradianceSrg(shader.m_shader, shader.m_srgLayout);
  146. if (!diffuseProbeGrid->GetBlendIrradianceSrg()->IsQueuedForCompile())
  147. {
  148. diffuseProbeGrid->GetBlendIrradianceSrg()->Compile();
  149. }
  150. }
  151. }
  152. void DiffuseProbeGridBlendIrradiancePass::BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context)
  153. {
  154. RHI::CommandList* commandList = context.GetCommandList();
  155. RPI::Scene* scene = m_pipeline->GetScene();
  156. DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
  157. // submit the DispatchItems for each DiffuseProbeGrid in this range
  158. for (uint32_t index = context.GetSubmitRange().m_startIndex; index < context.GetSubmitRange().m_endIndex; ++index)
  159. {
  160. AZStd::shared_ptr<DiffuseProbeGrid> diffuseProbeGrid = diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids()[index];
  161. DiffuseProbeGridShader& shader = m_shaders[diffuseProbeGrid->GetNumRaysPerProbe().m_index];
  162. const RHI::ShaderResourceGroup* shaderResourceGroup = diffuseProbeGrid->GetBlendIrradianceSrg()->GetRHIShaderResourceGroup();
  163. commandList->SetShaderResourceGroupForDispatch(*shaderResourceGroup->GetDeviceShaderResourceGroup(context.GetDeviceIndex()).get());
  164. uint32_t probeCountX;
  165. uint32_t probeCountY;
  166. diffuseProbeGrid->GetTexture2DProbeCount(probeCountX, probeCountY);
  167. probeCountX = AZ::DivideAndRoundUp(probeCountX, diffuseProbeGrid->GetFrameUpdateCount());
  168. RHI::DeviceDispatchItem dispatchItem;
  169. dispatchItem.m_arguments = shader.m_dispatchArgs;
  170. dispatchItem.m_pipelineState = shader.m_pipelineState->GetDevicePipelineState(context.GetDeviceIndex()).get();
  171. dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsX = probeCountX * dispatchItem.m_arguments.m_direct.m_threadsPerGroupX;
  172. dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsY = probeCountY * dispatchItem.m_arguments.m_direct.m_threadsPerGroupY;
  173. dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsZ = 1;
  174. commandList->Submit(dispatchItem, index);
  175. }
  176. }
  177. } // namespace Render
  178. } // namespace AZ