OutputTransformPass.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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 <DisplayMapper/OutputTransformPass.h>
  9. #include <Atom/Feature/ACES/AcesDisplayMapperFeatureProcessor.h>
  10. #include <Atom/RHI/Factory.h>
  11. #include <Atom/RHI/FrameGraphAttachmentInterface.h>
  12. #include <Atom/RPI.Public/RenderPipeline.h>
  13. #include <Atom/RPI.Public/Scene.h>
  14. #include <PostProcess/PostProcessFeatureProcessor.h>
  15. #include <PostProcess/ExposureControl/ExposureControlSettings.h>
  16. namespace AZ
  17. {
  18. namespace Render
  19. {
  20. RPI::Ptr<OutputTransformPass> OutputTransformPass::Create(const RPI::PassDescriptor& descriptor)
  21. {
  22. RPI::Ptr<OutputTransformPass> pass = aznew OutputTransformPass(descriptor);
  23. return AZStd::move(pass);
  24. }
  25. OutputTransformPass::OutputTransformPass(const RPI::PassDescriptor& descriptor)
  26. : ApplyShaperLookupTablePass(descriptor)
  27. , m_toneMapperShaderVariantOptionName(ToneMapperShaderVariantOptionName)
  28. , m_transferFunctionShaderVariantOptionName(TransferFunctionShaderVariantOptionName)
  29. , m_ldrGradingLutShaderVariantOptionName(LdrGradingLutShaderVariantOptionName)
  30. {
  31. m_flags.m_bindViewSrg = true;
  32. }
  33. OutputTransformPass::~OutputTransformPass()
  34. {
  35. }
  36. void OutputTransformPass::InitializeInternal()
  37. {
  38. ApplyShaperLookupTablePass::InitializeInternal();
  39. AZ_Assert(m_shaderResourceGroup != nullptr, "OutputTransformPass %s has a null shader resource group when calling Init.", GetPathName().GetCStr());
  40. if (m_shaderResourceGroup != nullptr)
  41. {
  42. m_shaderInputCinemaLimitsIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name{ "m_cinemaLimits" });
  43. }
  44. InitializeShaderVariant();
  45. }
  46. void OutputTransformPass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph)
  47. {
  48. if (GetLutAssetId().IsValid())
  49. {
  50. ApplyShaperLookupTablePass::SetupFrameGraphDependenciesCommon(frameGraph);
  51. }
  52. DeclareAttachmentsToFrameGraph(frameGraph);
  53. DeclarePassDependenciesToFrameGraph(frameGraph);
  54. frameGraph.SetEstimatedItemCount(1);
  55. }
  56. void OutputTransformPass::CompileResources(const RHI::FrameGraphCompileContext& context)
  57. {
  58. AZ_Assert(m_shaderResourceGroup != nullptr, "OutputTransformPass %s has a null shader resource group when calling Compile.", GetPathName().GetCStr());
  59. if (GetLutAssetId().IsValid())
  60. {
  61. ApplyShaperLookupTablePass::CompileResourcesCommon(context);
  62. }
  63. if (m_needToUpdateShaderVariant)
  64. {
  65. UpdateCurrentShaderVariant();
  66. }
  67. CompileShaderVariant(m_shaderResourceGroup);
  68. m_shaderResourceGroup->SetConstant(m_shaderInputCinemaLimitsIndex, m_displayMapperParameters.m_cinemaLimits);
  69. BindPassSrg(context, m_shaderResourceGroup);
  70. m_shaderResourceGroup->Compile();
  71. }
  72. void OutputTransformPass::BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context)
  73. {
  74. AZ_Assert(m_shaderResourceGroup != nullptr, "LookModificationPass %s has a null shader resource group when calling Execute.", GetPathName().GetCStr());
  75. RHI::CommandList* commandList = context.GetCommandList();
  76. commandList->SetViewport(m_viewportState);
  77. commandList->SetScissor(m_scissorState);
  78. SetSrgsForDraw(context);
  79. m_item.SetPipelineState(GetPipelineStateFromShaderVariant());
  80. commandList->Submit(m_item.GetDeviceDrawItem(context.GetDeviceIndex()));
  81. }
  82. void OutputTransformPass::FrameBeginInternal(FramePrepareParams params)
  83. {
  84. ApplyShaperLookupTablePass::FrameBeginInternal(params);
  85. AZ::RPI::Scene* scene = GetScene();
  86. if (scene)
  87. {
  88. PostProcessFeatureProcessor* fp = scene->GetFeatureProcessor<PostProcessFeatureProcessor>();
  89. if (fp)
  90. {
  91. AZ::RPI::ViewPtr view = GetRenderPipeline()->GetFirstView(GetPipelineViewTag());
  92. PostProcessSettings* postProcessSettings = fp->GetLevelSettingsFromView(view);
  93. if (postProcessSettings)
  94. {
  95. ExposureControlSettings* settings = postProcessSettings->GetExposureControlSettings();
  96. if (settings)
  97. {
  98. settings->UpdateBuffer();
  99. view->GetShaderResourceGroup()->SetBufferView(m_exposureControlBufferInputIndex, settings->GetBufferView());
  100. }
  101. }
  102. }
  103. }
  104. }
  105. void OutputTransformPass::SetToneMapperType(const ToneMapperType& toneMapperType)
  106. {
  107. if (m_toneMapperType != toneMapperType)
  108. {
  109. m_toneMapperType = toneMapperType;
  110. m_needToUpdateShaderVariant = true;
  111. }
  112. }
  113. void OutputTransformPass::SetTransferFunctionType(const TransferFunctionType& transferFunctionType)
  114. {
  115. if (m_transferFunctionType != transferFunctionType)
  116. {
  117. m_transferFunctionType = transferFunctionType;
  118. m_needToUpdateShaderVariant = true;
  119. }
  120. }
  121. void OutputTransformPass::InitializeShaderVariant()
  122. {
  123. AZ_Assert(m_shader != nullptr, "OutputTransformPass %s has a null shader when calling InitializeShaderVariant.", GetPathName().GetCStr());
  124. AZStd::vector<AZ::Name> toneMapperVariationTypes = { AZ::Name("ToneMapperType::None"),
  125. AZ::Name("ToneMapperType::Reinhard"),
  126. AZ::Name("ToneMapperType::AcesFitted"),
  127. AZ::Name("ToneMapperType::AcesFilmic"),
  128. AZ::Name("ToneMapperType::Filmic") };
  129. AZStd::vector<AZ::Name> transferFunctionVariationTypes = {
  130. AZ::Name("TransferFunctionType::None"),
  131. AZ::Name("TransferFunctionType::Gamma22"),
  132. AZ::Name("TransferFunctionType::PerceptualQuantizer") };
  133. AZStd::vector<AZ::Name> doLdrGradingTypes = {AZ::Name("true"), AZ::Name("false")};
  134. // Caching all pipeline state for each shader variation for performance reason.
  135. auto shaderOption = m_shader->CreateShaderOptionGroup();
  136. for (uint32_t tonemapperIndex = 0; tonemapperIndex < toneMapperVariationTypes.size(); ++tonemapperIndex)
  137. {
  138. for (uint32_t transferFunctionIndex = 0; transferFunctionIndex < transferFunctionVariationTypes.size(); ++transferFunctionIndex)
  139. {
  140. for (uint32_t colorGradingIndex = 0; colorGradingIndex < doLdrGradingTypes.size(); ++colorGradingIndex)
  141. {
  142. shaderOption.SetValue(
  143. m_toneMapperShaderVariantOptionName, toneMapperVariationTypes[tonemapperIndex]);
  144. shaderOption.SetValue(
  145. m_transferFunctionShaderVariantOptionName, transferFunctionVariationTypes[transferFunctionIndex]);
  146. shaderOption.SetValue(
  147. m_ldrGradingLutShaderVariantOptionName, doLdrGradingTypes[colorGradingIndex]);
  148. PreloadShaderVariant(m_shader, shaderOption, GetRenderAttachmentConfiguration(), GetMultisampleState());
  149. }
  150. }
  151. }
  152. m_needToUpdateShaderVariant = true;
  153. }
  154. void OutputTransformPass::UpdateCurrentShaderVariant()
  155. {
  156. AZ_Assert(m_shader != nullptr, "OutputTransformPass %s has a null shader when calling UpdateCurrentShaderVariant.", GetPathName().GetCStr());
  157. auto shaderOption = m_shader->CreateShaderOptionGroup();
  158. // Decide which shader to use.
  159. switch (m_toneMapperType)
  160. {
  161. case ToneMapperType::Reinhard:
  162. shaderOption.SetValue(m_toneMapperShaderVariantOptionName, AZ::Name("ToneMapperType::Reinhard"));
  163. break;
  164. case ToneMapperType::AcesFitted:
  165. shaderOption.SetValue(m_toneMapperShaderVariantOptionName, AZ::Name("ToneMapperType::AcesFitted"));
  166. break;
  167. case ToneMapperType::Filmic:
  168. shaderOption.SetValue(m_toneMapperShaderVariantOptionName, AZ::Name("ToneMapperType::Filmic"));
  169. break;
  170. case ToneMapperType::AcesFilmic:
  171. shaderOption.SetValue(m_toneMapperShaderVariantOptionName, AZ::Name("ToneMapperType::AcesFilmic"));
  172. break;
  173. default:
  174. shaderOption.SetValue(m_toneMapperShaderVariantOptionName, AZ::Name("ToneMapperType::None"));
  175. break;
  176. }
  177. switch (m_transferFunctionType)
  178. {
  179. case TransferFunctionType::Gamma22:
  180. shaderOption.SetValue(m_transferFunctionShaderVariantOptionName, AZ::Name("TransferFunctionType::Gamma22"));
  181. break;
  182. case TransferFunctionType::PerceptualQuantizer:
  183. shaderOption.SetValue(m_transferFunctionShaderVariantOptionName, AZ::Name("TransferFunctionType::PerceptualQuantizer"));
  184. break;
  185. default:
  186. shaderOption.SetValue(m_transferFunctionShaderVariantOptionName, AZ::Name("TransferFunctionType::None"));
  187. break;
  188. }
  189. shaderOption.SetValue(m_ldrGradingLutShaderVariantOptionName, GetLutAssetId().IsValid() ? AZ::Name("true") : AZ::Name("false"));
  190. UpdateShaderVariant(shaderOption);
  191. m_needToUpdateShaderVariant = false;
  192. }
  193. void OutputTransformPass::SetDisplayBufferFormat(RHI::Format format)
  194. {
  195. if (m_displayBufferFormat != format)
  196. {
  197. m_displayBufferFormat = format;
  198. if (m_displayBufferFormat == RHI::Format::R8G8B8A8_UNORM ||
  199. m_displayBufferFormat == RHI::Format::B8G8R8A8_UNORM)
  200. {
  201. AcesDisplayMapperFeatureProcessor::GetAcesDisplayMapperParameters(&m_displayMapperParameters, OutputDeviceTransformType_48Nits);
  202. }
  203. else if (m_displayBufferFormat == RHI::Format::R10G10B10A2_UNORM)
  204. {
  205. AcesDisplayMapperFeatureProcessor::GetAcesDisplayMapperParameters(&m_displayMapperParameters, OutputDeviceTransformType_1000Nits);
  206. }
  207. else
  208. {
  209. AZ_Assert(false, "Not yet supported.");
  210. // To work normally on unsupported environment, initialize the display parameters by OutputDeviceTransformType_48Nits.
  211. AcesDisplayMapperFeatureProcessor::GetAcesDisplayMapperParameters(&m_displayMapperParameters, OutputDeviceTransformType_48Nits);
  212. }
  213. }
  214. }
  215. } // namespace Render
  216. } // namespace AZ