ViewportContext.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  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/RPI.Public/ViewportContext.h>
  9. #include <Atom/RPI.Public/RenderPipeline.h>
  10. #include <Atom/RPI.Public/ViewportContextBus.h>
  11. #include <Atom/RPI.Public/ViewportContextManager.h>
  12. #include <Atom/RPI.Public/View.h>
  13. namespace AZ
  14. {
  15. namespace RPI
  16. {
  17. ViewportContext::ViewportContext(ViewportContextManager* manager, AzFramework::ViewportId id, const AZ::Name& name, RHI::Device& device, AzFramework::NativeWindowHandle nativeWindow, ScenePtr renderScene)
  18. : m_rootScene(nullptr)
  19. , m_id(id)
  20. , m_windowContext(AZStd::make_shared<WindowContext>())
  21. , m_manager(manager)
  22. , m_name(name)
  23. , m_viewportSize(1, 1)
  24. {
  25. m_windowContext->Initialize(device, nativeWindow);
  26. AzFramework::WindowRequestBus::EventResult(
  27. m_viewportSize,
  28. nativeWindow,
  29. &AzFramework::WindowRequestBus::Events::GetRenderResolution);
  30. AzFramework::WindowRequestBus::EventResult(
  31. m_viewportDpiScaleFactor,
  32. nativeWindow,
  33. &AzFramework::WindowRequestBus::Events::GetDpiScaleFactor);
  34. AzFramework::WindowNotificationBus::Handler::BusConnect(nativeWindow);
  35. AzFramework::ViewportRequestBus::Handler::BusConnect(id);
  36. // Clamp the viewport size to a minimum of (1, 1). Otherwise, it's very easy for consumers of this API to miss
  37. // that they need to guard against (0, 0) when the viewport gets hidden.
  38. m_viewportSize.m_height = AZStd::max(m_viewportSize.m_height, 1u);
  39. m_viewportSize.m_width = AZStd::max(m_viewportSize.m_width, 1u);
  40. m_currentPipelines.resize(MaxViewTypes);
  41. m_viewChangedEvents.resize(MaxViewTypes);
  42. m_viewGroup = AZStd::make_shared<ViewGroup>();
  43. m_viewGroup->Init(ViewGroup::Descriptor{ nullptr, nullptr });
  44. SetRenderScene(renderScene);
  45. }
  46. ViewportContext::~ViewportContext()
  47. {
  48. m_aboutToBeDestroyedEvent.Signal(m_id);
  49. AzFramework::WindowNotificationBus::Handler::BusDisconnect();
  50. AzFramework::ViewportRequestBus::Handler::BusDisconnect();
  51. for (const auto& pipeline : m_currentPipelines)
  52. {
  53. if (pipeline)
  54. {
  55. pipeline->RemoveFromRenderTick();
  56. pipeline->RemoveFromScene();
  57. }
  58. }
  59. m_currentPipelines.clear();
  60. m_viewChangedEvents.clear();
  61. m_manager->UnregisterViewportContext(m_id);
  62. m_windowContext->Shutdown();
  63. }
  64. AzFramework::ViewportId ViewportContext::GetId() const
  65. {
  66. return m_id;
  67. }
  68. AzFramework::NativeWindowHandle ViewportContext::GetWindowHandle() const
  69. {
  70. return m_windowContext->GetWindowHandle();
  71. }
  72. WindowContextSharedPtr ViewportContext::GetWindowContext()
  73. {
  74. return m_windowContext;
  75. }
  76. ScenePtr ViewportContext::GetRenderScene()
  77. {
  78. return m_rootScene;
  79. }
  80. void ViewportContext::SetRenderScene(ScenePtr scene)
  81. {
  82. if (m_rootScene != scene)
  83. {
  84. if (m_rootScene)
  85. {
  86. SceneNotificationBus::Handler::BusDisconnect(m_rootScene->GetId());
  87. }
  88. else
  89. {
  90. // If the scene was empty, we should save the default view from this scene as default view for the context.
  91. for (uint32_t i = 0; i < MaxViewTypes; i++)
  92. {
  93. auto renderPipeline =
  94. scene->FindRenderPipelineForWindow(m_windowContext->GetWindowHandle(), static_cast<ViewType>(i));
  95. if (renderPipeline)
  96. {
  97. if (AZ::RPI::ViewPtr pipelineView = renderPipeline->GetDefaultView(); pipelineView)
  98. {
  99. m_viewGroup->SetView(pipelineView, static_cast<ViewType>(i));
  100. }
  101. }
  102. }
  103. }
  104. m_rootScene = scene;
  105. if (m_rootScene)
  106. {
  107. SceneNotificationBus::Handler::BusConnect(m_rootScene->GetId());
  108. }
  109. for (uint32_t i = 0; i < MaxViewTypes; i++)
  110. {
  111. m_currentPipelines[i].reset();
  112. UpdatePipelineView(i);
  113. }
  114. }
  115. m_sceneChangedEvent.Signal(scene);
  116. }
  117. // This function (called from BootstrapSystemComponent::OnTick) controls the
  118. // render pipelines to render or not for the launcher. In the editor the pipelines
  119. // are controlled from EditorViewportWidget::UpdateScene.
  120. void ViewportContext::RenderTick()
  121. {
  122. auto renderPipelineOnce = [](RenderPipelinePtr& pipeline)
  123. {
  124. // add the current pipeline to next render tick if it's not already added.
  125. if (pipeline && pipeline->GetRenderMode() != RenderPipeline::RenderMode::RenderOnce)
  126. {
  127. pipeline->AddToRenderTickOnce();
  128. }
  129. };
  130. auto stopRenderingPipeline = [](RenderPipelinePtr& pipeline)
  131. {
  132. if (pipeline && pipeline->GetRenderMode() != RenderPipeline::RenderMode::NoRender)
  133. {
  134. pipeline->RemoveFromRenderTick();
  135. }
  136. };
  137. if (auto* xrSystem = AZ::RPI::RPISystemInterface::Get()->GetXRSystem())
  138. {
  139. // Check wheter to render default pipeline on host or not.
  140. if (xrSystem->GetRHIXRRenderingInterface()->IsDefaultRenderPipelineNeeded())
  141. {
  142. if (xrSystem->GetRHIXRRenderingInterface()->IsDefaultRenderPipelineEnabledOnHost())
  143. {
  144. renderPipelineOnce(m_currentPipelines[static_cast<size_t>(AZ::RPI::ViewType::Default)]);
  145. }
  146. else
  147. {
  148. stopRenderingPipeline(m_currentPipelines[static_cast<size_t>(AZ::RPI::ViewType::Default)]);
  149. }
  150. }
  151. // Render XR pipelines
  152. for (AZ::u32 i = 0; i < xrSystem->GetNumViews(); i++)
  153. {
  154. const AZ::RPI::ViewType viewType = (i == 0) ? AZ::RPI::ViewType::XrLeft : AZ::RPI::ViewType::XrRight;
  155. renderPipelineOnce(m_currentPipelines[static_cast<size_t>(viewType)]);
  156. }
  157. }
  158. else
  159. {
  160. // Render default pipeline
  161. renderPipelineOnce(m_currentPipelines[static_cast<size_t>(AZ::RPI::ViewType::Default)]);
  162. }
  163. }
  164. void ViewportContext::OnBeginPrepareRender()
  165. {
  166. AZ_PROFILE_FUNCTION(RPI);
  167. ViewportContextNotificationBus::Event(GetName(), &ViewportContextNotificationBus::Events::OnRenderTick);
  168. ViewportContextIdNotificationBus::Event(GetId(), &ViewportContextIdNotificationBus::Events::OnRenderTick);
  169. }
  170. void ViewportContext::OnEndPrepareRender()
  171. {
  172. AZ_PROFILE_FUNCTION(RPI);
  173. ViewportContextNotificationBus::Event(GetName(), &ViewportContextNotificationBus::Events::WaitForRender);
  174. ViewportContextIdNotificationBus::Event(GetId(), &ViewportContextIdNotificationBus::Events::WaitForRender);
  175. }
  176. AZ::Name ViewportContext::GetName() const
  177. {
  178. return m_name;
  179. }
  180. ViewGroupPtr ViewportContext::GetViewGroup()
  181. {
  182. return m_viewGroup;
  183. }
  184. ConstViewGroupPtr ViewportContext::GetViewGroup() const
  185. {
  186. return m_viewGroup;
  187. }
  188. ViewPtr ViewportContext::GetDefaultView()
  189. {
  190. return m_viewGroup->GetView();
  191. }
  192. ConstViewPtr ViewportContext::GetDefaultView() const
  193. {
  194. return m_viewGroup->GetView();
  195. }
  196. ViewPtr ViewportContext::GetStereoscopicView(AZ::RPI::ViewType viewType)
  197. {
  198. return m_viewGroup->GetView(viewType);
  199. }
  200. ConstViewPtr ViewportContext::GetStereoscopicView(AZ::RPI::ViewType viewType) const
  201. {
  202. return m_viewGroup->GetView(viewType);
  203. }
  204. AzFramework::WindowSize ViewportContext::GetViewportSize() const
  205. {
  206. return m_viewportSize;
  207. }
  208. float ViewportContext::GetDpiScalingFactor() const
  209. {
  210. return m_viewportDpiScaleFactor;
  211. }
  212. void ViewportContext::ConnectSizeChangedHandler(SizeChangedEvent::Handler& handler)
  213. {
  214. handler.Connect(m_sizeChangedEvent);
  215. }
  216. void ViewportContext::ConnectDpiScalingFactorChangedHandler(ScalarChangedEvent::Handler& handler)
  217. {
  218. handler.Connect(m_dpiScalingFactorChangedEvent);
  219. }
  220. void ViewportContext::ConnectViewMatrixChangedHandler(MatrixChangedEvent::Handler& handler, ViewType viewType)
  221. {
  222. m_viewGroup->ConnectViewMatrixChangedEvent(handler, viewType);
  223. }
  224. void ViewportContext::ConnectProjectionMatrixChangedHandler(MatrixChangedEvent::Handler& handler, ViewType viewType)
  225. {
  226. m_viewGroup->ConnectProjectionMatrixChangedEvent(handler, viewType);
  227. }
  228. void ViewportContext::ConnectSceneChangedHandler(SceneChangedEvent::Handler& handler)
  229. {
  230. handler.Connect(m_sceneChangedEvent);
  231. }
  232. void ViewportContext::ConnectCurrentPipelineChangedHandler(PipelineChangedEvent::Handler& handler)
  233. {
  234. handler.Connect(m_currentPipelineChangedEvent);
  235. }
  236. void ViewportContext::ConnectDefaultViewChangedHandler(ViewChangedEvent::Handler& handler)
  237. {
  238. handler.Connect(m_viewChangedEvents[DefaultViewType]);
  239. }
  240. void ViewportContext::ConnectAboutToBeDestroyedHandler(ViewportIdEvent::Handler& handler)
  241. {
  242. handler.Connect(m_aboutToBeDestroyedEvent);
  243. }
  244. const AZ::Matrix4x4& ViewportContext::GetCameraViewMatrix() const
  245. {
  246. return GetDefaultView()->GetWorldToViewMatrix();
  247. }
  248. AZ::Matrix3x4 ViewportContext::GetCameraViewMatrixAsMatrix3x4() const
  249. {
  250. return GetDefaultView()->GetWorldToViewMatrixAsMatrix3x4();
  251. }
  252. void ViewportContext::SetCameraViewMatrix(const AZ::Matrix4x4& matrix)
  253. {
  254. GetDefaultView()->SetWorldToViewMatrix(matrix);
  255. m_viewGroup->SignalViewMatrixChangedEvent(matrix);
  256. }
  257. const AZ::Matrix4x4& ViewportContext::GetCameraProjectionMatrix() const
  258. {
  259. return GetDefaultView()->GetViewToClipMatrix();
  260. }
  261. void ViewportContext::SetCameraProjectionMatrix(const AZ::Matrix4x4& matrix)
  262. {
  263. GetDefaultView()->SetViewToClipMatrix(matrix);
  264. }
  265. AZ::Transform ViewportContext::GetCameraTransform() const
  266. {
  267. return GetDefaultView()->GetCameraTransform();
  268. }
  269. void ViewportContext::SetCameraTransform(const AZ::Transform& transform)
  270. {
  271. const auto view = GetDefaultView();
  272. view->SetCameraTransform(AZ::Matrix3x4::CreateFromTransform(transform.GetOrthogonalized()));
  273. m_viewGroup->SignalViewMatrixChangedEvent(view->GetWorldToViewMatrix());
  274. }
  275. void ViewportContext::UpdateContextPipelineView(uint32_t viewIndex)
  276. {
  277. ViewType viewType = static_cast<ViewType>(viewIndex);
  278. if (auto view = m_viewGroup->GetView(viewType))
  279. {
  280. m_viewGroup->DisconnectProjectionMatrixHandler(viewType);
  281. m_viewGroup->DisconnectViewMatrixHandler(viewType);
  282. UpdatePipelineView(viewIndex);
  283. m_viewChangedEvents[viewIndex].Signal(view);
  284. m_viewGroup->SignalViewMatrixChangedEvent(view->GetWorldToViewMatrix());
  285. m_viewGroup->SignalProjectionMatrixChangedEvent(view->GetViewToClipMatrix());
  286. m_viewGroup->ConnectViewMatrixChangedHandler(viewType);
  287. m_viewGroup->ConnectProjectionMatrixChangedHandler(viewType);
  288. }
  289. }
  290. void ViewportContext::SetViewGroup(ViewGroupPtr viewGroup)
  291. {
  292. m_viewGroup = viewGroup;
  293. for (uint32_t i = 0; i < MaxViewTypes; i++)
  294. {
  295. UpdateContextPipelineView(i);
  296. }
  297. }
  298. void ViewportContext::UpdatePipelineView(uint32_t viewIndex)
  299. {
  300. ViewPtr pipelineView = m_viewGroup->GetView(static_cast<ViewType>(viewIndex));
  301. if (!pipelineView || !m_rootScene)
  302. {
  303. return;
  304. }
  305. auto& pipeline = m_currentPipelines[viewIndex];
  306. if (!pipeline)
  307. {
  308. pipeline = m_rootScene->FindRenderPipelineForWindow(m_windowContext->GetWindowHandle(), static_cast<ViewType>(viewIndex));
  309. if (pipeline)
  310. {
  311. m_currentPipelineChangedEvent.Signal(pipeline);
  312. }
  313. }
  314. if (pipeline)
  315. {
  316. pipeline->UnregisterView(pipelineView);
  317. pipeline->SetDefaultView(pipelineView);
  318. }
  319. }
  320. RenderPipelinePtr ViewportContext::GetCurrentPipeline()
  321. {
  322. return m_currentPipelines[DefaultViewType];
  323. }
  324. void ViewportContext::OnRenderPipelineChanged(RenderPipeline* pipeline,
  325. SceneNotification::RenderPipelineChangeType changeType)
  326. {
  327. if (changeType == RPI::SceneNotification::RenderPipelineChangeType::Added)
  328. {
  329. // If the pipeline is registered to our window, reset our current pipeline and do a lookup
  330. // Currently, Scene just stores pipelines sequentially in a vector, but we'll attempt to be safe
  331. // in the event prioritization is added later
  332. if (pipeline->GetWindowHandle() == m_windowContext->GetWindowHandle())
  333. {
  334. uint32_t viewIndex = static_cast<uint32_t>(pipeline->GetViewType());
  335. m_currentPipelines[viewIndex].reset();
  336. UpdatePipelineView(viewIndex);
  337. }
  338. }
  339. else if (changeType == RPI::SceneNotification::RenderPipelineChangeType::Removed)
  340. {
  341. uint32_t viewIndex = static_cast<uint32_t>(pipeline->GetViewType());
  342. if (m_currentPipelines[viewIndex].get() == pipeline)
  343. {
  344. m_currentPipelines[viewIndex].reset();
  345. UpdatePipelineView(viewIndex);
  346. }
  347. }
  348. }
  349. void ViewportContext::OnResolutionChanged(uint32_t width, uint32_t height)
  350. {
  351. if (m_viewportSize.m_width != width || m_viewportSize.m_height != height)
  352. {
  353. // Clamp the viewport size to a minimum of (1, 1).
  354. m_viewportSize.m_height = AZStd::max(height, 1u);
  355. m_viewportSize.m_width = AZStd::max(width, 1u);
  356. m_sizeChangedEvent.Signal(m_viewportSize);
  357. }
  358. }
  359. void ViewportContext::OnDpiScaleFactorChanged(float dpiScaleFactor)
  360. {
  361. m_viewportDpiScaleFactor = dpiScaleFactor;
  362. m_dpiScalingFactorChangedEvent.Signal(dpiScaleFactor);
  363. }
  364. } // namespace RPI
  365. } // namespace AZ