Vulkan: Smoothly recreate the swapchain using oldSwapchain on "resize" on Windows

This commit is contained in:
Henrik Rydgård committed 2025-10-20 15:42:34 +02:00
1 parent 84aeec7148
commit 6338832015
5 files changed
+27 -6

No files matched your search

+20 -1
View File
@@ -397,6 +397,8 @@ void VulkanContext::DestroySurface() {
if (surface_ != VK_NULL_HANDLE) {
vkDestroySurfaceKHR(instance_, surface_, nullptr);
surface_ = VK_NULL_HANDLE;
// NOTE: We do not reset winSysData1 and 2, it's useful for debugging to compare them.
}
}
@@ -935,6 +937,12 @@ void VulkanContext::SetDebugNameImpl(uint64_t handle, VkObjectType type, const c
VkResult VulkanContext::InitSurface(WindowSystem winsys, void *data1, void *data2) {
winsys_ = winsys;
if (winsysData1_ != data1) {
WARN_LOG(Log::G3D, "winsysData1 changed from %p to %p", winsysData1_, data1);
}
if (winsysData2_ != data2) {
WARN_LOG(Log::G3D, "winsysData2 changed from %p to %p", winsysData2_, data2);
}
winsysData1_ = data1;
winsysData2_ = data2;
return ReinitSurface();
@@ -1344,6 +1352,10 @@ bool VulkanContext::InitSwapchain() {
return false;
}
if (swapchain_) {
INFO_LOG(Log::G3D, "Swapchain already exists, recreating...");
}
VkResult res = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_devices_[physical_device_], surface_, &surfCapabilities_);
if (res == VK_ERROR_SURFACE_LOST_KHR) {
// Not much to do.
@@ -1496,6 +1508,8 @@ bool VulkanContext::InitSwapchain() {
}
}
VkSwapchainKHR oldSwapchain = swapchain_;
VkSwapchainCreateInfoKHR swap_chain_info{ VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR };
swap_chain_info.surface = surface_;
swap_chain_info.minImageCount = desiredNumberOfSwapChainImages;
@@ -1506,7 +1520,7 @@ bool VulkanContext::InitSwapchain() {
swap_chain_info.preTransform = preTransform;
swap_chain_info.imageArrayLayers = 1;
swap_chain_info.presentMode = swapchainPresentMode;
swap_chain_info.oldSwapchain = VK_NULL_HANDLE;
swap_chain_info.oldSwapchain = swapchain_;
swap_chain_info.clipped = true;
swap_chain_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
@@ -1535,6 +1549,11 @@ bool VulkanContext::InitSwapchain() {
}
INFO_LOG(Log::G3D, "Created swapchain: %dx%d %s", swap_chain_info.imageExtent.width, swap_chain_info.imageExtent.height, (surfCapabilities_.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) ? "(TRANSFER_SRC_BIT supported)" : "");
swapchainInited_ = true;
if (oldSwapchain != VK_NULL_HANDLE) {
vkDestroySwapchainKHR(device_, oldSwapchain, nullptr);
INFO_LOG(Log::G3D, "Destroyed old swapchain.");
}
return true;
}
+2 -1
View File
@@ -52,6 +52,7 @@ template<class R, class T> inline void ChainStruct(R &root, T *newStruct) {
// Not all will be usable on all platforms, of course...
enum WindowSystem {
WINDOWSYSTEM_UNINITIALIZED,
#ifdef _WIN32
WINDOWSYSTEM_WIN32,
#endif
@@ -450,7 +451,7 @@ private:
bool CheckLayers(const std::vector<LayerProperties> &layer_props, const std::vector<const char *> &layer_names) const;
WindowSystem winsys_{};
WindowSystem winsys_ = WINDOWSYSTEM_UNINITIALIZED;
// Don't use the real types here to avoid having to include platform-specific stuff
// that we really don't want in everything that uses VulkanContext.
-1
View File
@@ -174,7 +174,6 @@ bool VulkanQueueRunner::InitDepthStencilBuffer(VkCommandBuffer cmd, VulkanBarrie
return true;
}
void VulkanQueueRunner::DestroyBackBuffers() {
if (depth_.view) {
vulkan_->Delete().QueueDeleteImageView(depth_.view);
-1
View File
@@ -164,7 +164,6 @@ void WindowsVulkanContext::Shutdown() {
void WindowsVulkanContext::Resize() {
draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight());
vulkan_->DestroySwapchain();
VulkanContext::CreateInfo info{};
InitVulkanCreateInfoFromConfig(&info);
vulkan_->InitSwapchain();
+5 -2
View File
@@ -120,13 +120,16 @@ void AndroidVulkanContext::Shutdown() {
void AndroidVulkanContext::Resize() {
INFO_LOG(Log::G3D, "AndroidVulkanContext::Resize begin (oldsize: %dx%d)", g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
VulkanContext::CreateInfo info{};
InitVulkanCreateInfoFromConfig(&info);
draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
g_Vulkan->DestroySwapchain();
// TODO: We should only destroy the surface here if the window changed. We can track this inside g_Vulkan.
g_Vulkan->DestroySurface();
VulkanContext::CreateInfo info{};
InitVulkanCreateInfoFromConfig(&info);
g_Vulkan->UpdateCreateInfo(info);
g_Vulkan->ReinitSurface();