From 190b902facab950a4b92a40dbc98df8bd3d4e58d Mon Sep 17 00:00:00 2001
From: 999pingGG <[EMAIL REDACTED]>
Date: Fri, 19 Dec 2025 11:54:08 -0600
Subject: [PATCH] GPU: Fix Android surface and swapchain recreation on app
resume (#14676)
---
src/gpu/vulkan/SDL_gpu_vulkan.c | 27 ++++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/src/gpu/vulkan/SDL_gpu_vulkan.c b/src/gpu/vulkan/SDL_gpu_vulkan.c
index 10798a1d8fe9b..4f5b1f75f6913 100644
--- a/src/gpu/vulkan/SDL_gpu_vulkan.c
+++ b/src/gpu/vulkan/SDL_gpu_vulkan.c
@@ -668,6 +668,7 @@ typedef struct WindowData
SDL_GPUSwapchainComposition swapchainComposition;
SDL_GPUPresentMode presentMode;
bool needsSwapchainRecreate;
+ bool needsSurfaceRecreate;
Uint32 swapchainCreateWidth;
Uint32 swapchainCreateHeight;
@@ -4656,7 +4657,8 @@ static Uint32 VULKAN_INTERNAL_CreateSwapchain(
swapchainCreateInfo.compositeAlpha = compositeAlphaFlag;
swapchainCreateInfo.presentMode = SDLToVK_PresentMode[windowData->presentMode];
swapchainCreateInfo.clipped = VK_TRUE;
- swapchainCreateInfo.oldSwapchain = windowData->swapchain;
+ // The old swapchain could belong to a surface that no longer exists due to app switching.
+ swapchainCreateInfo.oldSwapchain = windowData->needsSurfaceRecreate ? (VkSwapchainKHR)0 : windowData->swapchain;
vulkanResult = renderer->vkCreateSwapchainKHR(
renderer->logicalDevice,
&swapchainCreateInfo,
@@ -9662,6 +9664,7 @@ static bool VULKAN_INTERNAL_OnWindowResize(void *userdata, SDL_Event *e)
if (e->type == SDL_EVENT_DID_ENTER_BACKGROUND) {
data = VULKAN_INTERNAL_FetchWindowData(w);
data->needsSwapchainRecreate = true;
+ data->needsSurfaceRecreate = true;
}
#endif
@@ -9977,6 +9980,24 @@ static bool VULKAN_INTERNAL_AcquireSwapchainTexture(
return true;
}
+ if (windowData->needsSurfaceRecreate) {
+ SDL_VideoDevice *videoDevice = SDL_GetVideoDevice();
+ SDL_assert(videoDevice);
+ SDL_assert(videoDevice->Vulkan_CreateSurface);
+ renderer->vkDestroySurfaceKHR(
+ renderer->instance,
+ windowData->surface,
+ NULL);
+ if (!videoDevice->Vulkan_CreateSurface(
+ videoDevice,
+ windowData->window,
+ renderer->instance,
+ NULL, // FIXME: VAllocationCallbacks
+ &windowData->surface)) {
+ SET_STRING_ERROR_AND_RETURN("Failed to recreate Vulkan surface!", false);
+ }
+ }
+
// If window data marked as needing swapchain recreate, try to recreate
if (windowData->needsSwapchainRecreate) {
Uint32 recreateSwapchainResult = VULKAN_INTERNAL_RecreateSwapchain(renderer, windowData);
@@ -9992,6 +10013,10 @@ static bool VULKAN_INTERNAL_AcquireSwapchainTexture(
}
return true;
}
+
+ // Unset this flag until after the swapchain has been recreated to let VULKAN_INTERNAL_CreateSwapchain()
+ // know whether it needs to pass the old swapchain or not.
+ windowData->needsSurfaceRecreate = false;
}
if (windowData->inFlightFences[windowData->frameCounter] != NULL) {