Handling Vulkan Swapchain Recreation During Window Resize
Guide to handling Vulkan swapchain recreation during window resize, covering GPU synchronization, resource rebuilding, and recovery from surface loss.
30 Aug 2025, 22:02 UTC

The Problem: Out-of-Date Swapchains
In Vulkan, the swapchain is a collection of buffers used to present images to the screen. Because these buffers are tied to the specific dimensions of the window surface, any change in window size renders the existing swapchain "out of date." Attempting to present to an outdated swapchain results in a VK_ERROR_OUT_OF_DATE_KHR error, and continuing to use the old image extents will cause visual corruption or application crashes.
The Takeaway: To maintain a stable render loop, you must detect the resize event, synchronize the GPU to ensure no resources are in use, recreate the swapchain using the old one as a template for efficiency, and rebuild all dependent resources (image views, framebuffers, and depth buffers) to match the new dimensions.
Prerequisites
- A functional Vulkan logical device with graphics and present queues.
- An existing swapchain and associated resources (image views, framebuffers).
- A window system integration (WSI) like GLFW or Win32 that provides resize callbacks.
- Validation layers enabled to detect mismatched extent errors during development.
Recreation Procedure
- Detect the Resize Event: Use your windowing library's callback to set a boolean flag (e.g.,
framebufferResized = true). Do not recreate the swapchain inside the callback; handle it at the start of your next frame logic to avoid threading conflicts. - Synchronize the GPU: You cannot destroy resources currently being read or written by the GPU. Use
vkDeviceWaitIdleto ensure all pending queues are empty.// Run on the main render thread vkDeviceWaitIdle(logicalDevice); - Query New Surface Extents: Retrieve the updated dimensions from the physical device. This ensures you use the actual surface size rather than the window size, which may differ on high-DPI displays.
VkSurfaceCapabilitiesKHR caps; vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &caps); VkExtent2D newExtent = caps.currentExtent; - Create the New Swapchain: Pass the handle of the current swapchain to the
oldSwapchainfield ofVkSwapchainCreateInfoKHR. This allows the driver to reuse internal memory and speeds up the transition.VkSwapchainCreateInfoKHR swapInfo = {}; swapInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; swapInfo.surface = surface; swapInfo.imageExtent = newExtent; swapInfo.oldSwapchain = oldSwapchain; // Optimization: reuse existing resources // ... other required fields (format, presentMode, etc.) VkSwapchainKHR newSwapchain; VkResult result = vkCreateSwapchainKHR(logicalDevice, &swapInfo, nullptr, &newSwapchain); - Cleanup and Update: Destroy the old swapchain only after the new one is successfully created. Then, update your local handle.
vkDestroySwapchainKHR(logicalDevice, oldSwapchain, nullptr); oldSwapchain = newSwapchain; - Rebuild Dependent Resources: This is the most common point of failure. You must recreate everything that depends on the swapchain's image handles or its extent:
- Image Views: Create new
VkImageViewhandles for the new swapchain images. - Depth/Resolve Images: If you use a depth buffer, it must be destroyed and recreated to match
newExtent. - Framebuffers: Recreate
VkFramebufferobjects using the new image views. - Command Buffers: If your command buffers are recorded with hard-coded viewport/scissor dimensions, they must be re-recorded.
- Image Views: Create new
Verification and Checks
| Check | Expected Result | Diagnostic Tool |
|---|---|---|
| Swapchain Creation | VK_SUCCESS or VK_SUBOPTIMAL_KHR |
Return value of vkCreateSwapchainKHR |
| Image Extent | Matches window client area exactly | Log caps.currentExtent |
| Resource Validity | No "Object Destroyed" warnings | Vulkan Validation Layers |
| Presentation | No VK_ERROR_OUT_OF_DATE_KHR after recreation |
Return value of vkQueuePresentKHR |
Recovery and Edge Cases
- Recursive Out-of-Date: If
vkCreateSwapchainKHRreturnsVK_ERROR_OUT_OF_DATE_KHR, the window was resized again during the recreation process. Wrap the procedure in awhileloop or retry the logic once more. - Surface Loss: If
VK_ERROR_SURFACE_LOST_KHRoccurs, the window surface itself is invalid. You must destroy theVkSurfaceKHRand recreate it via your WSI (e.g.,glfwCreateWindowSurface) before attempting swapchain recreation. - Suboptimal State:
VK_SUBOPTIMAL_KHRmeans the swapchain can still present, but the image doesn't perfectly match the surface. You can continue rendering, but you should trigger a recreation at the next convenient break to avoid clipping.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.