diff --git a/src/gpu/vulkan/SDL_gpu_vulkan.c b/src/gpu/vulkan/SDL_gpu_vulkan.c index 10798a1d8f..4f5b1f75f6 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) {