DiffuseGlobalIlluminationFeatureProcessor.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  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/Serialization/SerializeContext.h>
  9. #include <Atom/RPI.Public/RPIUtils.h>
  10. #include <Atom/RPI.Public/Scene.h>
  11. #include <Atom/RPI.Public/Pass/ParentPass.h>
  12. #include <Atom/RPI.Public/Pass/PassFilter.h>
  13. #include <Atom/RPI.Public/Pass/FullscreenTrianglePass.h>
  14. #include <Render/DiffuseGlobalIlluminationFeatureProcessor.h>
  15. namespace AZ
  16. {
  17. namespace Render
  18. {
  19. void DiffuseGlobalIlluminationFeatureProcessor::Reflect(ReflectContext* context)
  20. {
  21. if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
  22. {
  23. serializeContext
  24. ->Class<DiffuseGlobalIlluminationFeatureProcessor, FeatureProcessor>()
  25. ->Version(1);
  26. }
  27. }
  28. void DiffuseGlobalIlluminationFeatureProcessor::Activate()
  29. {
  30. EnableSceneNotification();
  31. }
  32. void DiffuseGlobalIlluminationFeatureProcessor::Deactivate()
  33. {
  34. DisableSceneNotification();
  35. }
  36. void DiffuseGlobalIlluminationFeatureProcessor::SetQualityLevel(DiffuseGlobalIlluminationQualityLevel qualityLevel)
  37. {
  38. if (qualityLevel >= DiffuseGlobalIlluminationQualityLevel::Count)
  39. {
  40. AZ_Assert(false, "SetQualityLevel called with invalid quality level [%d]", qualityLevel);
  41. return;
  42. }
  43. m_qualityLevel = qualityLevel;
  44. UpdatePasses();
  45. }
  46. void DiffuseGlobalIlluminationFeatureProcessor::OnRenderPipelineChanged([[maybe_unused]] RPI::RenderPipeline* renderPipeline,
  47. RPI::SceneNotification::RenderPipelineChangeType changeType)
  48. {
  49. if (changeType == RPI::SceneNotification::RenderPipelineChangeType::Added
  50. || changeType == RPI::SceneNotification::RenderPipelineChangeType::PassChanged)
  51. {
  52. UpdatePasses();
  53. }
  54. }
  55. void DiffuseGlobalIlluminationFeatureProcessor::UpdatePasses()
  56. {
  57. float sizeMultiplier = 0.0f;
  58. switch (m_qualityLevel)
  59. {
  60. case DiffuseGlobalIlluminationQualityLevel::Low:
  61. sizeMultiplier = 0.25f;
  62. break;
  63. case DiffuseGlobalIlluminationQualityLevel::Medium:
  64. sizeMultiplier = 0.5f;
  65. break;
  66. case DiffuseGlobalIlluminationQualityLevel::High:
  67. sizeMultiplier = 1.0f;
  68. break;
  69. default:
  70. AZ_Assert(false, "Unknown DiffuseGlobalIlluminationQualityLevel [%d]", m_qualityLevel);
  71. break;
  72. }
  73. // update the size multiplier on the DiffuseProbeGridDownsamplePass output
  74. // NOTE: The ownerScene wasn't added to both filters. This is because the passes from the non-owner scene may have invalid SRG values which could lead to
  75. // GPU error if the scene doesn't have this feature processor enabled.
  76. // For example, the ASV MultiScene sample may have TDR.
  77. {
  78. AZStd::vector<Name> downsamplePassHierarchy = { Name("DiffuseGlobalIlluminationPass"), Name("DiffuseProbeGridDownsamplePass") };
  79. RPI::PassFilter downsamplePassFilter = RPI::PassFilter::CreateWithPassHierarchy(downsamplePassHierarchy);
  80. RPI::PassSystemInterface::Get()->ForEachPass(
  81. downsamplePassFilter,
  82. [sizeMultiplier](RPI::Pass* pass) -> RPI::PassFilterExecutionFlow
  83. {
  84. // update the downsample pass size multipliers
  85. for (uint32_t attachmentIndex = 0; attachmentIndex < pass->GetOutputCount(); ++attachmentIndex)
  86. {
  87. RPI::Ptr<RPI::PassAttachment> attachment = pass->GetOutputBinding(attachmentIndex).GetAttachment();
  88. if (attachment)
  89. {
  90. RPI::PassAttachmentSizeMultipliers& sizeMultipliers = attachment->m_sizeMultipliers;
  91. sizeMultipliers.m_widthMultiplier = sizeMultiplier;
  92. sizeMultipliers.m_heightMultiplier = sizeMultiplier;
  93. }
  94. }
  95. // set the output scale on the PassSrg
  96. RPI::FullscreenTrianglePass* downsamplePass = static_cast<RPI::FullscreenTrianglePass*>(pass);
  97. RHI::ShaderInputNameIndex outputImageScaleShaderInput = "m_outputImageScale";
  98. downsamplePass->GetShaderResourceGroup()->SetConstant(
  99. outputImageScaleShaderInput, aznumeric_cast<uint32_t>(1.0f / sizeMultiplier));
  100. // update the parent pass IrradianceImage size multiplier
  101. RPI::ParentPass* parentPass = pass->GetParent();
  102. RPI::Ptr<RPI::PassAttachment> irradianceImageAttachment;
  103. for (uint32_t attachmentIndex = 0; attachmentIndex < parentPass->GetInputOutputCount(); ++attachmentIndex)
  104. {
  105. RPI::Ptr<RPI::PassAttachment> attachment = parentPass->GetInputOutputBinding(attachmentIndex).GetAttachment();
  106. if (attachment && attachment->m_name == Name("IrradianceImage"))
  107. {
  108. irradianceImageAttachment = attachment;
  109. break;
  110. }
  111. }
  112. if (irradianceImageAttachment)
  113. {
  114. RPI::PassAttachmentSizeMultipliers& sizeMultipliers = irradianceImageAttachment->m_sizeMultipliers;
  115. sizeMultipliers.m_widthMultiplier = sizeMultiplier;
  116. sizeMultipliers.m_heightMultiplier = sizeMultiplier;
  117. }
  118. // handle all downsample passes
  119. return RPI::PassFilterExecutionFlow::ContinueVisitingPasses;
  120. });
  121. }
  122. // update the image scale on the DiffuseComposite pass
  123. {
  124. AZStd::vector<Name> compositePassHierarchy = { Name("DiffuseGlobalIlluminationPass"), Name("DiffuseCompositePass") };
  125. RPI::PassFilter compositePassFilter = RPI::PassFilter::CreateWithPassHierarchy(compositePassHierarchy);
  126. RPI::PassSystemInterface::Get()->ForEachPass(compositePassFilter, [sizeMultiplier](RPI::Pass* pass) -> RPI::PassFilterExecutionFlow
  127. {
  128. RPI::FullscreenTrianglePass* compositePass = static_cast<RPI::FullscreenTrianglePass*>(pass);
  129. RHI::ShaderInputNameIndex imageScaleShaderInput = "m_imageScale";
  130. compositePass->GetShaderResourceGroup()->SetConstant(imageScaleShaderInput, aznumeric_cast<uint32_t>(1.0f / sizeMultiplier));
  131. return RPI::PassFilterExecutionFlow::ContinueVisitingPasses;
  132. });
  133. }
  134. }
  135. } // namespace Render
  136. } // namespace AZ