# SDL: GPU: recreate swapchain on window pixel size change event (#10985)

**URL:** <https://discourse.libsdl.org/t/sdl-gpu-recreate-swapchain-on-window-pixel-size-change-event-10985/54576>\
**Category:** SDL Commits\
**Created:** [September 29, 2024, 1:10am UTC](https://discourse.libsdl.org/t/sdl-gpu-recreate-swapchain-on-window-pixel-size-change-event-10985/54576 "2024-09-29T01:10:02Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![SDLPushPostBot](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/sdlpushpostbot/32/4370_2.png) [@SDLPushPostBot](https://discourse.libsdl.org/u/SDLPushPostBot)\
**Post date:** [September 29, 2024, 1:10am UTC](https://discourse.libsdl.org/t/sdl-gpu-recreate-swapchain-on-window-pixel-size-change-event-10985/54576/1 "2024-09-29T01:10:02Z")

</div>

> <https://github.com/libsdl-org/SDL/commit/fc242abbd2bddface0fd9ffba47957d978c21bf4>

```diff
From fc242abbd2bddface0fd9ffba47957d978c21bf4 Mon Sep 17 00:00:00 2001
From: Evan Hemsley <[EMAIL REDACTED]>
Date: Sat, 28 Sep 2024 18:09:56 -0700
Subject: [PATCH] GPU: recreate swapchain on window pixel size change event
 (#10985)

---
 include/SDL3/SDL_gpu.h | 2 +-
 src/gpu/d3d11/SDL_gpu_d3d11.c | 69 ++++++++------
 src/gpu/d3d12/SDL_gpu_d3d12.c | 161 ++++++++++++++++----------------
 src/gpu/vulkan/SDL_gpu_vulkan.c | 43 +++------
 4 files changed, 136 insertions(+), 139 deletions(-)

diff --git a/include/SDL3/SDL_gpu.h b/include/SDL3/SDL_gpu.h
index a70a399eabee6..5983ce66713b9 100644
--- a/include/SDL3/SDL_gpu.h
+++ b/include/SDL3/SDL_gpu.h
@@ -3263,7 +3263,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_WindowSupportsGPUPresentMode(
  * Claims a window, creating a swapchain structure for it.
  *
  * This must be called before SDL_AcquireGPUSwapchainTexture is called using
- * the window.
+ * the window. You should only call this function from the thread that created the window.
  *
  * The swapchain will be created with SDL_GPU_SWAPCHAINCOMPOSITION_SDR and
  * SDL_GPU_PRESENTMODE_VSYNC. If you want to have different swapchain
diff --git a/src/gpu/d3d11/SDL_gpu_d3d11.c b/src/gpu/d3d11/SDL_gpu_d3d11.c
index 90402ede29203..a7472fc136c80 100644
--- a/src/gpu/d3d11/SDL_gpu_d3d11.c
+++ b/src/gpu/d3d11/SDL_gpu_d3d11.c
@@ -482,6 +482,7 @@ typedef struct D3D11WindowData
     DXGI_COLOR_SPACE_TYPE swapchainColorSpace;
     SDL_GPUFence *inFlightFences[MAX_FRAMES_IN_FLIGHT];
     Uint32 frameCounter;
+ bool needsSwapchainRecreate;
 } D3D11WindowData;
 
 typedef struct D3D11Shader
@@ -5021,6 +5022,18 @@ static D3D11WindowData *D3D11_INTERNAL_FetchWindowData(
     return (D3D11WindowData *)SDL_GetPointerProperty(properties, WINDOW_PROPERTY_DATA, NULL);
 }
 
+static bool D3D11_INTERNAL_OnWindowResize(void *userdata, SDL_Event *e)
+{
+ SDL_Window *w = (SDL_Window *)userdata;
+ D3D11WindowData *data;
+ if (e->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED && e->window.windowID == SDL_GetWindowID(w)) {
+ data = D3D11_INTERNAL_FetchWindowData(w);
+ data->needsSwapchainRecreate = true;
+ }
+
+ return true;
+}
+
 static bool D3D11_INTERNAL_InitializeSwapchainTexture(
     D3D11Renderer *renderer,
     IDXGISwapChain *swapchain,
@@ -5089,7 +5102,6 @@ static bool D3D11_INTERNAL_CreateSwapchain(
     SDL_GPUPresentMode presentMode)
 {
     HWND dxgiHandle;
- int width, height;
     Uint32 i;
     DXGI_SWAP_CHAIN_DESC swapchainDesc;
     DXGI_FORMAT swapchainFormat;
@@ -5105,9 +5117,6 @@ static bool D3D11_INTERNAL_CreateSwapchain(
     dxgiHandle = (HWND)windowData->window;
 #endif
 
- // Get the window size
- SDL_GetWindowSize(windowData->window, &width, &height);
-
     swapchainFormat = SwapchainCompositionToTextureFormat[swapchainComposition];
 
     // Initialize the swapchain buffer descriptor
@@ -5216,6 +5225,10 @@ static bool D3D11_INTERNAL_CreateSwapchain(
         return false;
     }
 
+ int w, h;
+ SDL_SyncWindow(windowData->window);
+ SDL_GetWindowSizeInPixels(windowData->window, &w, &h);
+
     // Initialize dummy container, width/height will be filled out in AcquireSwapchainTexture
     SDL_zerop(&windowData->textureContainer);
     windowData->textureContainer.textures = SDL_calloc(1, sizeof(D3D11Texture *));
@@ -5231,6 +5244,8 @@ static bool D3D11_INTERNAL_CreateSwapchain(
     windowData->textureContainer.header.info.num_levels = 1;
     windowData->textureContainer.header.info.sample_count = SDL_GPU_SAMPLECOUNT_1;
     windowData->textureContainer.header.info.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
+ windowData->textureContainer.header.info.width = w;
+ windowData->textureContainer.header.info.height = h;
 
     windowData->texture.container = &windowData->textureContainer;
     windowData->texture.containerIndex = 0;
@@ -5240,32 +5255,41 @@ static bool D3D11_INTERNAL_CreateSwapchain(
 
 static bool D3D11_INTERNAL_ResizeSwapchain(
     D3D11Renderer *renderer,
- D3D11WindowData *windowData,
- Sint32 width,
- Sint32 height)
+ D3D11WindowData *windowData)
 {
+ D3D11_Wait((SDL_GPURenderer *)renderer);
+
     // Release the old RTV
     ID3D11RenderTargetView_Release(windowData->texture.subresources[0].colorTargetViews[0]);
     SDL_free(windowData->texture.subresources[0].colorTargetViews);
     SDL_free(windowData->texture.subresources);
 
+ int w, h;
+ SDL_SyncWindow(windowData->window);
+ SDL_GetWindowSizeInPixels(windowData->window, &w, &h);
+
     // Resize the swapchain
     HRESULT res = IDXGISwapChain_ResizeBuffers(
         windowData->swapchain,
         0, // Keep buffer count the same
- width,
- height,
+ w,
+ h,
         DXGI_FORMAT_UNKNOWN, // Keep the old format
         renderer->supportsTearing ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0);
     CHECK_D3D11_ERROR_AND_RETURN("Could not resize swapchain buffers", false);
 
     // Create the texture object for the swapchain
- return D3D11_INTERNAL_InitializeSwapchainTexture(
+ bool result = D3D11_INTERNAL_InitializeSwapchainTexture(
         renderer,
         windowData->swapchain,
         windowData->swapchainFormat,
         (windowData->swapchainComposition == SDL_GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR) ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : windowData->swapchainFormat,
         &windowData->texture);
+
+ windowData->textureContainer.header.info.width = w;
+ windowData->textureContainer.header.info.height = h;
+ windowData->needsSwapchainRecreate = !result;
+ return result;
 }
 
 static bool D3D11_SupportsSwapchainComposition(
@@ -5350,14 +5374,13 @@ static bool D3D11_ClaimWindow(
     D3D11WindowData *windowData = D3D11_INTERNAL_FetchWindowData(window);
 
     if (windowData == NULL) {
- windowData = (D3D11WindowData *)SDL_malloc(sizeof(D3D11WindowData));
+ windowData = (D3D11WindowData *)SDL_calloc(1, sizeof(D3D11WindowData));
         windowData->window = window;
 
         if (D3D11_INTERNAL_CreateSwapchain(renderer, windowData, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, SDL_GPU_PRESENTMODE_VSYNC)) {
             SDL_SetPointerProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA, windowData);
 
             SDL_LockMutex(renderer->windowLock);
-
             if (renderer->claimedWindowCount >= renderer->claimedWindowCapacity) {
                 renderer->claimedWindowCapacity *= 2;
                 renderer->claimedWindows = SDL_realloc(
@@ -5366,9 +5389,10 @@ static bool D3D11_ClaimWindow(
             }
             renderer->claimedWindows[renderer->claimedWindowCount] = windowData;
             renderer->claimedWindowCount += 1;
-
             SDL_UnlockMutex(renderer->windowLock);
 
+ SDL_AddEventWatch(D3D11_INTERNAL_OnWindowResize, window);
+
             return true;
         } else {
             SDL_free(windowData);
@@ -5439,6 +5463,7 @@ static void D3D11_ReleaseWindow(
     SDL_free(windowData);
 
     SDL_ClearProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA);
+ SDL_RemoveEventWatch(D3D11_INTERNAL_OnWindowResize, window);
 }
 
 static bool D3D11_AcquireSwapchainTexture(
@@ -5449,8 +5474,6 @@ static bool D3D11_AcquireSwapchainTexture(
     D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
     D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer;
     D3D11WindowData *windowData;
- DXGI_SWAP_CHAIN_DESC swapchainDesc;
- int windowW, windowH;
     HRESULT res;
 
     *swapchainTexture = NULL;
@@ -5460,16 +5483,8 @@ static bool D3D11_AcquireSwapchainTexture(
         SET_STRING_ERROR_AND_RETURN("Cannot acquire a swapchain texture from an unclaimed window!", false)
     }
 
- // Check for window size changes and resize the swapchain if needed.
- IDXGISwapChain_GetDesc(windowData->swapchain, &swapchainDesc);
- SDL_GetWindowSize(window, &windowW, &windowH);
-
- if ((UINT)windowW != swapchainDesc.BufferDesc.Width || (UINT)windowH != swapchainDesc.BufferDesc.Height) {
- if (!D3D11_INTERNAL_ResizeSwapchain(
- renderer,
- windowData,
- windowW,
- windowH)) {
+ if (windowData->needsSwapchainRecreate) {
+ if (!D3D11_INTERNAL_ResizeSwapchain(renderer, windowData)) {
             return false;
         }
     }
@@ -5511,10 +5526,6 @@ static bool D3D11_AcquireSwapchainTexture(
         (void **)&windowData->texture.handle);
     CHECK_D3D11_ERROR_AND_RETURN("Could not acquire swapchain!", false);
 
- // Update the texture container dimensions
- windowData->textureContainer.header.info.width = windowW;
- windowData->textureContainer.header.info.height = windowH;
-
     // Set up presentation
     if (d3d11CommandBuffer->windowDataCount == d3d11CommandBuffer->windowDataCapacity) {
         d3d11CommandBuffer->windowDataCapacity += 1;
diff --git a/src/gpu/d3d12/SDL_gpu_d3d12.c b/src/gpu/d3d12/SDL_gpu_d3d12.c
index 37cedb86a8e65..20a6367ee48f4 100644
--- a/src/gpu/d3d12/SDL_gpu_d3d12.c
+++ b/src/gpu/d3d12/SDL_gpu_d3d12.c
@@ -544,7 +544,6 @@ typedef struct D3D12WindowData
     SDL_Window *window;
 #if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
     D3D12XBOX_FRAME_PIPELINE_TOKEN frameToken;
- Uint32 swapchainWidth, swapchainHeight;
 #else
     IDXGISwapChain3 *swapchain;
 #endif
@@ -555,6 +554,7 @@ typedef struct D3D12WindowData
 
     D3D12TextureContainer textureContainers[MAX_FRAMES_IN_FLIGHT];
     SDL_GPUFence *inFlightFences[MAX_FRAMES_IN_FLIGHT];
+ bool needsSwapchainRecreate;
 } D3D12WindowData;
 
 typedef struct D3D12PresentData
@@ -5973,6 +5973,18 @@ static D3D12WindowData *D3D12_INTERNAL_FetchWindowData(
     return (D3D12WindowData *)SDL_GetPointerProperty(properties, WINDOW_PROPERTY_DATA, NULL);
 }
 
+static bool D3D12_INTERNAL_OnWindowResize(void *userdata, SDL_Event *e)
+{
+ SDL_Window *w = (SDL_Window *)userdata;
+ D3D12WindowData *data;
+ if (e->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED && e->window.windowID == SDL_GetWindowID(w)) {
+ data = D3D12_INTERNAL_FetchWindowData(w);
+ data->needsSwapchainRecreate = true;
+ }
+
+ return true;
+}
+
 static bool D3D12_SupportsSwapchainComposition(
     SDL_GPURenderer *driverData,
     SDL_Window *window,
@@ -6063,7 +6075,8 @@ static bool D3D12_INTERNAL_CreateSwapchain(
     D3D12Texture *texture;
 
     // Get the swapchain size
- SDL_GetWindowSize(windowData->window, &width, &height);
+ SDL_SyncWindow(windowData->window);
+ SDL_GetWindowSizeInPixels(windowData->window, &width, &height);
 
     // Create the swapchain textures
     SDL_zero(createInfo);
@@ -6091,8 +6104,6 @@ static bool D3D12_INTERNAL_CreateSwapchain(
     windowData->swapchainComposition = swapchain_composition;
     windowData->swapchainColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
     windowData->frameCounter = 0;
- windowData->swapchainWidth = width;
- windowData->swapchainHeight = height;
 
     // Precache blit pipelines for the swapchain format
     for (Uint32 i = 0; i < 5; i += 1) {
@@ -6126,35 +6137,31 @@ static void D3D12_INTERNAL_DestroySwapchain(
     }
 }
 
-static bool D3D12_INTERNAL_ResizeSwapchainIfNeeded(
+static bool D3D12_INTERNAL_ResizeSwapchain(
     D3D12Renderer *renderer,
     D3D12WindowData *windowData)
 {
- int w, h;
- SDL_GetWindowSize(windowData->window, &w, &h);
-
- if (w != windowData->swapchainWidth || h != windowData->swapchainHeight) {
- // Wait so we don't release in-flight views
- D3D12_Wait((SDL_GPURenderer *)renderer);
-
- // Present a black screen
- renderer->commandQueue->PresentX(0, NULL, NULL);
+ // Wait so we don't release in-flight views
+ D3D12_Wait((SDL_GPURenderer *)renderer);
 
- // Clean up the previous swapchain textures
- for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
- D3D12_INTERNAL_DestroyTexture(
- renderer,
- windowData->textureContainers[i].activeTexture);
- }
+ // Present a black screen
+ renderer->commandQueue->PresentX(0, NULL, NULL);
 
- // Create a new swapchain
- D3D12_INTERNAL_CreateSwapchain(
+ // Clean up the previous swapchain textures
+ for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
+ D3D12_INTERNAL_DestroyTexture(
             renderer,
- windowData,
- windowData->swapchainComposition,
- windowData->present_mode);
+ windowData->textureContainers[i].activeTexture);
     }
 
+ // Create a new swapchain
+ D3D12_INTERNAL_CreateSwapchain(
+ renderer,
+ windowData,
+ windowData->swapchainComposition,
+ windowData->present_mode);
+
+ windowData->needsSwapchainRecreate = false;
     return true;
 }
 #else
@@ -6273,58 +6280,58 @@ static bool D3D12_INTERNAL_InitializeSwapchainTexture(
     return true;
 }
 
-static bool D3D12_INTERNAL_ResizeSwapchainIfNeeded(
+static bool D3D12_INTERNAL_ResizeSwapchain(
     D3D12Renderer *renderer,
     D3D12WindowData *windowData)
 {
- DXGI_SWAP_CHAIN_DESC swapchainDesc;
- int w, h;
+ // Wait so we don't release in-flight views
+ D3D12_Wait((SDL_GPURenderer *)renderer);
 
- IDXGISwapChain_GetDesc(windowData->swapchain, &swapchainDesc);
- SDL_GetWindowSize(windowData->window, &w, &h);
+ // Release views and clean up
+ for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
+ D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
+ renderer,
+ &windowData->textureContainers[i].activeTexture->srvHandle);
+ D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
+ renderer,
+ &windowData->textureContainers[i].activeTexture->subresources[0].rtvHandles[0]);
 
- if ((UINT)w != swapchainDesc.BufferDesc.Width || (UINT)h != swapchainDesc.BufferDesc.Height) {
- // Wait so we don't release in-flight views
- D3D12_Wait((SDL_GPURenderer *)renderer);
+ SDL_free(windowData->textureContainers[i].activeTexture->subresources[0].rtvHandles);
+ SDL_free(windowData->textureContainers[i].activeTexture->subresources);
+ SDL_free(windowData->textureContainers[i].activeTexture);
+ SDL_free(windowData->textureContainers[i].textures);
+ }
 
- // Release views and clean up
- for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
- D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
- renderer,
- &windowData->textureContainers[i].activeTexture->srvHandle);
- D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
+ int w, h;
+ SDL_SyncWindow(windowData->window);
+ SDL_GetWindowSizeInPixels(
+ windowData->window,
+ &w,
+ &h);
+
+ // Resize the swapchain
+ HRESULT res = IDXGISwapChain_ResizeBuffers(
+ windowData->swapchain,
+ 0, // Keep buffer count the same
+ w,
+ h,
+ DXGI_FORMAT_UNKNOWN, // Keep the old format
+ renderer->supportsTearing ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0);
+ CHECK_D3D12_ERROR_AND_RETURN("Could not resize swapchain buffers", false)
+
+ // Create texture object for the swapchain
+ for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
+ if (!D3D12_INTERNAL_InitializeSwapchainTexture(
                 renderer,
- &windowData->textureContainers[i].activeTexture->subresources[0].rtvHandles[0]);
-
- SDL_free(windowData->textureContainers[i].activeTexture->subresources[0].rtvHandles);
- SDL_free(windowData->textureContainers[i].activeTexture->subresources);
- SDL_free(windowData->textureContainers[i].activeTexture);
- SDL_free(windowData->textureContainers[i].textures);
- }
-
- // Resize the swapchain
- HRESULT res = IDXGISwapChain_ResizeBuffers(
- windowData->swapchain,
- 0, // Keep buffer count the same
- w,
- h,
- DXGI_FORMAT_UNKNOWN, // Keep the old format
- renderer->supportsTearing ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0);
- CHECK_D3D12_ERROR_AND_RETURN("Could not resize swapchain buffers", false)
-
- // Create texture object for the swapchain
- for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
- if (!D3D12_INTERNAL_InitializeSwapchainTexture(
- renderer,
- windowData->swapchain,
- windowData->swapchainComposition,
- i,
- &windowData->textureContainers[i])) {
- return false;
- }
+ windowData->swapchain,
+ windowData->swapchainComposition,
+ i,
+ &windowData->textureContainers[i])) {
+ return false;
         }
     }
 
+ windowData->needsSwapchainRecreate = false;
     return true;
 }
 
@@ -6358,7 +6365,6 @@ static bool D3D12_INTERNAL_CreateSwapchain(
     SDL_GPUPresentMode presentMode)
 {
     HWND dxgiHandle;
- int width, height;
     DXGI_SWAP_CHAIN_DESC1 swapchainDesc;
     DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreenDesc;
     DXGI_FORMAT swapchainFormat;
@@ -6374,9 +6380,6 @@ static bool D3D12_INTERNAL_CreateSwapchain(
     dxgiHandle = (HWND)windowData->window;
 #endif
 
- // Get the window size
- SDL_GetWindowSize(windowData->window, &width, &height);
-
     swapchainFormat = SwapchainCompositionToTextureFormat[swapchainComposition];
 
     // Initialize the swapchain buffer descriptor
@@ -6529,7 +6532,6 @@ static bool D3D12_ClaimWindow(
             SDL_SetPointerProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA, windowData);
 
             SDL_LockMutex(renderer->windowLock);
-
             if (renderer->claimedWindowCount >= renderer->claimedWindowCapacity) {
                 renderer->claimedWindowCapacity *= 2;
                 renderer->claimedWindows = (D3D12WindowData **)SDL_realloc(
@@ -6538,9 +6540,10 @@ static bool D3D12_ClaimWindow(
             }
             renderer->claimedWindows[renderer->claimedWindowCount] = windowData;
             renderer->claimedWindowCount += 1;
-
             SDL_UnlockMutex(renderer->windowLock);
 
+ SDL_AddEventWatch(D3D12_INTERNAL_OnWindowResize, window);
+
             return true;
         } else {
             SDL_free(windowData);
@@ -6589,6 +6592,7 @@ static void D3D12_ReleaseWindow(
 
     SDL_free(windowData);
     SDL_ClearProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA);
+ SDL_RemoveEventWatch(D3D12_INTERNAL_OnWindowResize, window);
 }
 
 static bool D3D12_SetSwapchainParameters(
@@ -6918,10 +6922,11 @@ static bool D3D12_AcquireSwapchainTexture(
         SET_STRING_ERROR_AND_RETURN("Cannot acquire swapchain texture from an unclaimed window!", false)
     }
 
- res = D3D12_INTERNAL_ResizeSwapchainIfNeeded(
- renderer,
- windowData);
- CHECK_D3D12_ERROR_AND_RETURN("Could not resize swapchain", false);
+ if (windowData->needsSwapchainRecreate) {
+ if (!D3D12_INTERNAL_ResizeSwapchain(renderer, windowData)) {
+ return false;
+ }
+ }
 
     if (windowData->inFlightFences[windowData->frameCounter] != NULL) {
         if (windowData->present_mode == SDL_GPU_PRESENTMODE_VSYNC) {
@@ -6932,7 +6937,7 @@ static bool D3D12_AcquireSwapchainTexture(
                 &windowData->inFlightFences[windowData->frameCounter],
                 1)) {
                 return false;
- }
+ }
         } else {
             if (!D3D12_QueryFence(
                     (SDL_GPURenderer *)renderer,
diff --git a/src/gpu/vulkan/SDL_gpu_vulkan.c b/src/gpu/vulkan/SDL_gpu_vulkan.c
index 84c073657aca9..280b2bacca9f3 100644
--- a/src/gpu/vulkan/SDL_gpu_vulkan.c
+++ b/src/gpu/vulkan/SDL_gpu_vulkan.c
@@ -1159,6 +1159,7 @@ struct VulkanRenderer
     SDL_Mutex *acquireUniformBufferLock;
     SDL_Mutex *renderPassFetchLock;
     SDL_Mutex *framebufferFetchLock;
+ SDL_Mutex *windowLock;
 
     Uint8 defragInProgress;
 
@@ -4493,35 +4494,6 @@ static bool VULKAN_INTERNAL_CreateSwapchain(
         &drawableWidth,
         &drawableHeight);
 
- if (drawableWidth < (Sint32)swapchainSupportDetails.capabilities.minImageExtent.width ||
- drawableWidth > (Sint32)swapchainSupportDetails.capabilities.maxImageExtent.width ||
- drawableHeight < (Sint32)swapchainSupportDetails.capabilities.minImageExtent.height ||
- drawableHeight > (Sint32)swapchainSupportDetails.capabilities.maxImageExtent.height) {
- if (swapchainSupportDetails.capabilities.currentExtent.width != SDL_MAX_UINT32) {
- drawableWidth = VULKAN_INTERNAL_clamp(
- drawableWidth,
- (Sint32)swapchainSupportDetails.capabilities.minImageExtent.width,
- (Sint32)swapchainSupportDetails.capabilities.maxImageExtent.width);
- drawableHeight = VULKAN_INTERNAL_clamp(
- drawableHeight,
- (Sint32)swapchainSupportDetails.capabilities.minImageExtent.height,
- (Sint32)swapchainSupportDetails.capabilities.maxImageExtent.height);
- } else {
- renderer->vkDestroySurfaceKHR(
- renderer->instance,
- swapchainData->surface,
- NULL);
- if (swapchainSupportDetails.formatsLength > 0) {
- SDL_free(swapchainSupportDetails.formats);
- }
- if (swapchainSupportDetails.presentModesLength > 0) {
- SDL_free(swapchainSupportDetails.presentModes);
- }
- SDL_free(swapchainData);
- SET_STRING_ERROR_AND_RETURN("No fallback swapchain size available!", false);
- }
- }
-
     swapchainData->imageCount = MAX_FRAMES_IN_FLIGHT;
 
     if (swapchainSupportDetails.capabilities.maxImageCount > 0 &&
@@ -4833,6 +4805,7 @@ static void VULKAN_DestroyDevice(
     SDL_DestroyMutex(renderer->acquireUniformBufferLock);
     SDL_DestroyMutex(renderer->renderPassFetchLock);
     SDL_DestroyMutex(renderer->framebufferFetchLock);
+ SDL_DestroyMutex(renderer->windowLock);
 
     renderer->vkDestroyDevice(renderer->logicalDevice, NULL);
     renderer->vkDestroyInstance(renderer->instance, NULL);
@@ -9356,7 +9329,7 @@ static bool VULKAN_INTERNAL_OnWindowResize(void *userdata, SDL_Event *e)
 {
     SDL_Window *w = (SDL_Window *)userdata;
     WindowData *data;
- if (e->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED) {
+ if (e->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED && e->window.windowID == SDL_GetWindowID(w)) {
         data = VULKAN_INTERNAL_FetchWindowData(w);
         data->needsSwapchainRecreate = true;
     }
@@ -9460,6 +9433,7 @@ static bool VULKAN_ClaimWindow(
         if (VULKAN_INTERNAL_CreateSwapchain(renderer, windowData)) {
             SDL_SetPointerProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA, windowData);
 
+ SDL_LockMutex(renderer->windowLock);
             if (renderer->claimedWindowCount >= renderer->claimedWindowCapacity) {
                 renderer->claimedWindowCapacity *= 2;
                 renderer->claimedWindows = SDL_realloc(
@@ -9469,6 +9443,7 @@ static bool VULKAN_ClaimWindow(
 
             renderer->claimedWindows[renderer->claimedWindowCount] = windowData;
             renderer->claimedWindowCount += 1;
+ SDL_UnlockMutex(renderer->windowLock);
 
             SDL_AddEventWatch(VULKAN_INTERNAL_OnWindowResize, window);
 
@@ -9511,6 +9486,7 @@ static void VULKAN_ReleaseWindow(
             windowData);
     }
 
+ SDL_LockMutex(renderer->windowLock);
     for (i = 0; i < renderer->claimedWindowCount; i += 1) {
         if (renderer->claimedWindows[i]->window == window) {
             renderer->claimedWindows[i] = renderer->claimedWindows[renderer->claimedWindowCount - 1];
@@ -9518,6 +9494,7 @@ static void VULKAN_ReleaseWindow(
             break;
         }
     }
+ SDL_UnlockMutex(renderer->windowLock);
 
     SDL_free(windowData);
 
@@ -9619,7 +9596,10 @@ static bool VULKAN_AcquireSwapchainTexture(
 
     // If window data marked as needing swapchain recreate, try to recreate
     if (windowData->needsSwapchainRecreate) {
- VULKAN_INTERNAL_RecreateSwapchain(renderer, windowData);
+ if (!VULKAN_INTERNAL_RecreateSwapchain(renderer, windowData)) {
+ return false;
+ }
+
         swapchainData = windowData->swapchainData;
 
         if (swapchainData == NULL) {
@@ -11340,6 +11320,7 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
     renderer->acquireUniformBufferLock = SDL_CreateMutex();
     renderer->renderPassFetchLock = SDL_CreateMutex();
     renderer->framebufferFetchLock = SDL_CreateMutex();
+ renderer->windowLock = SDL_CreateMutex();
 
     /*
      * Create submitted command buffer list

```
