BloomCompositePass.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  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 <PostProcessing/BloomCompositePass.h>
  9. #include <PostProcess/Bloom/BloomSettings.h>
  10. #include <PostProcess/PostProcessFeatureProcessor.h>
  11. #include <Atom/RHI/CommandList.h>
  12. #include <Atom/RHI/Factory.h>
  13. #include <Atom/RHI/FrameScheduler.h>
  14. #include <Atom/RPI.Reflect/Pass/PassTemplate.h>
  15. #include <Atom/RPI.Public/Pass/PassUtils.h>
  16. #include <Atom/RPI.Public/Pass/PassAttachment.h>
  17. #include <Atom/RPI.Public/RPIUtils.h>
  18. #include <Atom/RPI.Public/Scene.h>
  19. #include <Atom/RPI.Public/RenderPipeline.h>
  20. #include <Atom/RPI.Public/View.h>
  21. #include <Atom/RPI.Public/RPISystemInterface.h>
  22. #include <Atom/RPI.Public/Shader/ShaderResourceGroup.h>
  23. #include <Atom/RPI.Reflect/Pass/ComputePassData.h>
  24. namespace AZ
  25. {
  26. namespace Render
  27. {
  28. RPI::Ptr<BloomCompositePass> BloomCompositePass::Create(const RPI::PassDescriptor& descriptor)
  29. {
  30. RPI::Ptr<BloomCompositePass> pass = aznew BloomCompositePass(descriptor);
  31. return AZStd::move(pass);
  32. }
  33. BloomCompositePass::BloomCompositePass(const RPI::PassDescriptor& descriptor)
  34. : ParentPass(descriptor)
  35. {
  36. // Load DownsampleMipChainPassData (shader asset)
  37. const RPI::DownsampleMipChainPassData* passData = RPI::PassUtils::GetPassData<RPI::DownsampleMipChainPassData>(descriptor);
  38. if (passData == nullptr)
  39. {
  40. AZ_Error("PassSystem", false, "[BloomCompositePass '%s']: Trying to construct without valid DownsampleMipChainPassData!",
  41. GetPathName().GetCStr());
  42. return;
  43. }
  44. m_passData = *passData;
  45. }
  46. void BloomCompositePass::BuildInternal()
  47. {
  48. BuildChildPasses();
  49. ParentPass::BuildInternal();
  50. }
  51. void BloomCompositePass::FrameBeginInternal(FramePrepareParams params)
  52. {
  53. GetAttachmentInfo();
  54. UpdateParameters();
  55. UpdateChildren();
  56. ParentPass::FrameBeginInternal(params);
  57. }
  58. void BloomCompositePass::GetAttachmentInfo()
  59. {
  60. AZ_Assert(GetInputCount() > 0, "[BloomCompositePass '%s']: must have an input", GetPathName().GetCStr());
  61. // The Output attachment of composite pass is provided by downsample pass, because
  62. // composite pass as a parent pass is unable to bind attachment to slot by itself
  63. // in the pass file, which could result in errors during following passes' initialization
  64. AZ_Assert(GetInputOutputCount() > 0, "[BloomCompositePass '%s']: must have an output", GetPathName().GetCStr());
  65. RPI::PassAttachment* inAttachment = GetInputBinding(0).GetAttachment().get();
  66. RPI::PassAttachment* outAttachment = GetInputOutputBinding(0).GetAttachment().get();
  67. if (inAttachment != nullptr && outAttachment != nullptr)
  68. {
  69. m_inputWidth = inAttachment->m_descriptor.m_image.m_size.m_width;
  70. m_inputHeight = inAttachment->m_descriptor.m_image.m_size.m_height;
  71. m_outputWidth = outAttachment->m_descriptor.m_image.m_size.m_width;
  72. m_outputHeight = outAttachment->m_descriptor.m_image.m_size.m_height;
  73. }
  74. }
  75. void BloomCompositePass::UpdateParameters()
  76. {
  77. RPI::Scene* scene = GetScene();
  78. PostProcessFeatureProcessor* fp = scene->GetFeatureProcessor<PostProcessFeatureProcessor>();
  79. RPI::ViewPtr view = m_pipeline->GetFirstView(GetPipelineViewTag());
  80. if (fp)
  81. {
  82. PostProcessSettings* postProcessSettings = fp->GetLevelSettingsFromView(view);
  83. if (postProcessSettings)
  84. {
  85. BloomSettings* bloomSettings = postProcessSettings->GetBloomSettings();
  86. if (bloomSettings)
  87. {
  88. m_intensity = bloomSettings->GetIntensity();
  89. m_enableBicubic = bloomSettings->GetBicubicEnabled();
  90. m_tintData[0] = bloomSettings->GetTintStage0();
  91. m_tintData[1] = bloomSettings->GetTintStage1();
  92. m_tintData[2] = bloomSettings->GetTintStage2();
  93. m_tintData[3] = bloomSettings->GetTintStage3();
  94. m_tintData[4] = bloomSettings->GetTintStage4();
  95. }
  96. }
  97. }
  98. }
  99. void BloomCompositePass::CreateBinding(BloomCompositeChildPass* pass, uint32_t mipLevel)
  100. {
  101. RPI::PassAttachmentBinding& parentInBinding = GetInputBinding(0);
  102. const RPI::Ptr<RPI::PassAttachment>& parentInAttachment = parentInBinding.GetAttachment();
  103. if (!parentInAttachment)
  104. {
  105. AZ_Error(
  106. "PassSystem",
  107. false,
  108. "[BloomCompositePass '%s']: Slot '%s' has no attachment.",
  109. GetPathName().GetCStr(),
  110. parentInBinding.m_name.GetCStr());
  111. return;
  112. }
  113. RPI::PassAttachmentBinding& parentInOutBinding = GetInputOutputBinding(0);
  114. const RPI::Ptr<RPI::PassAttachment>& parentInOutAttachment = parentInOutBinding.GetAttachment();
  115. if (!parentInOutAttachment)
  116. {
  117. AZ_Error(
  118. "PassSystem",
  119. false,
  120. "[BloomCompositePass '%s']: Slot '%s' has no attachment.",
  121. GetPathName().GetCStr(),
  122. parentInOutBinding.m_name.GetCStr());
  123. return;
  124. }
  125. // Create input binding, from downsampling pass
  126. RPI::PassAttachmentBinding inBinding;
  127. inBinding.m_name = "Input";
  128. inBinding.m_shaderInputName = "m_inputTexture";
  129. inBinding.m_slotType = RPI::PassSlotType::Input;
  130. inBinding.m_scopeAttachmentUsage = RHI::ScopeAttachmentUsage::Shader;
  131. inBinding.m_connectedBinding = &parentInBinding;
  132. RHI::ImageViewDescriptor inViewDesc;
  133. inViewDesc.m_mipSliceMin = static_cast<uint16_t>(mipLevel);
  134. inViewDesc.m_mipSliceMax = static_cast<uint16_t>(mipLevel);
  135. inBinding.m_unifiedScopeDesc.SetAsImage(inViewDesc);
  136. inBinding.SetAttachment(parentInAttachment);
  137. pass->AddAttachmentBinding(inBinding);
  138. // Create output binding, owned by current pass
  139. RPI::PassAttachmentBinding outBinding;
  140. outBinding.m_name = "Output";
  141. outBinding.m_shaderInputName = "m_outputTexture";
  142. outBinding.m_slotType = RPI::PassSlotType::Output;
  143. outBinding.m_scopeAttachmentUsage = RHI::ScopeAttachmentUsage::Shader;
  144. if (mipLevel == 0)
  145. {
  146. outBinding.m_connectedBinding = &parentInOutBinding;
  147. outBinding.SetAttachment(parentInOutAttachment);
  148. }
  149. else
  150. {
  151. outBinding.m_connectedBinding = &parentInBinding;
  152. RHI::ImageViewDescriptor outViewDesc;
  153. outViewDesc.m_mipSliceMin = static_cast<uint16_t>(mipLevel - 1);
  154. outViewDesc.m_mipSliceMax = static_cast<uint16_t>(mipLevel - 1);
  155. outBinding.m_unifiedScopeDesc.SetAsImage(outViewDesc);
  156. outBinding.SetAttachment(parentInAttachment);
  157. }
  158. pass->AddAttachmentBinding(outBinding);
  159. }
  160. void BloomCompositePass::BuildChildPasses()
  161. {
  162. if (!m_children.empty())
  163. {
  164. // In this case children are still exists but attachment binding is flushed out, so we rebind them again
  165. for (size_t childIndex = 0, mipLevel = m_children.size() - 1;
  166. childIndex < m_children.size();
  167. ++childIndex, --mipLevel)
  168. {
  169. BloomCompositeChildPass* compositeChild = static_cast<BloomCompositeChildPass*>(m_children[childIndex].get());
  170. CreateBinding(compositeChild, static_cast<uint32_t>(mipLevel));
  171. }
  172. }
  173. else
  174. {
  175. // Create children
  176. RPI::PassSystemInterface* passSystem = RPI::PassSystemInterface::Get();
  177. for (size_t childIndex = 0, mipLevel = Render::Bloom::MaxStageCount - 1;
  178. childIndex < Render::Bloom::MaxStageCount;
  179. ++childIndex, --mipLevel)
  180. {
  181. RPI::PassDescriptor childDesc;
  182. childDesc.m_passData = AZStd::make_shared<RPI::ComputePassData>();
  183. RPI::ComputePassData* passData = static_cast<RPI::ComputePassData*>(childDesc.m_passData.get());
  184. passData->m_shaderReference = m_passData.m_shaderReference;
  185. childDesc.m_passName = Name{ AZStd::string::format("BloomComposite%d", static_cast<uint32_t>(childIndex)) };
  186. RPI::Ptr<BloomCompositeChildPass> childPass = passSystem->CreatePass<BloomCompositeChildPass>(childDesc);
  187. CreateBinding(childPass.get(), static_cast<uint32_t>(mipLevel));
  188. AddChild(childPass);
  189. }
  190. }
  191. }
  192. void BloomCompositePass::UpdateChildren()
  193. {
  194. uint32_t sourceWidth, sourceHeight, targetWidth, targetHeight;
  195. targetWidth = m_inputWidth;
  196. targetHeight = m_inputHeight;
  197. sourceWidth = targetWidth / 2;
  198. sourceHeight = targetHeight / 2;
  199. BloomCompositeChildPass* compositeChild = static_cast<BloomCompositeChildPass*>(m_children[m_children.size() - 1].get());
  200. compositeChild->UpdateParameters(0, m_inputWidth, m_inputHeight, m_outputWidth, m_outputHeight, m_enableBicubic, m_tintData[0], m_intensity);
  201. for (int childIndex = static_cast<int>(m_children.size() - 2), mipLevel = 1;
  202. childIndex >= 0;
  203. --childIndex, ++mipLevel)
  204. {
  205. BloomCompositeChildPass* blurChild = static_cast<BloomCompositeChildPass*>(m_children[childIndex].get());
  206. blurChild->UpdateParameters(static_cast<uint32_t>(mipLevel), sourceWidth, sourceHeight, targetWidth, targetHeight, m_enableBicubic, m_tintData[m_children.size() - childIndex - 1], m_intensity);
  207. targetWidth = sourceWidth;
  208. targetHeight = sourceHeight;
  209. sourceWidth = targetWidth / 2;
  210. sourceHeight = targetHeight / 2;
  211. }
  212. }
  213. RPI::Ptr<BloomCompositeChildPass> BloomCompositeChildPass::Create(const RPI::PassDescriptor& descriptor)
  214. {
  215. RPI::Ptr<BloomCompositeChildPass> pass = aznew BloomCompositeChildPass(descriptor);
  216. return AZStd::move(pass);
  217. }
  218. BloomCompositeChildPass::BloomCompositeChildPass(const RPI::PassDescriptor& descriptor)
  219. : ComputePass(descriptor)
  220. { }
  221. void BloomCompositeChildPass::UpdateParameters(uint32_t sourceMip, uint32_t sourceImageWidth, uint32_t sourceImageHeight, uint32_t targetImageWidth, uint32_t targetImageHeight, bool enableBicubic, Vector3 tint, float intensity)
  222. {
  223. m_shaderResourceGroup->SetConstant(m_intensityInputIndex, intensity);
  224. float sourceWidth = static_cast<float>(sourceImageWidth);
  225. float sourceHeight = static_cast<float>(sourceImageHeight);
  226. m_shaderResourceGroup->SetConstant(m_sourceImageSizeInputIndex, AZ::Vector2(sourceWidth, sourceHeight));
  227. m_shaderResourceGroup->SetConstant(m_sourceImageTexelSizeInputIndex, AZ::Vector2(1.0f / sourceWidth, 1.0f / sourceHeight));
  228. m_shaderResourceGroup->SetConstant(m_sourceMipLevelInputIndex, sourceMip);
  229. m_shaderResourceGroup->SetConstant(m_enableBicubicInputIndex, enableBicubic);
  230. m_shaderResourceGroup->SetConstant(m_tintInputIndex, tint);
  231. m_targetImageWidth = targetImageWidth;
  232. m_targetImageHeight = targetImageHeight;
  233. }
  234. void BloomCompositeChildPass::FrameBeginInternal(FramePrepareParams params)
  235. {
  236. m_shaderResourceGroup->SetConstant(m_targetImageSizeInputIndex, AZ::Vector2(static_cast<float>(m_targetImageWidth), static_cast<float>(m_targetImageHeight)));
  237. SetTargetThreadCounts(m_targetImageWidth, m_targetImageHeight, 1);
  238. ComputePass::FrameBeginInternal(params);
  239. }
  240. } // namespace RPI
  241. } // namespace AZ