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