3
0

EditorStatePassSystem.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 <Pass/EditorStatePassSystem.h>
  9. #include <Pass/EditorStatePassSystemUtils.h>
  10. #include <Pass/EditorModeFeedbackParentPass.h>
  11. #include <Pass/State/EditorStateBufferCopyPass.h>
  12. #include <Pass/Child/EditorModeDesaturationPass.h>
  13. #include <Pass/Child/EditorModeTintPass.h>
  14. #include <Pass/Child/EditorModeBlurPass.h>
  15. #include <Pass/Child/EditorModeOutlinePass.h>
  16. #include <Atom/RPI.Public/Pass/PassFilter.h>
  17. #include <Atom/RPI.Public/RenderPipeline.h>
  18. namespace AZ::Render
  19. {
  20. static constexpr const char* const MainPassParentTemplateName = "EditorModeFeedbackParentTemplate";
  21. static constexpr const char* const MainPassParentTemplatePassClassName = "EditorModeFeedbackParentPass";
  22. static constexpr const char* const MainPassParentPassName = "EditorModeFeedback";
  23. static constexpr const char* const EditorModeDesaturationPassName = "EditorModeDesaturationPass";
  24. static constexpr const char* const EditorModeTintPassPassName = "EditorModeTintPass";
  25. static constexpr const char* const EditorModeBlurPassName = "EditorModeBlurPass";
  26. static constexpr const char* const EditorModeOutlinePassName = "EditorModeOutlinePass";
  27. EditorStatePassSystem::EditorStatePassSystem(EditorStateList&& editorStates)
  28. : m_editorStates(AZStd::move(editorStates))
  29. {
  30. auto* passSystem = RPI::PassSystemInterface::Get();
  31. AZ_Assert(passSystem, "Cannot get the pass system.");
  32. passSystem->AddPassCreator(Name(MainPassParentTemplatePassClassName), &EditorModeFeedbackParentPass::Create);
  33. passSystem->AddPassCreator(Name(BufferCopyStatePassTemplatePassClassName), &EditorStateBufferCopyPass::Create);
  34. passSystem->AddPassCreator(Name(StatePassTemplatePassClassName), &EditorStateParentPass::Create);
  35. passSystem->AddPassCreator(Name(EditorModeDesaturationPassName), &EditorModeDesaturationPass::Create);
  36. passSystem->AddPassCreator(Name(EditorModeTintPassPassName), &EditorModeTintPass::Create);
  37. passSystem->AddPassCreator(Name(EditorModeBlurPassName), &EditorModeBlurPass::Create);
  38. passSystem->AddPassCreator(Name(EditorModeOutlinePassName), &EditorModeOutlinePass::Create);
  39. // Editor state child effect passes
  40. passSystem->LoadPassTemplateMappings("Passes/Child/EditorModeFeedback_ChildPassTemplates.azasset");
  41. }
  42. void EditorStatePassSystem::AddPassesToRenderPipeline(RPI::RenderPipeline* renderPipeline)
  43. {
  44. const auto templateName = Name(MainPassParentTemplateName);
  45. // Early return if pass is already found in render pipeline or if the pipeline is not the default one (i.e it is an XR pipeline).
  46. auto passFilter = AZ::RPI::PassFilter::CreateWithTemplateName(templateName, renderPipeline);
  47. auto foundPass = AZ::RPI::PassSystemInterface::Get()->FindFirstPass(passFilter);
  48. if (foundPass || renderPipeline->GetViewType() != RPI::ViewType::Default)
  49. {
  50. return;
  51. }
  52. // check if the reference pass of insert position exist
  53. Name postProcessPassName = Name("PostProcessPass");
  54. if (renderPipeline->FindFirstPass(postProcessPassName) == nullptr)
  55. {
  56. AZ_Warning("EditorModeFeedback", false, "Can't find %s in the render pipeline. Editor mode feedback is disabled", postProcessPassName.GetCStr());
  57. return;
  58. }
  59. auto mainParentPassTemplate = RPI::PassSystemInterface::Get()->GetPassTemplate(templateName);
  60. if (!mainParentPassTemplate)
  61. {
  62. // Create the pass template and add it to the pass system.
  63. auto newPassTemplate = AZStd::make_shared<RPI::PassTemplate>();
  64. newPassTemplate->m_name = templateName;
  65. newPassTemplate->m_passClass = Name(MainPassParentTemplatePassClassName);
  66. // Input depth slot
  67. {
  68. RPI::PassSlot slot;
  69. slot.m_name = Name("InputDepth");
  70. slot.m_slotType = RPI::PassSlotType::Input;
  71. newPassTemplate->AddSlot(slot);
  72. }
  73. // Input/output color slot
  74. {
  75. RPI::PassSlot slot;
  76. slot.m_name = Name("ColorInputOutput");
  77. slot.m_slotType = RPI::PassSlotType::InputOutput;
  78. newPassTemplate->AddSlot(slot);
  79. }
  80. // Entity mask passes
  81. m_masks = CreateMaskPassTemplatesFromEditorStates(m_editorStates);
  82. for (const auto& drawList : m_masks)
  83. {
  84. RPI::PassRequest pass;
  85. pass.m_passName = GetMaskPassNameForDrawList(drawList);
  86. pass.m_templateName = GetMaskPassTemplateNameForDrawList(drawList);
  87. // Input depth
  88. {
  89. RPI::PassConnection connection;
  90. connection.m_localSlot = Name("InputDepth");
  91. connection.m_attachmentRef = { Name("Parent"), Name("InputDepth") };
  92. pass.AddInputConnection(connection);
  93. }
  94. newPassTemplate->AddPassRequest(pass);
  95. }
  96. // Editor state passes
  97. auto previousOutput = AZStd::make_pair(Name("Parent"), Name("ColorInputOutput"));
  98. for (const auto& state : m_editorStates)
  99. {
  100. CreateAndAddStateParentPassTemplate(*state);
  101. RPI::PassRequest pass;
  102. pass.m_passName = state->GetPassName();
  103. pass.m_templateName = state->GetPassTemplateName();
  104. // Input depth
  105. {
  106. RPI::PassConnection connection;
  107. connection.m_localSlot = Name("InputDepth");
  108. connection.m_attachmentRef = { Name("Parent"), Name("InputDepth") };
  109. pass.AddInputConnection(connection);
  110. }
  111. // Input entity mask
  112. {
  113. RPI::PassConnection connection;
  114. connection.m_localSlot = Name("InputEntityMask");
  115. connection.m_attachmentRef = { GetMaskPassNameForDrawList(state->GetEntityMaskDrawList()), Name("OutputEntityMask") };
  116. pass.AddInputConnection(connection);
  117. }
  118. // Input color
  119. {
  120. RPI::PassConnection connection;
  121. connection.m_localSlot = Name("InputColor");
  122. connection.m_attachmentRef = { previousOutput.first, previousOutput.second };
  123. pass.AddInputConnection(connection);
  124. }
  125. newPassTemplate->AddPassRequest(pass);
  126. // Buffer copy pass
  127. {
  128. CreateAndAddBufferCopyPassTemplate(*state);
  129. RPI::PassRequest buffercopy;
  130. buffercopy.m_passName = GetBufferCopyPassNameForState(*state);
  131. buffercopy.m_templateName = GetBufferCopyPassTemplateName(*state);
  132. // Input color
  133. {
  134. RPI::PassConnection connection;
  135. connection.m_localSlot = Name("InputColor");
  136. connection.m_attachmentRef = { pass.m_passName, Name("OutputColor") };
  137. buffercopy.AddInputConnection(connection);
  138. }
  139. newPassTemplate->AddPassRequest(buffercopy);
  140. previousOutput = { buffercopy.m_passName, Name("OutputColor") };
  141. }
  142. }
  143. RPI::PassSystemInterface::Get()->AddPassTemplate(newPassTemplate->m_name, newPassTemplate);
  144. mainParentPassTemplate = newPassTemplate;
  145. }
  146. AZ::RPI::PassRequest passRequest;
  147. passRequest.m_passName = Name(MainPassParentPassName);
  148. passRequest.m_templateName = mainParentPassTemplate->m_name;
  149. passRequest.AddInputConnection(
  150. RPI::PassConnection{ Name("ColorInputOutput"), RPI::PassAttachmentRef{ postProcessPassName, Name("Output") } });
  151. passRequest.AddInputConnection(
  152. RPI::PassConnection{ Name("InputDepth"), RPI::PassAttachmentRef{ Name("DepthPrePass"), Name("Depth") } });
  153. RPI::Ptr<RPI::Pass> parentPass = RPI::PassSystemInterface::Get()->CreatePassFromRequest(&passRequest);
  154. if (!parentPass)
  155. {
  156. AZ_Error("EditorStatePassSystem", false, "Create editor mode feedback parent pass from pass request failed", renderPipeline->GetId().GetCStr());
  157. return;
  158. }
  159. // Inject the parent pass after the PostProcess pass
  160. if (!renderPipeline->AddPassAfter(parentPass, postProcessPassName))
  161. {
  162. AZ_Error(
  163. "EditorStatePassSystem", false, "Add editor mode feedback parent pass to render pipeline [%s] failed", renderPipeline->GetId().GetCStr());
  164. return;
  165. }
  166. }
  167. EntityMaskMap EditorStatePassSystem::GetEntitiesForEditorStates() const
  168. {
  169. EntityMaskMap entityMaskMap;
  170. for (const auto& state : m_editorStates)
  171. {
  172. if (state->IsEnabled())
  173. {
  174. const auto entityIds = state->GetMaskedEntities();
  175. auto& mask = entityMaskMap[state->GetEntityMaskDrawList()];
  176. for (const auto& entityId : entityIds)
  177. {
  178. mask.insert(entityId);
  179. }
  180. }
  181. }
  182. return entityMaskMap;
  183. }
  184. void EditorStatePassSystem::Update()
  185. {
  186. for (auto& state : m_editorStates)
  187. {
  188. state->UpdatePassDataForPipelines();
  189. }
  190. }
  191. const char* EditorStatePassSystem::GetParentPassTemplateName() const
  192. {
  193. return MainPassParentTemplateName;
  194. }
  195. void EditorStatePassSystem::ConfigureStatePassesForPipeline([[maybe_unused]]RPI::RenderPipeline* renderPipeline)
  196. {
  197. RPI::PassFilter mainPassParentPassFilter = RPI::PassFilter::CreateWithPassName(Name(MainPassParentPassName), renderPipeline);
  198. RPI::Ptr<RPI::Pass> mainPass = RPI::PassSystemInterface::Get()->FindFirstPass(mainPassParentPassFilter);
  199. if (!mainPass)
  200. {
  201. return;
  202. }
  203. auto mainPassParent = azdynamic_cast<EditorModeFeedbackParentPass*>(mainPass.get());
  204. for (auto& state : m_editorStates)
  205. {
  206. auto statePass = mainPassParent->FindChildPass(Name(state->GetPassName()));
  207. state->AddParentPassForPipeline(renderPipeline->GetId(), statePass);
  208. }
  209. }
  210. void EditorStatePassSystem::RemoveStatePassesForPipeline([[maybe_unused]]RPI::RenderPipeline* renderPipeline)
  211. {
  212. for (auto& state : m_editorStates)
  213. {
  214. state->RemoveParentPassForPipeline(renderPipeline->GetId());
  215. }
  216. }
  217. } // namespace AZ::Render