DiffuseProbeGridRenderPass.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  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/RHISystemInterface.h>
  9. #include <Atom/RPI.Public/Image/AttachmentImagePool.h>
  10. #include <Atom/RPI.Public/Image/ImageSystemInterface.h>
  11. #include <Atom/RPI.Public/RenderPipeline.h>
  12. #include <Atom/RPI.Public/RPIUtils.h>
  13. #include <DiffuseProbeGrid_Traits_Platform.h>
  14. #include <Render/DiffuseProbeGridRenderPass.h>
  15. #include <Render/DiffuseProbeGridFeatureProcessor.h>
  16. namespace AZ
  17. {
  18. namespace Render
  19. {
  20. RPI::Ptr<Render::DiffuseProbeGridRenderPass> DiffuseProbeGridRenderPass::Create(const RPI::PassDescriptor& descriptor)
  21. {
  22. return aznew DiffuseProbeGridRenderPass(descriptor);
  23. }
  24. DiffuseProbeGridRenderPass::DiffuseProbeGridRenderPass(const RPI::PassDescriptor& descriptor)
  25. : Base(descriptor)
  26. {
  27. if (!AZ_TRAIT_DIFFUSE_GI_PASSES_SUPPORTED)
  28. {
  29. // GI is not supported on this platform
  30. SetEnabled(false);
  31. return;
  32. }
  33. // create the shader resource group
  34. // Note: the shader may not be available on all platforms
  35. AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRender.azshader";
  36. m_shader = RPI::LoadCriticalShader(shaderFilePath);
  37. if (m_shader == nullptr)
  38. {
  39. return;
  40. }
  41. m_srgLayout = m_shader->FindShaderResourceGroupLayout(RPI::SrgBindingSlot::Pass);
  42. AZ_Assert(m_srgLayout != nullptr, "[DiffuseProbeGridRenderPass '%s']: Failed to find SRG layout", GetPathName().GetCStr());
  43. m_shaderResourceGroup = RPI::ShaderResourceGroup::Create(m_shader->GetAsset(), m_shader->GetSupervariantIndex(), m_srgLayout->GetName());
  44. AZ_Assert(m_shaderResourceGroup, "[DiffuseProbeGridRenderPass '%s']: Failed to create SRG", GetPathName().GetCStr());
  45. }
  46. bool DiffuseProbeGridRenderPass::IsEnabled() const
  47. {
  48. if (!RenderPass::IsEnabled())
  49. {
  50. return false;
  51. }
  52. RPI::Scene* scene = m_pipeline->GetScene();
  53. if (!scene)
  54. {
  55. return false;
  56. }
  57. DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
  58. if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetProbeGrids().empty())
  59. {
  60. // no diffuse probe grids
  61. return false;
  62. }
  63. return true;
  64. }
  65. void DiffuseProbeGridRenderPass::FrameBeginInternal(FramePrepareParams params)
  66. {
  67. RPI::Scene* scene = m_pipeline->GetScene();
  68. DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
  69. // get output attachment size
  70. AZ_Assert(GetInputOutputCount() > 0, "DiffuseProbeGridRenderPass: Could not find output bindings");
  71. RPI::PassAttachment* m_outputAttachment = GetInputOutputBinding(0).GetAttachment().get();
  72. AZ_Assert(m_outputAttachment, "DiffuseProbeGridRenderPass: Output binding has no attachment!");
  73. RHI::Size size = m_outputAttachment->m_descriptor.m_image.m_size;
  74. RHI::Viewport viewport(0.f, aznumeric_cast<float>(size.m_width), 0.f, aznumeric_cast<float>(size.m_height));
  75. RHI::Scissor scissor(0, 0, size.m_width, size.m_height);
  76. params.m_viewportState = viewport;
  77. params.m_scissorState = scissor;
  78. Base::FrameBeginInternal(params);
  79. // process attachment readback for RealTime grids, if raytracing is supported on this device
  80. if (RHI::RHISystemInterface::Get()->GetRayTracingSupport() != RHI::MultiDevice::NoDevices)
  81. {
  82. for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids())
  83. {
  84. diffuseProbeGrid->GetTextureReadback().FrameBegin(params);
  85. }
  86. }
  87. }
  88. void DiffuseProbeGridRenderPass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph)
  89. {
  90. RPI::Scene* scene = m_pipeline->GetScene();
  91. DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
  92. for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids())
  93. {
  94. if (!ShouldRender(diffuseProbeGrid))
  95. {
  96. continue;
  97. }
  98. // grid data
  99. {
  100. RHI::BufferScopeAttachmentDescriptor desc;
  101. desc.m_attachmentId = diffuseProbeGrid->GetGridDataBufferAttachmentId();
  102. desc.m_bufferViewDescriptor = diffuseProbeGrid->GetRenderData()->m_gridDataBufferViewDescriptor;
  103. desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load;
  104. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Read, RHI::ScopeAttachmentStage::FragmentShader);
  105. }
  106. // probe irradiance image
  107. {
  108. RHI::AttachmentId attachmentId = diffuseProbeGrid->GetIrradianceImageAttachmentId();
  109. if (diffuseProbeGrid->GetMode() == DiffuseProbeGridMode::Baked && !frameGraph.GetAttachmentDatabase().IsAttachmentValid(attachmentId))
  110. {
  111. // import the irradiance image now, since it is baked and therefore was not imported during the raytracing pass
  112. [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportImage(attachmentId, diffuseProbeGrid->GetIrradianceImage());
  113. AZ_Assert(result == RHI::ResultCode::Success, "Failed to import probeIrradianceImage");
  114. }
  115. RHI::ImageScopeAttachmentDescriptor desc;
  116. desc.m_attachmentId = attachmentId;
  117. desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeIrradianceImageViewDescriptor;
  118. desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load;
  119. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Read, RHI::ScopeAttachmentStage::FragmentShader);
  120. }
  121. // probe distance image
  122. {
  123. RHI::AttachmentId attachmentId = diffuseProbeGrid->GetDistanceImageAttachmentId();
  124. if (diffuseProbeGrid->GetMode() == DiffuseProbeGridMode::Baked && !frameGraph.GetAttachmentDatabase().IsAttachmentValid(attachmentId))
  125. {
  126. // import the distance image now, since it is baked and therefore was not imported during the raytracing pass
  127. [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportImage(attachmentId, diffuseProbeGrid->GetDistanceImage());
  128. AZ_Assert(result == RHI::ResultCode::Success, "Failed to import probeDistanceImage");
  129. }
  130. RHI::ImageScopeAttachmentDescriptor desc;
  131. desc.m_attachmentId = attachmentId;
  132. desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeDistanceImageViewDescriptor;
  133. desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load;
  134. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Read, RHI::ScopeAttachmentStage::FragmentShader);
  135. }
  136. // probe data image
  137. {
  138. RHI::AttachmentId attachmentId = diffuseProbeGrid->GetProbeDataImageAttachmentId();
  139. if (diffuseProbeGrid->GetMode() == DiffuseProbeGridMode::Baked && !frameGraph.GetAttachmentDatabase().IsAttachmentValid(attachmentId))
  140. {
  141. // import the probe data image now, since it is baked and therefore was not imported during the raytracing pass
  142. [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportImage(attachmentId, diffuseProbeGrid->GetProbeDataImage());
  143. AZ_Assert(result == RHI::ResultCode::Success, "Failed to import ProbeDataImage");
  144. }
  145. RHI::ImageScopeAttachmentDescriptor desc;
  146. desc.m_attachmentId = attachmentId;
  147. desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeDataImageViewDescriptor;
  148. desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load;
  149. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Read, RHI::ScopeAttachmentStage::FragmentShader);
  150. }
  151. diffuseProbeGrid->GetTextureReadback().Update(GetName());
  152. }
  153. Base::SetupFrameGraphDependencies(frameGraph);
  154. }
  155. void DiffuseProbeGridRenderPass::CompileResources(const RHI::FrameGraphCompileContext& context)
  156. {
  157. RPI::Scene* scene = m_pipeline->GetScene();
  158. DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
  159. for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids())
  160. {
  161. if (!ShouldRender(diffuseProbeGrid))
  162. {
  163. continue;
  164. }
  165. // the diffuse probe grid Srg must be updated in the Compile phase in order to successfully bind the ReadWrite shader inputs
  166. // (see ValidateSetImageView() of ShaderResourceGroupData.cpp)
  167. diffuseProbeGrid->UpdateRenderObjectSrg();
  168. if (!diffuseProbeGrid->GetRenderObjectSrg()->IsQueuedForCompile())
  169. {
  170. diffuseProbeGrid->GetRenderObjectSrg()->Compile();
  171. }
  172. }
  173. if (auto viewSRG = diffuseProbeGridFeatureProcessor->GetViewSrg(m_pipeline, GetPipelineViewTag()))
  174. {
  175. BindSrg(viewSRG->GetRHIShaderResourceGroup());
  176. }
  177. Base::CompileResources(context);
  178. }
  179. bool DiffuseProbeGridRenderPass::ShouldRender(const AZStd::shared_ptr<DiffuseProbeGrid>& diffuseProbeGrid)
  180. {
  181. // check for baked mode with no valid textures
  182. if (diffuseProbeGrid->GetMode() == DiffuseProbeGridMode::Baked &&
  183. !diffuseProbeGrid->HasValidBakedTextures())
  184. {
  185. return false;
  186. }
  187. // check for RealTime mode without ray tracing
  188. if (diffuseProbeGrid->GetMode() == DiffuseProbeGridMode::RealTime &&
  189. (RHI::RHISystemInterface::Get()->GetRayTracingSupport() == RHI::MultiDevice::NoDevices))
  190. {
  191. return false;
  192. }
  193. // check if culled out
  194. if (!diffuseProbeGrid->GetIsVisible())
  195. {
  196. return false;
  197. }
  198. // DiffuseProbeGrid should be rendered
  199. return true;
  200. }
  201. } // namespace Render
  202. } // namespace AZ