Parcourir la source

Fix crash in Vulkan when minimizing window on Windows (#19038)

* Fix crash in Vulkan when minimizing window on Windows

Signed-off-by: kiotk <[email protected]>

* Removed redundant code to enhance maintainability

Signed-off-by: kiotk <[email protected]>

---------

Signed-off-by: kiotk <[email protected]>
kiotk il y a 1 mois
Parent
commit
4076a9d176

+ 6 - 0
Code/Framework/AzFramework/AzFramework/Windowing/WindowBus.h

@@ -158,6 +158,12 @@ namespace AzFramework
         //! This is called when the window's desired render resolution is changed.
         virtual void OnResolutionChanged(uint32_t width, uint32_t height) { AZ_UNUSED(width); AZ_UNUSED(height); };
 
+        //! This is called when the window is minimized.
+        virtual void OnWindowMinimized() {};
+
+        //! This is called when the window is restored from minimized.
+        virtual void OnWindowRestored() {};
+
         //! This is called if the window's underyling DPI scaling factor changes.
         virtual void OnDpiScaleFactorChanged(float dpiScaleFactor) { AZ_UNUSED(dpiScaleFactor); }
 

+ 25 - 4
Code/Framework/AzFramework/Platform/Windows/AzFramework/Windowing/NativeWindow_Windows.cpp

@@ -266,6 +266,14 @@ namespace AzFramework
 
         switch (message)
         {
+        case WM_GETMINMAXINFO:
+        {
+            MINMAXINFO* minMaxInfo = reinterpret_cast<MINMAXINFO*>(lParam);
+            minMaxInfo->ptMinTrackSize.x = static_cast<LONG>(MIN_WINDOW_WIDTH);
+            minMaxInfo->ptMinTrackSize.y = static_cast<LONG>(MIN_WINDOW_HEIGHT);
+
+            return 0;
+        }
         case WM_CLOSE:
         {
             nativeWindowImpl->Deactivate();
@@ -273,10 +281,23 @@ namespace AzFramework
         }
         case WM_SIZE:
         {
-            const uint16_t newWidth = LOWORD(lParam);
-            const uint16_t newHeight = HIWORD(lParam);
-            
-            nativeWindowImpl->WindowSizeChanged(static_cast<uint32_t>(newWidth), static_cast<uint32_t>(newHeight));
+            const uint32_t m_width  = static_cast<uint32_t>(LOWORD(lParam));
+            const uint32_t m_height = static_cast<uint32_t>(HIWORD(lParam));
+
+            if (wParam == SIZE_MINIMIZED)
+            {
+                WindowNotificationBus::Event(nativeWindowImpl->GetWindowHandle(), &AzFramework::WindowNotifications::OnWindowMinimized);
+            }
+            else if (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED)
+            {
+                WindowNotificationBus::Event(nativeWindowImpl->GetWindowHandle(), &AzFramework::WindowNotifications::OnWindowRestored);
+                nativeWindowImpl->WindowSizeChanged(m_width, m_height);
+                WindowNotificationBus::Event(nativeWindowImpl->GetWindowHandle(), &AzFramework::WindowNotifications::OnWindowResized, m_width, m_height);
+            }
+            else if(m_width > 0 && m_height > 0)
+            {
+                nativeWindowImpl->WindowSizeChanged(m_width, m_height);
+            }
             break;
         }
         case WM_INPUT:

+ 2 - 0
Code/Framework/AzFramework/Platform/Windows/AzFramework/Windowing/NativeWindow_Windows.h

@@ -68,5 +68,7 @@ namespace AzFramework
         using GetDpiForWindowType = UINT(*)(HWND hwnd);
         GetDpiForWindowType m_getDpiFunction = nullptr;
         uint32_t m_mainDisplayRefreshRate = 0;
+        static constexpr uint32_t MIN_WINDOW_WIDTH  = 320;
+        static constexpr uint32_t MIN_WINDOW_HEIGHT = 180;
     };
 } // namespace AzFramework

+ 5 - 0
Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/Specific/SwapChainPass.h

@@ -63,6 +63,10 @@ namespace AZ
             void OnResolutionChanged(uint32_t width, uint32_t height) override;
             // Swapchain may get resized when window is resized
             void OnWindowResized(uint32_t width, uint32_t height) override;
+            // Window is minimized
+            void OnWindowMinimized() override;
+            // Window is restored
+            void OnWindowRestored() override;
 
         private:
             // Sets up a swap chain PassAttachment using the swap chain id from the window context 
@@ -83,6 +87,7 @@ namespace AZ
             RHI::Scissor m_scissorState;
             RHI::Viewport m_viewportState;
             ViewType m_viewType = ViewType::Default;
+            bool m_isMinimized = false;
         };
 
     }   // namespace RPI

+ 20 - 2
Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Specific/SwapChainPass.cpp

@@ -123,7 +123,7 @@ namespace AZ
 
         void SwapChainPass::BuildInternal()
         {
-            if (m_windowContext->GetSwapChainsSize() == 0 || m_windowContext->GetSwapChain(m_viewType) == nullptr)
+            if (m_windowContext->GetSwapChainsSize() == 0 || m_windowContext->GetSwapChain(m_viewType) == nullptr || m_isMinimized)
             {
                 return;
             }
@@ -163,7 +163,7 @@ namespace AZ
         void SwapChainPass::FrameBeginInternal(FramePrepareParams params)
         {
             if (m_windowContext->GetSwapChainsSize() == 0 || m_windowContext->GetSwapChain(m_viewType) == nullptr ||
-                m_windowContext->GetSwapChain(m_viewType)->GetImageCount() == 0)
+                m_windowContext->GetSwapChain(m_viewType)->GetImageCount() == 0 || m_isMinimized)
             {
                 return;
             }
@@ -202,14 +202,32 @@ namespace AZ
         
         void SwapChainPass::OnResolutionChanged([[maybe_unused]] uint32_t width, [[maybe_unused]] uint32_t height)
         {
+            if (m_isMinimized)
+            {
+                return;
+            }
             QueueForBuildAndInitialization();
         }
 
         void SwapChainPass::OnWindowResized([[maybe_unused]] uint32_t width, [[maybe_unused]] uint32_t height)
         {
+            if (m_isMinimized)
+            {
+                return;
+            }
             QueueForBuildAndInitialization();
         }
 
+        void SwapChainPass::OnWindowMinimized()
+        {
+            m_isMinimized = true;
+        }
+
+        void SwapChainPass::OnWindowRestored()
+        {
+            m_isMinimized = false;
+        }
+
         void SwapChainPass::ReadbackSwapChain(AZStd::shared_ptr<AttachmentReadback> readback)
         {
             if (m_swapChainAttachment)