DisplayMapperPass.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  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/DisplayMapper/DisplayMapperPass.h>
  9. #include <ACES/Aces.h>
  10. #include <Atom/Feature/ACES/AcesDisplayMapperFeatureProcessor.h>
  11. #include <Atom/RPI.Public/Pass/FullscreenTrianglePass.h>
  12. #include <Atom/RPI.Public/Pass/PassFilter.h>
  13. #include <Atom/RPI.Public/Pass/PassFactory.h>
  14. #include <Atom/RPI.Public/Pass/PassSystemInterface.h>
  15. #include <Atom/RPI.Public/Pass/PassUtils.h>
  16. #include <Atom/RPI.Public/Pass/Specific/SwapChainPass.h>
  17. #include <Atom/RPI.Public/RenderPipeline.h>
  18. #include <Atom/RPI.Public/RPIUtils.h>
  19. #include <Atom/RPI.Public/Scene.h>
  20. #include <Atom/RPI.Public/View.h>
  21. #include <Atom/RPI.Reflect/Pass/ComputePassData.h>
  22. #include <Atom/RPI.Reflect/Pass/FullscreenTrianglePassData.h>
  23. #include <Atom/RPI.Reflect/Asset/AssetUtils.h>
  24. #include <Atom/RHI/Factory.h>
  25. #include <Atom/RHI/FrameScheduler.h>
  26. #include <Atom/RHI/PipelineState.h>
  27. #include <AzCore/Asset/AssetCommon.h>
  28. #include <AzCore/Asset/AssetManagerBus.h>
  29. namespace AZ
  30. {
  31. namespace Render
  32. {
  33. RPI::Ptr<DisplayMapperPass> DisplayMapperPass::Create(const RPI::PassDescriptor& descriptor)
  34. {
  35. RPI::Ptr<DisplayMapperPass> pass = aznew DisplayMapperPass(descriptor);
  36. return pass;
  37. }
  38. DisplayMapperPass::DisplayMapperPass(const RPI::PassDescriptor& descriptor)
  39. : RPI::ParentPass(descriptor)
  40. {
  41. GetDisplayMapperConfiguration();
  42. const DisplayMapperPassData* passData = RPI::PassUtils::GetPassData<DisplayMapperPassData>(descriptor);
  43. if (passData != nullptr)
  44. {
  45. m_displayMapperConfigurationDescriptor = passData->m_config;
  46. }
  47. }
  48. void DisplayMapperPass::ConfigureDisplayParameters()
  49. {
  50. // [GFX TODO] [ATOM-2450] Logic determine the type of display attached and use it to drive the
  51. // display mapper parameters.
  52. if (m_pipelineOutput && m_pipelineOutput->GetAttachment())
  53. {
  54. m_displayBufferFormat = m_pipelineOutput->GetAttachment()->m_descriptor.m_image.m_format;
  55. }
  56. if (m_displayBufferFormat != RHI::Format::Unknown)
  57. {
  58. if (m_acesOutputTransformPass)
  59. {
  60. m_acesOutputTransformPass->SetAcesParameterOverrides(m_displayMapperConfigurationDescriptor.m_acesParameterOverrides);
  61. m_acesOutputTransformPass->SetDisplayBufferFormat(m_displayBufferFormat);
  62. }
  63. if (m_bakeAcesOutputTransformLutPass)
  64. {
  65. m_bakeAcesOutputTransformLutPass->SetDisplayBufferFormat(m_displayBufferFormat);
  66. AZ_Assert(m_acesOutputTransformLutPass != nullptr, "AcesOutputTransformLutPass should be created when baking ACES LUTs.");
  67. m_acesOutputTransformLutPass->SetShaperParams(m_bakeAcesOutputTransformLutPass->GetShaperParams());
  68. }
  69. if (m_outputTransformPass)
  70. {
  71. if (m_displayMapperConfigurationDescriptor.m_operationType == DisplayMapperOperationType::Reinhard)
  72. {
  73. // When using Reinhard tonemapper, a gamma of 2.2 for the transfer function is used for LDR display,
  74. // and PQ is used for HDR.
  75. if (m_displayBufferFormat == RHI::Format::R8G8B8A8_UNORM ||
  76. m_displayBufferFormat == RHI::Format::B8G8R8A8_UNORM)
  77. {
  78. m_outputTransformPass->SetTransferFunctionType(TransferFunctionType::Gamma22);
  79. }
  80. else
  81. {
  82. m_outputTransformPass->SetTransferFunctionType(TransferFunctionType::PerceptualQuantizer);
  83. }
  84. }
  85. m_outputTransformPass->SetDisplayBufferFormat(m_displayBufferFormat);
  86. }
  87. }
  88. }
  89. void DisplayMapperPass::BuildInternal()
  90. {
  91. const Name outputName = Name{ "Output" };
  92. Name inputPass = Name{ "Parent" };
  93. Name inputPassAttachment = Name{ "Input" };
  94. if (m_acesOutputTransformPass)
  95. {
  96. m_acesOutputTransformPass->SetInputReferencePassName(inputPass);
  97. m_acesOutputTransformPass->SetInputReferenceAttachmentName(inputPassAttachment);
  98. inputPass = m_acesOutputTransformPassName;
  99. inputPassAttachment = outputName;
  100. }
  101. else if (m_acesOutputTransformLutPass)
  102. {
  103. m_acesOutputTransformLutPass->SetInputReferencePassName(inputPass);
  104. m_acesOutputTransformLutPass->SetInputReferenceAttachmentName(inputPassAttachment);
  105. inputPass = m_acesOutputTransformLutPassName;
  106. inputPassAttachment = outputName;
  107. }
  108. else if (m_displayMapperPassthroughPass)
  109. {
  110. m_displayMapperPassthroughPass->SetInputReferencePassName(inputPass);
  111. m_displayMapperPassthroughPass->SetInputReferenceAttachmentName(inputPassAttachment);
  112. inputPass = m_displayMapperPassthroughPassName;
  113. inputPassAttachment = outputName;
  114. }
  115. else if (m_displayMapperSRGBPass)
  116. {
  117. m_displayMapperSRGBPass->SetInputReferencePassName(inputPass);
  118. m_displayMapperSRGBPass->SetInputReferenceAttachmentName(inputPassAttachment);
  119. inputPass = m_displayMapperSRGBPassName;
  120. inputPassAttachment = outputName;
  121. }
  122. else if (m_outputTransformPass)
  123. {
  124. m_outputTransformPass->SetInputReferencePassName(inputPass);
  125. m_outputTransformPass->SetInputReferenceAttachmentName(inputPassAttachment);
  126. inputPass = m_outputTransformPassName;
  127. inputPassAttachment = outputName;
  128. }
  129. if (m_ldrGradingLookupTablePass)
  130. {
  131. m_ldrGradingLookupTablePass->SetInputReferencePassName(inputPass);
  132. m_ldrGradingLookupTablePass->SetInputReferenceAttachmentName(inputPassAttachment);
  133. }
  134. m_pipelineOutput = FindAttachmentBinding(Name("PipelineOutput"));
  135. ParentPass::BuildInternal();
  136. }
  137. void DisplayMapperPass::InitializeInternal()
  138. {
  139. // Force update on bindings because children of display mapper pass have their outputs connect to
  140. // their parent's output, which is a non-conventional and non-standard workflow. Parent outputs are
  141. // updated after child outputs, so post-build the child outputs do not yet point to the attachments on
  142. // the parent bindings they are connected to. Forcing this refresh sets the attachment on the child output.
  143. for (const RPI::Ptr<Pass>& child : m_children)
  144. {
  145. child->UpdateConnectedBindings();
  146. }
  147. RPI::ParentPass::InitializeInternal();
  148. }
  149. void DisplayMapperPass::FrameBeginInternal(FramePrepareParams params)
  150. {
  151. ConfigureDisplayParameters();
  152. ParentPass::FrameBeginInternal(params);
  153. }
  154. void DisplayMapperPass::FrameEndInternal()
  155. {
  156. GetDisplayMapperConfiguration();
  157. ParentPass::FrameEndInternal();
  158. }
  159. void DisplayMapperPass::CreateChildPassesInternal()
  160. {
  161. ClearChildren();
  162. BuildGradingLutTemplate();
  163. CreateGradingAndAcesPasses();
  164. }
  165. AZStd::shared_ptr<RPI::PassTemplate> CreatePassTemplateHelper(
  166. const Name& templateName, const Name& passClass, bool renderToOwnedImage, const Name& ownedImageName, const char* shaderFilePath)
  167. {
  168. auto passTemplate = AZStd::make_shared<RPI::PassTemplate>();
  169. passTemplate->m_name = templateName;
  170. passTemplate->m_passClass = passClass;
  171. // Slots
  172. passTemplate->m_slots.resize(2);
  173. RPI::PassSlot& inSlot = passTemplate->m_slots[0];
  174. inSlot.m_name = "Input";
  175. inSlot.m_slotType = RPI::PassSlotType::Input;
  176. inSlot.m_scopeAttachmentUsage = RHI::ScopeAttachmentUsage::Shader;
  177. inSlot.m_loadStoreAction.m_loadAction = RHI::AttachmentLoadAction::DontCare;
  178. RPI::PassSlot& outSlot = passTemplate->m_slots[1];
  179. outSlot.m_name = "Output";
  180. outSlot.m_slotType = RPI::PassSlotType::Output;
  181. outSlot.m_scopeAttachmentUsage = RHI::ScopeAttachmentUsage::RenderTarget;
  182. outSlot.m_loadStoreAction.m_loadAction = RHI::AttachmentLoadAction::DontCare;
  183. passTemplate->m_connections.resize(1);
  184. RPI::PassConnection& outConnection = passTemplate->m_connections[0];
  185. if (renderToOwnedImage)
  186. {
  187. // If rendering to it's own image attachment
  188. passTemplate->m_imageAttachments.resize(1);
  189. RPI::PassImageAttachmentDesc& imageAttachment = passTemplate->m_imageAttachments[0];
  190. imageAttachment.m_name = ownedImageName;
  191. imageAttachment.m_sizeSource.m_source.m_pass = "This";
  192. imageAttachment.m_sizeSource.m_source.m_attachment = "Input";
  193. imageAttachment.m_formatSource.m_pass = "This";
  194. imageAttachment.m_formatSource.m_attachment = "Input";
  195. imageAttachment.m_imageDescriptor.m_bindFlags = RHI::ImageBindFlags::CopyRead | RHI::ImageBindFlags::Color | RHI::ImageBindFlags::ShaderReadWrite;
  196. outConnection.m_localSlot = "Output";
  197. outConnection.m_attachmentRef.m_pass = "This";
  198. outConnection.m_attachmentRef.m_attachment = ownedImageName;
  199. }
  200. else
  201. {
  202. // Output connection will be the parent's output
  203. outConnection.m_localSlot = "Output";
  204. outConnection.m_attachmentRef.m_pass = "Parent";
  205. outConnection.m_attachmentRef.m_attachment = "Output";
  206. }
  207. Data::AssetId shaderAssetId;
  208. Data::AssetCatalogRequestBus::BroadcastResult(
  209. shaderAssetId, &Data::AssetCatalogRequestBus::Events::GetAssetIdByPath,
  210. shaderFilePath, azrtti_typeid<RPI::ShaderAsset>(), false);
  211. if (!shaderAssetId.IsValid())
  212. {
  213. AZ_Assert(false, "[DisplayMapperPass] Unable to obtain asset id for %s.", shaderFilePath);
  214. return nullptr;
  215. }
  216. AZStd::shared_ptr<RPI::FullscreenTrianglePassData> passData = AZStd::make_shared<RPI::FullscreenTrianglePassData>();
  217. passData->m_shaderAsset.m_filePath = shaderFilePath;
  218. passData->m_shaderAsset.m_assetId = shaderAssetId;
  219. passTemplate->m_passData = AZStd::move(passData);
  220. return passTemplate;
  221. }
  222. AZStd::shared_ptr<RPI::PassTemplate> CreateBakeAcesLutPassTemplateHelper(
  223. const Name& templateName, const Name& passClass, const char* shaderFilePath)
  224. {
  225. auto passTemplate = AZStd::make_shared<RPI::PassTemplate>();
  226. passTemplate->m_name = templateName;
  227. passTemplate->m_passClass = passClass;
  228. // Slots
  229. passTemplate->m_slots.resize(1);
  230. RPI::PassSlot& outSlot = passTemplate->m_slots[0];
  231. outSlot.m_name = "Output";
  232. outSlot.m_slotType = RPI::PassSlotType::Output;
  233. outSlot.m_scopeAttachmentUsage = RHI::ScopeAttachmentUsage::Shader;
  234. outSlot.m_loadStoreAction.m_loadAction = RHI::AttachmentLoadAction::Clear;
  235. Data::AssetId shaderAssetId;
  236. Data::AssetCatalogRequestBus::BroadcastResult(
  237. shaderAssetId, &Data::AssetCatalogRequestBus::Events::GetAssetIdByPath,
  238. shaderFilePath, azrtti_typeid<RPI::ShaderAsset>(), false);
  239. if (!shaderAssetId.IsValid())
  240. {
  241. AZ_Assert(false, "[DisplayMapperPass] Unable to obtain asset id for %s.", shaderFilePath);
  242. return nullptr;
  243. }
  244. AZStd::shared_ptr<RPI::ComputePassData> passData = AZStd::make_shared<RPI::ComputePassData>();
  245. passData->m_totalNumberOfThreadsX = 32;
  246. passData->m_totalNumberOfThreadsY = 32;
  247. passData->m_totalNumberOfThreadsZ = 32;
  248. passData->m_shaderReference.m_filePath = shaderFilePath;
  249. passData->m_shaderReference.m_assetId = shaderAssetId;
  250. passTemplate->m_passData = AZStd::move(passData);
  251. return passTemplate;
  252. }
  253. /**
  254. * Create a pass templates for HDR and LDR grading passes, and the output transform passes.
  255. */
  256. void DisplayMapperPass::BuildGradingLutTemplate()
  257. {
  258. // Pass template names
  259. const Name acesOutputTransformTemplateName = Name{ "AcesOutputTransformTemplate" };
  260. const Name acesOutputTransformLutTemplateName = Name{ "AcesOutputTransformLutTemplate" };
  261. const Name bakeAcesOutputTransformLutTemplateName = Name{ "BakeAcesOutputTransformLutTemplate" };
  262. const Name displayMapperPassthroughTemplateName = Name{ "DisplayMapperPassthroughTemplate" };
  263. const Name displayMapperSRGBTemplateName = Name{ "DisplayMapperSRGBTemplate" };
  264. const Name hdrGradingLutTemplateName = Name{ "HdrGradingLutTemplate" };
  265. const Name ldrGradingLutTemplateName = Name{ "LdrGradingLutTemplate" };
  266. const Name outputTransformTemplateName = Name{ "OutputTransformTemplate" };
  267. // Pass classes
  268. const Name acesOutputTransformPassClassName = Name{ "AcesOutputTransformPass" };
  269. const Name acesOutputTransformLutPassClassName = Name{ "AcesOutputTransformLutPass" };
  270. const Name bakeAcesOutputTransformLutPassClassName = Name{ "BakeAcesOutputTransformLutPass" };
  271. const Name displayMapperFullScreenPassClassName = Name{ "DisplayMapperFullScreenPass" };
  272. const Name applyShaperLookupTablePassClassName = Name{ "ApplyShaperLookupTablePass" };
  273. const Name outputTransformPassClassName = Name{ "OutputTransformPass" };
  274. // Names of owned image attachments that may be used
  275. const Name hdrGradingImageName = Name{ "HdrGradingImage" };
  276. const Name outputTransformImageName = Name{ "OutputTransformImage" };
  277. const char* acesOuputTransformShaderPath = "Shaders/PostProcessing/DisplayMapper.azshader";
  278. const char* acesOuputTransformLutShaderPath = "Shaders/PostProcessing/AcesOutputTransformLut.azshader";
  279. const char* bakeAcesOuputTransformLutShaderPath = "Shaders/PostProcessing/BakeAcesOutputTransformLutCS.azshader";
  280. const char* passthroughShaderPath = "Shaders/PostProcessing/FullscreenCopy.azshader";
  281. const char* sRGBShaderPath = "Shaders/PostProcessing/DisplayMapperSRGB.azshader";
  282. const char* applyShaperLookupTableShaderFilePath = "Shaders/PostProcessing/ApplyShaperLookupTable.azshader";
  283. const char* outputTransformShaderPath = "Shaders/PostProcessing/OutputTransform.azshader";
  284. // Output transform templates. If there is no LDR grading LUT pass, then the output transform pass is the final pass
  285. // and will render to the DisplayMapper's output attachment. Otherwise, it renders to its own attachment image.
  286. // ACES
  287. m_acesOutputTransformTemplate.reset();
  288. m_acesOutputTransformTemplate = CreatePassTemplateHelper(
  289. acesOutputTransformTemplateName, acesOutputTransformPassClassName,
  290. m_displayMapperConfigurationDescriptor.m_ldrGradingLutEnabled, outputTransformImageName, acesOuputTransformShaderPath);
  291. // ACES LUT
  292. m_acesOutputTransformLutTemplate.reset();
  293. m_acesOutputTransformLutTemplate = CreatePassTemplateHelper(
  294. acesOutputTransformLutTemplateName, acesOutputTransformLutPassClassName,
  295. m_displayMapperConfigurationDescriptor.m_ldrGradingLutEnabled, outputTransformImageName, acesOuputTransformLutShaderPath);
  296. // Bake ACES LUT
  297. m_bakeAcesOutputTransformLutTemplate.reset();
  298. m_bakeAcesOutputTransformLutTemplate = CreateBakeAcesLutPassTemplateHelper(
  299. bakeAcesOutputTransformLutTemplateName, bakeAcesOutputTransformLutPassClassName,
  300. bakeAcesOuputTransformLutShaderPath);
  301. // Passthrough
  302. m_passthroughTemplate.reset();
  303. m_passthroughTemplate = CreatePassTemplateHelper(
  304. displayMapperPassthroughTemplateName, displayMapperFullScreenPassClassName,
  305. m_displayMapperConfigurationDescriptor.m_ldrGradingLutEnabled, outputTransformImageName, passthroughShaderPath);
  306. // sRGB
  307. m_sRGBTemplate.reset();
  308. m_sRGBTemplate = CreatePassTemplateHelper(
  309. displayMapperSRGBTemplateName, displayMapperFullScreenPassClassName,
  310. m_displayMapperConfigurationDescriptor.m_ldrGradingLutEnabled, outputTransformImageName, sRGBShaderPath);
  311. // Output Transform
  312. m_outputTransformTemplate.reset();
  313. m_outputTransformTemplate = CreatePassTemplateHelper(
  314. outputTransformTemplateName, outputTransformPassClassName,
  315. m_displayMapperConfigurationDescriptor.m_ldrGradingLutEnabled, outputTransformImageName, outputTransformShaderPath);
  316. // LDR grading LUT pass, if enabled, is the final pass and so it will render into the DisplayMapper's output attachment.
  317. m_ldrGradingLookupTableTemplate.reset();
  318. m_ldrGradingLookupTableTemplate = CreatePassTemplateHelper(
  319. ldrGradingLutTemplateName, applyShaperLookupTablePassClassName,
  320. false, Name{ "" }, applyShaperLookupTableShaderFilePath);
  321. }
  322. template<typename PassType>
  323. RPI::Ptr<PassType> CreatePassHelper(RPI::PassSystemInterface* passSystem, AZStd::shared_ptr<RPI::PassTemplate> passTemplate, const Name& passName)
  324. {
  325. RPI::Ptr<RPI::Pass> pass = passSystem->CreatePassFromTemplate(passTemplate, passName);
  326. if (!pass)
  327. {
  328. AZ_Assert(false, "[DisplayMapperPass] Unable to create %s.", passName.GetCStr());
  329. return nullptr;
  330. }
  331. RPI::Ptr<PassType> returnPass = static_cast<PassType*>(pass.get());
  332. return AZStd::move(returnPass);
  333. }
  334. void DisplayMapperPass::CreateGradingAndAcesPasses()
  335. {
  336. RPI::PassSystemInterface* passSystem = RPI::PassSystemInterface::Get();
  337. if (m_displayMapperConfigurationDescriptor.m_operationType == DisplayMapperOperationType::Aces)
  338. {
  339. // ACES path
  340. m_acesOutputTransformPass = CreatePassHelper<AcesOutputTransformPass>(passSystem, m_acesOutputTransformTemplate, m_acesOutputTransformPassName);
  341. }
  342. else if (m_displayMapperConfigurationDescriptor.m_operationType == DisplayMapperOperationType::AcesLut)
  343. {
  344. // Aces LUT path
  345. m_bakeAcesOutputTransformLutPass = CreatePassHelper<BakeAcesOutputTransformLutPass>(passSystem, m_bakeAcesOutputTransformLutTemplate, m_bakeAcesOutputTransformLutPassName);
  346. m_acesOutputTransformLutPass = CreatePassHelper<AcesOutputTransformLutPass>(passSystem, m_acesOutputTransformLutTemplate, m_acesOutputTransformLutPassName);
  347. }
  348. else if (m_displayMapperConfigurationDescriptor.m_operationType == DisplayMapperOperationType::Passthrough)
  349. {
  350. // Passthrough
  351. // [GFX TODO][ATOM-4189] Optimize the passthrough function in the DisplayMapper
  352. // Only need to create this if LDR grading LUT pass is not used.
  353. if (!m_displayMapperConfigurationDescriptor.m_ldrGradingLutEnabled)
  354. {
  355. m_displayMapperPassthroughPass = CreatePassHelper<DisplayMapperFullScreenPass>(passSystem, m_passthroughTemplate, m_displayMapperPassthroughPassName);
  356. }
  357. }
  358. else if (m_displayMapperConfigurationDescriptor.m_operationType == DisplayMapperOperationType::GammaSRGB)
  359. {
  360. m_displayMapperSRGBPass = CreatePassHelper<DisplayMapperFullScreenPass>(passSystem, m_sRGBTemplate, m_displayMapperSRGBPassName);
  361. }
  362. else if (m_displayMapperConfigurationDescriptor.m_operationType == DisplayMapperOperationType::Reinhard)
  363. {
  364. m_outputTransformPass = CreatePassHelper<OutputTransformPass>(passSystem, m_outputTransformTemplate, m_outputTransformPassName);
  365. m_outputTransformPass->SetToneMapperType(ToneMapperType::Reinhard);
  366. }
  367. if (m_displayMapperConfigurationDescriptor.m_ldrGradingLutEnabled)
  368. {
  369. // ID should be valid, maybe no need to check again here.
  370. if (m_displayMapperConfigurationDescriptor.m_ldrColorGradingLut.GetId().IsValid())
  371. {
  372. // For LDR tonemapping, no need to set the shaper function as the default identity shaper is assumed.
  373. m_ldrGradingLookupTablePass = CreatePassHelper<ApplyShaperLookupTablePass>(passSystem, m_ldrGradingLookupTableTemplate, m_ldrGradingLookupTablePassName);
  374. m_ldrGradingLookupTablePass->SetLutAssetId(m_displayMapperConfigurationDescriptor.m_ldrColorGradingLut.GetId());
  375. }
  376. }
  377. // Add the children as necessary
  378. if (m_acesOutputTransformPass)
  379. {
  380. AddChild(m_acesOutputTransformPass);
  381. }
  382. if (m_bakeAcesOutputTransformLutPass)
  383. {
  384. AddChild(m_bakeAcesOutputTransformLutPass);
  385. }
  386. if (m_acesOutputTransformLutPass)
  387. {
  388. AddChild(m_acesOutputTransformLutPass);
  389. }
  390. if (m_displayMapperPassthroughPass)
  391. {
  392. AddChild(m_displayMapperPassthroughPass);
  393. }
  394. if (m_displayMapperSRGBPass)
  395. {
  396. AddChild(m_displayMapperSRGBPass);
  397. }
  398. if (m_outputTransformPass)
  399. {
  400. AddChild(m_outputTransformPass);
  401. }
  402. if (m_ldrGradingLookupTablePass)
  403. {
  404. AddChild(m_ldrGradingLookupTablePass);
  405. }
  406. }
  407. void DisplayMapperPass::GetDisplayMapperConfiguration()
  408. {
  409. DisplayMapperConfigurationDescriptor desc;
  410. AZ::RPI::Scene* scene = GetScene();
  411. if (scene)
  412. {
  413. AcesDisplayMapperFeatureProcessor* fp = scene->GetFeatureProcessor<AcesDisplayMapperFeatureProcessor>();
  414. if (fp)
  415. {
  416. desc = fp->GetDisplayMapperConfiguration();
  417. // Check to ensure that a valid LUT has been set
  418. if (desc.m_ldrGradingLutEnabled)
  419. {
  420. if (!desc.m_ldrColorGradingLut.GetId().IsValid())
  421. {
  422. desc.m_ldrGradingLutEnabled = false;
  423. }
  424. }
  425. if (desc.m_operationType != m_displayMapperConfigurationDescriptor.m_operationType ||
  426. desc.m_ldrGradingLutEnabled != m_displayMapperConfigurationDescriptor.m_ldrGradingLutEnabled ||
  427. desc.m_ldrColorGradingLut != m_displayMapperConfigurationDescriptor.m_ldrColorGradingLut ||
  428. desc.m_acesParameterOverrides.m_overrideDefaults != m_displayMapperConfigurationDescriptor.m_acesParameterOverrides.m_overrideDefaults)
  429. {
  430. m_flags.m_createChildren = true;
  431. QueueForBuildAndInitialization();
  432. }
  433. m_displayMapperConfigurationDescriptor = desc;
  434. }
  435. }
  436. else
  437. {
  438. // At the time the DisplayMapper is created, there is no scene, so just get the default settings
  439. AcesDisplayMapperFeatureProcessor::GetDefaultDisplayMapperConfiguration(m_displayMapperConfigurationDescriptor);
  440. }
  441. }
  442. void DisplayMapperPass::ClearChildren()
  443. {
  444. RemoveChildren();
  445. m_acesOutputTransformPass = nullptr;
  446. m_bakeAcesOutputTransformLutPass = nullptr;
  447. m_acesOutputTransformLutPass = nullptr;
  448. m_displayMapperPassthroughPass = nullptr;
  449. m_displayMapperSRGBPass = nullptr;
  450. m_ldrGradingLookupTablePass = nullptr;
  451. m_outputTransformPass = nullptr;
  452. }
  453. } // namespace Render
  454. } // namespace AZ