diff --git a/src/graphics/presentation/window/swapchain.cpp b/src/graphics/presentation/window/swapchain.cpp index 51de9d4c9..3fb2b78e8 100644 --- a/src/graphics/presentation/window/swapchain.cpp +++ b/src/graphics/presentation/window/swapchain.cpp @@ -279,6 +279,7 @@ public: void Create(); void Recreate(bool surface_lost = false); + [[nodiscard]] bool NeedsResize() const; [[nodiscard]] Status AcquireNextImage(); [[nodiscard]] bool PrepareSystemOverlay(); void RecordPresentCommands(CommandBuffer& command, VulkanImage& source, @@ -298,6 +299,8 @@ private: vk::SwapchainKHR m_handle = nullptr; vk::Format m_format = vk::Format::eUndefined; vk::Extent2D m_extent {}; + // Drawable pixel size observed when this swapchain was created. + vk::Extent2D m_window_extent {}; std::vector m_images; std::vector m_image_views; std::vector m_image_acquired; @@ -357,19 +360,25 @@ void Swapchain::Create() { EXIT_IF(graphics.device == nullptr); EXIT_IF(m_window.surface == nullptr); - Common::LockGuard lock(m_window.mutex); - EXIT_IF(graphics.screen_width == 0); - EXIT_IF(graphics.screen_height == 0); + // Capture the size before querying surface capabilities. If the window changes + // during creation, the next presentation will detect the newer size. + { + Common::LockGuard lock(m_window.mutex); + m_window_extent = {graphics.screen_width, graphics.screen_height}; + } + EXIT_IF(m_window_extent.width == 0); + EXIT_IF(m_window_extent.height == 0); + m_window.RefreshSurfaceCapabilities(); const auto& surface = m_window.surface_capabilities; EXIT_NOT_IMPLEMENTED(surface.formats.empty()); m_extent = surface.capabilities.currentExtent; if (m_extent.width == std::numeric_limits::max()) { m_extent.width = - std::clamp(graphics.screen_width, surface.capabilities.minImageExtent.width, + std::clamp(m_window_extent.width, surface.capabilities.minImageExtent.width, surface.capabilities.maxImageExtent.width); m_extent.height = - std::clamp(graphics.screen_height, surface.capabilities.minImageExtent.height, + std::clamp(m_window_extent.height, surface.capabilities.minImageExtent.height, surface.capabilities.maxImageExtent.height); } uint32_t image_count = surface.capabilities.minImageCount + 1; @@ -473,8 +482,8 @@ void Swapchain::Create() { graphics.device.createSemaphore(&semaphore_info, nullptr, &m_render_complete[i]), "create swapchain render-complete semaphore"); } - m_image_index = static_cast(-1); - m_frame_index = 0; + m_image_index = static_cast(-1); + m_frame_index = 0; } Swapchain::~Swapchain() { @@ -515,11 +524,12 @@ void Swapchain::Destroy() { graphics.device.destroySwapchainKHR(m_handle, nullptr); } - m_handle = nullptr; - m_format = vk::Format::eUndefined; - m_extent = {}; - m_image_index = static_cast(-1); - m_frame_index = 0; + m_handle = nullptr; + m_format = vk::Format::eUndefined; + m_extent = {}; + m_window_extent = {}; + m_image_index = static_cast(-1); + m_frame_index = 0; m_images.clear(); m_image_views.clear(); m_image_acquired.clear(); @@ -539,10 +549,15 @@ void Swapchain::Recreate(bool surface_lost) { m_window.RecreateSurface(); #endif } - m_window.RefreshSurfaceCapabilities(); Create(); } +bool Swapchain::NeedsResize() const { + Common::LockGuard lock(m_window.mutex); + return m_window_extent.width != m_window.graphic_ctx.screen_width || + m_window_extent.height != m_window.graphic_ctx.screen_height; +} + Swapchain::Status Swapchain::AcquireNextImage() { EXIT_IF(m_handle == nullptr || m_frame_index >= m_image_acquired.size()); m_image_index = static_cast(-1); @@ -768,6 +783,10 @@ void Presenter::Present(Frame& frame, bool reuse) { const auto overlay_visual = GetSystemOverlayVisualState(); auto& swapchain = m_impl->swapchain; + // Some window systems keep presenting an old swapchain after a resize. + if (swapchain.NeedsResize()) { + m_impl->RecoverSwapchain(Swapchain::Status::Recreate); + } for (uint32_t attempt = 0; attempt < 2; attempt++) { auto status = swapchain.AcquireNextImage(); if (status != Swapchain::Status::Success) { diff --git a/src/graphics/presentation/window/window.cpp b/src/graphics/presentation/window/window.cpp index ef4e8b2e2..e223eca45 100644 --- a/src/graphics/presentation/window/window.cpp +++ b/src/graphics/presentation/window/window.cpp @@ -783,14 +783,13 @@ static void WindowCreate(WindowContext& context) { } SDL_SetWindowPosition(context.window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); - SDL_SetWindowResizable(context.window, false); HostInputInit(context.window); InitializeSystemOverlayInput(context.window); context.UpdateIcon(); } uint32_t WindowContext::InitialWindowFlags(bool fullscreen) noexcept { - auto flags = static_cast(SDL_WINDOW_VULKAN); + auto flags = static_cast(SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE); if (fullscreen) { flags |= static_cast(SDL_WINDOW_FULLSCREEN); }