MultiGPURPIExampleComponent.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  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 <AtomSampleViewerOptions.h>
  9. #include <MultiGPURPIExampleComponent.h>
  10. #include <Atom/Component/DebugCamera/CameraComponent.h>
  11. #include <Atom/Component/DebugCamera/NoClipControllerComponent.h>
  12. #include <Atom/RHI/RHISystemInterface.h>
  13. #include <Atom/RPI.Public/Pass/PassFilter.h>
  14. #include <Atom/RPI.Public/RPISystemInterface.h>
  15. #include <Atom/RPI.Public/RenderPipeline.h>
  16. #include <Atom/RPI.Public/Scene.h>
  17. #include <Atom/RPI.Public/ViewProviderBus.h>
  18. #include <Atom/RPI.Reflect/Asset/AssetUtils.h>
  19. #include <Atom/RPI.Reflect/Model/ModelAsset.h>
  20. #include <Atom/Feature/ImGui/ImGuiUtils.h>
  21. #include <AzCore/Math/MatrixUtils.h>
  22. #include <Automation/ScriptableImGui.h>
  23. #include <Automation/ScriptRunnerBus.h>
  24. #include <AzCore/Component/Entity.h>
  25. #include <AzFramework/Components/TransformComponent.h>
  26. #include <AzFramework/Scene/SceneSystemInterface.h>
  27. #include <AzFramework/Entity/GameEntityContextComponent.h>
  28. #include <EntityUtilityFunctions.h>
  29. #include <SampleComponentConfig.h>
  30. #include <SampleComponentManager.h>
  31. #include <Utils/Utils.h>
  32. #include <RHI/BasicRHIComponent.h>
  33. namespace AtomSampleViewer
  34. {
  35. using namespace AZ;
  36. void MultiGPURPIExampleComponent::Reflect(AZ::ReflectContext* context)
  37. {
  38. if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  39. {
  40. serializeContext->Class<MultiGPURPIExampleComponent, AZ::Component>()
  41. ->Version(0)
  42. ;
  43. }
  44. }
  45. MultiGPURPIExampleComponent::MultiGPURPIExampleComponent()
  46. {
  47. }
  48. void MultiGPURPIExampleComponent::Activate()
  49. {
  50. AZ::TickBus::Handler::BusConnect();
  51. AZ::Render::Bootstrap::DefaultWindowNotificationBus::Handler::BusConnect();
  52. // save original render pipeline first and remove it from the scene
  53. m_originalPipeline = m_scene->GetDefaultRenderPipeline();
  54. m_scene->RemoveRenderPipeline(m_originalPipeline->GetId());
  55. // add the multi-GPU pipeline
  56. const AZStd::string pipelineName("MultiGPUPipeline");
  57. AZ::RPI::RenderPipelineDescriptor pipelineDesc;
  58. pipelineDesc.m_name = pipelineName;
  59. pipelineDesc.m_rootPassTemplate = "MultiGPUPipeline";
  60. m_pipeline = AZ::RPI::RenderPipeline::CreateRenderPipelineForWindow(pipelineDesc, *m_windowContext);
  61. m_scene->AddRenderPipeline(m_pipeline);
  62. const AZStd::string copyPipelineName("MultiGPUCopyTestPipeline");
  63. AZ::RPI::RenderPipelineDescriptor copyPipelineDesc;
  64. copyPipelineDesc.m_name = copyPipelineName;
  65. copyPipelineDesc.m_rootPassTemplate = "MultiGPUCopyTestPipeline";
  66. m_copyPipeline = AZ::RPI::RenderPipeline::CreateRenderPipelineForWindow(copyPipelineDesc, *m_windowContext);
  67. m_imguiScope = AZ::Render::ImGuiActiveContextScope::FromPass({ "MultiGPUPipeline", "ImGuiPass" });
  68. }
  69. void MultiGPURPIExampleComponent::Deactivate()
  70. {
  71. // remove cb pipeline before adding original pipeline.
  72. if (!m_pipeline)
  73. {
  74. return;
  75. }
  76. m_imguiScope = {}; // restores previous ImGui context.
  77. if (m_currentlyUsingCopyPipline)
  78. {
  79. m_scene->RemoveRenderPipeline(m_copyPipeline->GetId());
  80. }
  81. else
  82. {
  83. m_scene->RemoveRenderPipeline(m_pipeline->GetId());
  84. }
  85. m_scene->AddRenderPipeline(m_originalPipeline);
  86. m_pipeline = nullptr;
  87. m_copyPipeline = nullptr;
  88. m_useCopyPipeline = false;
  89. m_currentlyUsingCopyPipline = false;
  90. m_migrate = false;
  91. m_currentlyMigrated = false;
  92. AZ::Render::Bootstrap::DefaultWindowNotificationBus::Handler::BusDisconnect();
  93. AZ::TickBus::Handler::BusDisconnect();
  94. }
  95. void MultiGPURPIExampleComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint timePoint)
  96. {
  97. if (m_currentlyUsingCopyPipline != m_useCopyPipeline)
  98. {
  99. AZ::RPI::RenderPipelinePtr prevPipeline = m_scene->GetDefaultRenderPipeline();
  100. if (m_useCopyPipeline)
  101. {
  102. m_copyPipeline->GetRootPass()->SetEnabled(true);
  103. m_scene->AddRenderPipeline(m_copyPipeline);
  104. m_scene->RemoveRenderPipeline(prevPipeline->GetId());
  105. m_imguiScope = {};
  106. m_imguiScope = AZ::Render::ImGuiActiveContextScope::FromPass({ m_copyPipeline->GetId().GetCStr(), "ImGuiPass" });
  107. }
  108. else
  109. {
  110. m_pipeline->GetRootPass()->SetEnabled(true);
  111. m_scene->AddRenderPipeline(m_pipeline);
  112. m_scene->RemoveRenderPipeline(prevPipeline->GetId());
  113. m_imguiScope = {};
  114. m_imguiScope = AZ::Render::ImGuiActiveContextScope::FromPass({ m_pipeline->GetId().GetCStr(), "ImGuiPass" });
  115. }
  116. m_currentlyUsingCopyPipline = m_useCopyPipeline;
  117. }
  118. if (m_currentlyMigrated != m_migrate)
  119. {
  120. AZ::RPI::PassFilter trianglePassFilter = AZ::RPI::PassFilter::CreateWithPassName(Name("TrianglePass2"), m_scene);
  121. AZ::RPI::PassFilter copyPassFilter = AZ::RPI::PassFilter::CreateWithPassName(Name("CopyPass"), m_scene);
  122. AZ::RPI::PassFilter compositePassFilter = AZ::RPI::PassFilter::CreateWithPassName(Name("CompositePass"), m_scene);
  123. RPI::RenderPass* trianglePass =
  124. azrtti_cast<RPI::RenderPass*>(AZ::RPI::PassSystemInterface::Get()->FindFirstPass(trianglePassFilter));
  125. RPI::Pass* copyPass = AZ::RPI::PassSystemInterface::Get()->FindFirstPass(copyPassFilter);
  126. RPI::Pass* compositePass = AZ::RPI::PassSystemInterface::Get()->FindFirstPass(compositePassFilter);
  127. AZ_Assert(trianglePass && copyPass && compositePass, "Couldn't find passes");
  128. if (m_migrate)
  129. {
  130. trianglePass->SetDeviceIndex(0);
  131. copyPass->SetEnabled(false);
  132. auto& attachmentBinding = compositePass->GetInputBinding(1);
  133. attachmentBinding.m_connectedBinding = &trianglePass->GetOutputBinding(0);
  134. attachmentBinding.UpdateConnection(false);
  135. }
  136. else
  137. {
  138. trianglePass->SetDeviceIndex(1);
  139. copyPass->SetEnabled(true);
  140. auto& attachmentBinding = compositePass->GetInputBinding(1);
  141. attachmentBinding.m_connectedBinding = &copyPass->GetOutputBinding(0);
  142. attachmentBinding.UpdateConnection(false);
  143. }
  144. m_currentlyMigrated = m_migrate;
  145. }
  146. if (m_imguiSidebar.Begin())
  147. {
  148. ImGui::Spacing();
  149. ImGui::Checkbox("Use copy test pipeline", &m_useCopyPipeline);
  150. if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
  151. {
  152. ImGui::SetTooltip("Add additional device to device copy passes to test the modes of the copy pass:\n"
  153. "image to buffer\n"
  154. "buffer to buffer\n"
  155. "buffer to image\n"
  156. "image to image\n");
  157. }
  158. if (!m_useCopyPipeline)
  159. {
  160. ImGui::Checkbox("Migrate", &m_migrate);
  161. if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
  162. {
  163. ImGui::SetTooltip("Migrate all passes to the first GPU.");
  164. }
  165. }
  166. m_imguiSidebar.End();
  167. }
  168. }
  169. void MultiGPURPIExampleComponent::DefaultWindowCreated()
  170. {
  171. AZ::Render::Bootstrap::DefaultWindowBus::BroadcastResult(m_windowContext,
  172. &AZ::Render::Bootstrap::DefaultWindowBus::Events::GetDefaultWindowContext);
  173. }
  174. } // namespace AtomSampleViewer