MultiViewportSwapchainComponent.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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 <RHI/MultiViewportSwapchainComponent.h>
  9. #include <Utils/Utils.h>
  10. #include <AzFramework/Windowing/NativeWindow.h>
  11. #include <Atom/RHI/FrameGraphAttachmentDatabase.h>
  12. #include <Atom/RHI/FrameGraphExecuteContext.h>
  13. #include <Atom/RHI/FrameGraphInterface.h>
  14. #include <Atom/RHI/ScopeProducerFunction.h>
  15. #include <SampleComponentManager.h>
  16. namespace AtomSampleViewer
  17. {
  18. using namespace AZ;
  19. void MultiViewportSwapchainComponent::Reflect(AZ::ReflectContext* context)
  20. {
  21. if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  22. {
  23. serializeContext->Class<MultiViewportSwapchainComponent, AZ::Component>()
  24. ->Version(1);
  25. }
  26. }
  27. MultiViewportSwapchainComponent::MultiViewportSwapchainComponent()
  28. {
  29. m_windowContext = AZStd::make_shared<AZ::RPI::WindowContext>();
  30. m_windowContext2 = AZStd::make_shared<AZ::RPI::WindowContext>();
  31. m_nativeWindow2 = AZStd::make_unique<AzFramework::NativeWindow>("Second Window", AzFramework::WindowGeometry(0, 0, 1280, 720));
  32. CreateClearColors();
  33. m_supportRHISamplePipeline = true;
  34. }
  35. void MultiViewportSwapchainComponent::OnFramePrepare(AZ::RHI::FrameGraphBuilder& frameGraphBuilder)
  36. {
  37. if (m_nativeWindow2 && m_nativeWindow2->IsActive())
  38. {
  39. RPI::WindowContext& windowContext = *m_windowContext2;
  40. frameGraphBuilder.GetAttachmentDatabase().ImportSwapChain(windowContext.GetSwapChainAttachmentId(), windowContext.GetSwapChain());
  41. }
  42. BasicRHIComponent::OnFramePrepare(frameGraphBuilder);
  43. }
  44. void MultiViewportSwapchainComponent::Activate()
  45. {
  46. m_nativeWindow2->Activate();
  47. // Create a scope for the swapchain of main window
  48. CreateScopeForWindow(m_windowContext, RHI::ScopeId{"MultiViewportSwapchain"});
  49. // Create a scope for the swapchain of second window
  50. AzFramework::WindowNotificationBus::Handler::BusConnect(m_nativeWindow2->GetWindowHandle());
  51. AZ::RHI::Ptr<AZ::RHI::Device> device = AZ::RHI::RHISystemInterface::Get()->GetDevice();
  52. m_windowContext2->Initialize(*device, m_nativeWindow2->GetWindowHandle());
  53. CreateScopeForWindow(m_windowContext2, RHI::ScopeId{"MultiViewportSwapchain2"}, 1);
  54. AZ::TickBus::Handler::BusConnect();
  55. AZ::RHI::RHISystemNotificationBus::Handler::BusConnect();
  56. }
  57. void MultiViewportSwapchainComponent::CreateScopeForWindow(AZStd::shared_ptr<AZ::RPI::WindowContext>& windowContext, const AZ::RHI::ScopeId& swapchainScope, uint32_t shift)
  58. {
  59. struct ScopeData
  60. {
  61. RPI::WindowContext* u_windowContext;
  62. uint32_t u_shift;
  63. };
  64. const auto prepareFunction = [this](RHI::FrameGraphInterface frameGraph, ScopeData& userData)
  65. {
  66. RHI::ClearValue clearValue = SelectClearColor(m_timeInSeconds, userData.u_shift);
  67. RPI::WindowContext& windowContext = *userData.u_windowContext;
  68. // Handle the case where the window may have closed
  69. if (windowContext.GetSwapChain() == nullptr)
  70. {
  71. return;
  72. }
  73. // Binds the swapchain as a color attachment.
  74. {
  75. RHI::ImageScopeAttachmentDescriptor descriptor;
  76. if (userData.u_shift)
  77. {
  78. descriptor.m_attachmentId = windowContext.GetSwapChainAttachmentId();
  79. }
  80. else
  81. {
  82. descriptor.m_attachmentId = m_outputAttachmentId;
  83. }
  84. descriptor.m_loadStoreAction.m_loadAction = RHI::AttachmentLoadAction::Clear;
  85. descriptor.m_loadStoreAction.m_clearValue = clearValue;
  86. frameGraph.UseColorAttachment(descriptor);
  87. }
  88. };
  89. RHI::EmptyCompileFunction<ScopeData> compileFunction;
  90. RHI::EmptyExecuteFunction<ScopeData> executeFunction;
  91. m_scopeProducers.emplace_back(
  92. aznew RHI::ScopeProducerFunction<
  93. ScopeData,
  94. decltype(prepareFunction),
  95. decltype(compileFunction),
  96. decltype(executeFunction)>(
  97. swapchainScope,
  98. ScopeData{ windowContext.get(), shift },
  99. prepareFunction,
  100. compileFunction,
  101. executeFunction));
  102. }
  103. void MultiViewportSwapchainComponent::CreateClearColors()
  104. {
  105. m_clearValues.emplace_back(RHI::ClearValue::CreateVector4Float(1.0f, 0.0f, 0.0f, 1.0f));
  106. m_clearValues.emplace_back(RHI::ClearValue::CreateVector4Float(0.0f, 1.0f, 0.0f, 1.0f));
  107. m_clearValues.emplace_back(RHI::ClearValue::CreateVector4Float(0.0f, 0.0f, 1.0f, 1.0f));
  108. m_clearValues.emplace_back(RHI::ClearValue::CreateVector4Float(0.0f, 0.0f, 0.0f, 1.0f));
  109. m_clearValues.emplace_back(RHI::ClearValue::CreateVector4Float(1.0f, 1.0f, 1.0f, 1.0f));
  110. }
  111. AZ::RHI::ClearValue MultiViewportSwapchainComponent::SelectClearColor(uint32_t time, uint32_t shift)
  112. {
  113. AZ::RHI::ClearValue clearValue;
  114. const u32 colorIndex = (time + shift) % m_numberOfClearColors;
  115. return m_clearValues[colorIndex];
  116. }
  117. void MultiViewportSwapchainComponent::Deactivate()
  118. {
  119. if (m_nativeWindow2 && m_nativeWindow2->IsActive())
  120. {
  121. m_nativeWindow2->Deactivate();
  122. }
  123. m_clearValues.clear();
  124. m_scopeProducers.clear();
  125. m_windowContext2 = nullptr;
  126. m_windowContext = nullptr;
  127. AZ::RHI::RHISystemNotificationBus::Handler::BusDisconnect();
  128. AZ::TickBus::Handler::BusDisconnect();
  129. }
  130. void MultiViewportSwapchainComponent::OnWindowClosed()
  131. {
  132. if (m_nativeWindow2 && m_nativeWindow2->IsActive())
  133. {
  134. m_nativeWindow2->Deactivate();
  135. }
  136. }
  137. void MultiViewportSwapchainComponent::OnTick(float deltaTime, AZ::ScriptTimePoint time)
  138. {
  139. AZ_UNUSED(deltaTime);
  140. m_timeInSeconds = static_cast<uint32_t>(time.GetSeconds());
  141. }
  142. } // namespace AzRHISample