From afdf325fb4090e93a124519d1a3bc1fbe0ba9025 Mon Sep 17 00:00:00 2001
From: Evan Hemsley <[EMAIL REDACTED]>
Date: Mon, 30 Sep 2024 10:23:19 -0700
Subject: [PATCH] GPU: Add swapchain dimension out params (#11003)
---
include/SDL3/SDL_gpu.h | 22 +-
src/dynapi/SDL_dynapi_procs.h | 2 +-
src/gpu/SDL_gpu.c | 12 +-
src/gpu/SDL_sysgpu.h | 4 +-
src/gpu/d3d11/SDL_gpu_d3d11.c | 23 +-
src/gpu/d3d12/SDL_gpu_d3d12.c | 26 +-
src/gpu/metal/SDL_gpu_metal.m | 16 +-
src/gpu/vulkan/SDL_gpu_vulkan.c | 492 ++++++++++++++++----------------
src/render/gpu/SDL_render_gpu.c | 19 +-
test/testgpu_simple_clear.c | 2 +-
test/testgpu_spinning_cube.c | 6 +-
11 files changed, 343 insertions(+), 281 deletions(-)
diff --git a/include/SDL3/SDL_gpu.h b/include/SDL3/SDL_gpu.h
index 123ffdcb33597..a986a2f2c7aa6 100644
--- a/include/SDL3/SDL_gpu.h
+++ b/include/SDL3/SDL_gpu.h
@@ -3316,7 +3316,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_ReleaseWindowFromGPUDevice(
* \param window an SDL_Window that has been claimed.
* \param swapchain_composition the desired composition of the swapchain.
* \param present_mode the desired present mode for the swapchain.
- * \returns true if successful, false on error.
+ * \returns true if successful, false on error; call SDL_GetError() for more information.
*
* \since This function is available since SDL 3.0.0.
*
@@ -3350,20 +3350,22 @@ extern SDL_DECLSPEC SDL_GPUTextureFormat SDLCALL SDL_GetGPUSwapchainTextureForma
* When a swapchain texture is acquired on a command buffer, it will
* automatically be submitted for presentation when the command buffer is
* submitted. The swapchain texture should only be referenced by the command
- * buffer used to acquire it. The swapchain texture handle can be NULL under
+ * buffer used to acquire it. The swapchain texture handle can be filled in with NULL under
* certain conditions. This is not necessarily an error. If this function
- * returns false then there is an error. The swapchain texture is managed by
- * the implementation and must not be freed by the user. The texture
- * dimensions will be the width and height of the claimed window. You can
- * obtain these dimensions by calling SDL_GetWindowSizeInPixels. You MUST NOT
+ * returns false then there is an error.
+ *
+ * The swapchain texture is managed by
+ * the implementation and must not be freed by the user. You MUST NOT
* call this function from any thread other than the one that created the
* window.
*
* \param command_buffer a command buffer.
* \param window a window that has been claimed.
- * \param swapchainTexture a pointer filled in with a swapchain texture
+ * \param swapchain_texture a pointer filled in with a swapchain texture
* handle.
- * \returns true on success, false on error.
+ * \param swapchain_texture_width a pointer filled in with the swapchain texture width, may be NULL.
+ * \param swapchain_texture_height a pointer filled in with the swapchain texture height, may be NULL.
+ * \returns true on success, false on error; call SDL_GetError() for more information.
*
* \since This function is available since SDL 3.0.0.
*
@@ -3375,7 +3377,9 @@ extern SDL_DECLSPEC SDL_GPUTextureFormat SDLCALL SDL_GetGPUSwapchainTextureForma
extern SDL_DECLSPEC bool SDLCALL SDL_AcquireGPUSwapchainTexture(
SDL_GPUCommandBuffer *command_buffer,
SDL_Window *window,
- SDL_GPUTexture **swapchainTexture);
+ SDL_GPUTexture **swapchain_texture,
+ Uint32 *swapchain_texture_width,
+ Uint32 *swapchain_texture_height);
/**
* Submits a command buffer so its commands can be processed on the GPU.
diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h
index bdba993f16498..cfaec9dad77e5 100644
--- a/src/dynapi/SDL_dynapi_procs.h
+++ b/src/dynapi/SDL_dynapi_procs.h
@@ -50,7 +50,7 @@ SDL_DYNAPI_PROC(int,SDL_swprintf,(SDL_OUT_Z_CAP(b) wchar_t *a, size_t b, SDL_PRI
// New API symbols are added at the end
SDL_DYNAPI_PROC(SDL_Surface*,SDL_AcquireCameraFrame,(SDL_Camera *a, Uint64 *b),(a,b),return)
SDL_DYNAPI_PROC(SDL_GPUCommandBuffer*,SDL_AcquireGPUCommandBuffer,(SDL_GPUDevice *a),(a),return)
-SDL_DYNAPI_PROC(bool,SDL_AcquireGPUSwapchainTexture,(SDL_GPUCommandBuffer *a, SDL_Window *b, SDL_GPUTexture **c),(a,b,c),return)
+SDL_DYNAPI_PROC(bool,SDL_AcquireGPUSwapchainTexture,(SDL_GPUCommandBuffer *a, SDL_Window *b, SDL_GPUTexture **c, Uint32 *d, Uint32 *e),(a,b,c,d,e),return)
SDL_DYNAPI_PROC(int,SDL_AddAtomicInt,(SDL_AtomicInt *a, int b),(a,b),return)
SDL_DYNAPI_PROC(bool,SDL_AddEventWatch,(SDL_EventFilter a, void *b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_AddGamepadMapping,(const char *a),(a),return)
diff --git a/src/gpu/SDL_gpu.c b/src/gpu/SDL_gpu.c
index aedb81259afc1..a1210a0ea9e6a 100644
--- a/src/gpu/SDL_gpu.c
+++ b/src/gpu/SDL_gpu.c
@@ -2613,7 +2613,9 @@ SDL_GPUTextureFormat SDL_GetGPUSwapchainTextureFormat(
bool SDL_AcquireGPUSwapchainTexture(
SDL_GPUCommandBuffer *command_buffer,
SDL_Window *window,
- SDL_GPUTexture **swapchainTexture)
+ SDL_GPUTexture **swapchain_texture,
+ Uint32 *swapchain_texture_width,
+ Uint32 *swapchain_texture_height)
{
if (command_buffer == NULL) {
SDL_InvalidParamError("command_buffer");
@@ -2623,8 +2625,8 @@ bool SDL_AcquireGPUSwapchainTexture(
SDL_InvalidParamError("window");
return false;
}
- if (swapchainTexture == NULL) {
- SDL_InvalidParamError("swapchainTexture");
+ if (swapchain_texture == NULL) {
+ SDL_InvalidParamError("swapchain_texture");
return false;
}
@@ -2636,7 +2638,9 @@ bool SDL_AcquireGPUSwapchainTexture(
return COMMAND_BUFFER_DEVICE->AcquireSwapchainTexture(
command_buffer,
window,
- swapchainTexture);
+ swapchain_texture,
+ swapchain_texture_width,
+ swapchain_texture_height);
}
bool SDL_SubmitGPUCommandBuffer(
diff --git a/src/gpu/SDL_sysgpu.h b/src/gpu/SDL_sysgpu.h
index 5388696d1021d..ce48a5eb2eeaf 100644
--- a/src/gpu/SDL_sysgpu.h
+++ b/src/gpu/SDL_sysgpu.h
@@ -651,7 +651,9 @@ struct SDL_GPUDevice
bool (*AcquireSwapchainTexture)(
SDL_GPUCommandBuffer *commandBuffer,
SDL_Window *window,
- SDL_GPUTexture **swapchainTexture);
+ SDL_GPUTexture **swapchainTexture,
+ Uint32 *swapchainTextureWidth,
+ Uint32 *swapchainTextureHeight);
bool (*Submit)(
SDL_GPUCommandBuffer *commandBuffer);
diff --git a/src/gpu/d3d11/SDL_gpu_d3d11.c b/src/gpu/d3d11/SDL_gpu_d3d11.c
index a7472fc136c80..39bbd9e2f1f25 100644
--- a/src/gpu/d3d11/SDL_gpu_d3d11.c
+++ b/src/gpu/d3d11/SDL_gpu_d3d11.c
@@ -480,6 +480,8 @@ typedef struct D3D11WindowData
SDL_GPUSwapchainComposition swapchainComposition;
DXGI_FORMAT swapchainFormat;
DXGI_COLOR_SPACE_TYPE swapchainColorSpace;
+ Uint32 width;
+ Uint32 height;
SDL_GPUFence *inFlightFences[MAX_FRAMES_IN_FLIGHT];
Uint32 frameCounter;
bool needsSwapchainRecreate;
@@ -5250,6 +5252,8 @@ static bool D3D11_INTERNAL_CreateSwapchain(
windowData->texture.container = &windowData->textureContainer;
windowData->texture.containerIndex = 0;
+ windowData->width = w;
+ windowData->height = h;
return true;
}
@@ -5288,6 +5292,8 @@ static bool D3D11_INTERNAL_ResizeSwapchain(
windowData->textureContainer.header.info.width = w;
windowData->textureContainer.header.info.height = h;
+ windowData->width = w;
+ windowData->height = h;
windowData->needsSwapchainRecreate = !result;
return result;
}
@@ -5469,7 +5475,9 @@ static void D3D11_ReleaseWindow(
static bool D3D11_AcquireSwapchainTexture(
SDL_GPUCommandBuffer *commandBuffer,
SDL_Window *window,
- SDL_GPUTexture **swapchainTexture)
+ SDL_GPUTexture **swapchainTexture,
+ Uint32 *swapchainTextureWidth,
+ Uint32 *swapchainTextureHeight)
{
D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer;
@@ -5477,6 +5485,12 @@ static bool D3D11_AcquireSwapchainTexture(
HRESULT res;
*swapchainTexture = NULL;
+ if (swapchainTextureWidth) {
+ *swapchainTextureWidth = 0;
+ }
+ if (swapchainTextureHeight) {
+ *swapchainTextureHeight = 0;
+ }
windowData = D3D11_INTERNAL_FetchWindowData(window);
if (windowData == NULL) {
@@ -5489,6 +5503,13 @@ static bool D3D11_AcquireSwapchainTexture(
}
}
+ if (swapchainTextureWidth) {
+ *swapchainTextureWidth = windowData->width;
+ }
+ if (swapchainTextureHeight) {
+ *swapchainTextureHeight = windowData->height;
+ }
+
if (windowData->inFlightFences[windowData->frameCounter] != NULL) {
if (windowData->presentMode == SDL_GPU_PRESENTMODE_VSYNC) {
// In VSYNC mode, block until the least recent presented frame is done
diff --git a/src/gpu/d3d12/SDL_gpu_d3d12.c b/src/gpu/d3d12/SDL_gpu_d3d12.c
index 20a6367ee48f4..6807c8f0115b4 100644
--- a/src/gpu/d3d12/SDL_gpu_d3d12.c
+++ b/src/gpu/d3d12/SDL_gpu_d3d12.c
@@ -554,6 +554,8 @@ typedef struct D3D12WindowData
D3D12TextureContainer textureContainers[MAX_FRAMES_IN_FLIGHT];
SDL_GPUFence *inFlightFences[MAX_FRAMES_IN_FLIGHT];
+ Uint32 width;
+ Uint32 height;
bool needsSwapchainRecreate;
} D3D12WindowData;
@@ -6331,6 +6333,8 @@ static bool D3D12_INTERNAL_ResizeSwapchain(
}
}
+ windowData->width = w;
+ windowData->height = h;
windowData->needsSwapchainRecreate = false;
return true;
}
@@ -6382,6 +6386,9 @@ static bool D3D12_INTERNAL_CreateSwapchain(
swapchainFormat = SwapchainCompositionToTextureFormat[swapchainComposition];
+ int w, h;
+ SDL_GetWindowSizeInPixels(windowData->window, &w, &h);
+
// Initialize the swapchain buffer descriptor
swapchainDesc.Width = 0;
swapchainDesc.Height = 0;
@@ -6477,6 +6484,8 @@ static bool D3D12_INTERNAL_CreateSwapchain(
windowData->swapchainComposition = swapchainComposition;
windowData->swapchainColorSpace = SwapchainCompositionToColorSpace[swapchainComposition];
windowData->frameCounter = 0;
+ windowData->width = w;
+ windowData->height = h;
// Precache blit pipelines for the swapchain format
for (Uint32 i = 0; i < 5; i += 1) {
@@ -6907,7 +6916,9 @@ static SDL_GPUCommandBuffer *D3D12_AcquireCommandBuffer(
static bool D3D12_AcquireSwapchainTexture(
SDL_GPUCommandBuffer *commandBuffer,
SDL_Window *window,
- SDL_GPUTexture **swapchainTexture)
+ SDL_GPUTexture **swapchainTexture,
+ Uint32 *swapchainTextureWidth,
+ Uint32 *swapchainTextureHeight)
{
D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
D3D12Renderer *renderer = d3d12CommandBuffer->renderer;
@@ -6916,6 +6927,12 @@ static bool D3D12_AcquireSwapchainTexture(
HRESULT res;
*swapchainTexture = NULL;
+ if (swapchainTextureWidth) {
+ *swapchainTextureWidth = 0;
+ }
+ if (swapchainTextureHeight) {
+ *swapchainTextureHeight = 0;
+ }
windowData = D3D12_INTERNAL_FetchWindowData(window);
if (windowData == NULL) {
@@ -6928,6 +6945,13 @@ static bool D3D12_AcquireSwapchainTexture(
}
}
+ if (swapchainTextureWidth) {
+ *swapchainTextureWidth = windowData->width;
+ }
+ if (swapchainTextureHeight) {
+ *swapchainTextureHeight = windowData->height;
+ }
+
if (windowData->inFlightFences[windowData->frameCounter] != NULL) {
if (windowData->present_mode == SDL_GPU_PRESENTMODE_VSYNC) {
// In VSYNC mode, block until the least recent presented frame is done
diff --git a/src/gpu/metal/SDL_gpu_metal.m b/src/gpu/metal/SDL_gpu_metal.m
index 70d59400694db..fd118bc69d75c 100644
--- a/src/gpu/metal/SDL_gpu_metal.m
+++ b/src/gpu/metal/SDL_gpu_metal.m
@@ -3590,7 +3590,9 @@ static void METAL_ReleaseWindow(
static bool METAL_AcquireSwapchainTexture(
SDL_GPUCommandBuffer *commandBuffer,
SDL_Window *window,
- SDL_GPUTexture **texture)
+ SDL_GPUTexture **texture,
+ Uint32 *swapchainTextureWidth,
+ Uint32 *swapchainTextureHeight)
{
@autoreleasepool {
MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
@@ -3599,6 +3601,12 @@ static bool METAL_AcquireSwapchainTexture(
CGSize drawableSize;
*texture = NULL;
+ if (swapchainTextureWidth) {
+ *swapchainTextureWidth = 0;
+ }
+ if (swapchainTextureHeight) {
+ *swapchainTextureHeight = 0;
+ }
windowData = METAL_INTERNAL_FetchWindowData(window);
if (windowData == NULL) {
@@ -3613,6 +3621,12 @@ static bool METAL_AcquireSwapchainTexture(
drawableSize = windowData->layer.drawableSize;
windowData->textureContainer.header.info.width = (Uint32)drawableSize.width;
windowData->textureContainer.header.info.height = (Uint32)drawableSize.height;
+ if (swapchainTextureWidth) {
+ *swapchainTextureWidth = (Uint32)drawableSize.width;
+ }
+ if (swapchainTextureHeight) {
+ *swapchainTextureHeight = (Uint32)drawableSize.height;
+ }
// Set up presentation
if (metalCommandBuffer->windowDataCount == metalCommandBuffer->windowDataCapacity) {
diff --git a/src/gpu/vulkan/SDL_gpu_vulkan.c b/src/gpu/vulkan/SDL_gpu_vulkan.c
index 280b2bacca9f3..81e476a9eebf2 100644
--- a/src/gpu/vulkan/SDL_gpu_vulkan.c
+++ b/src/gpu/vulkan/SDL_gpu_vulkan.c
@@ -665,8 +665,13 @@ typedef struct VulkanFramebuffer
SDL_AtomicInt referenceCount;
} VulkanFramebuffer;
-typedef struct VulkanSwapchainData
+typedef struct WindowData
{
+ SDL_Window *window;
+ SDL_GPUSwapchainComposition swapchainComposition;
+ SDL_GPUPresentMode presentMode;
+ bool needsSwapchainRecreate;
+
// Window surface
VkSurfaceKHR surface;
@@ -675,12 +680,13 @@ typedef struct VulkanSwapchainData
VkFormat format;
VkColorSpaceKHR colorSpace;
VkComponentMapping swapchainSwizzle;
- VkPresentModeKHR presentMode;
bool usingFallbackFormat;
// Swapchain images
VulkanTextureContainer *textureContainers; // use containers so that swapchain textures can use the same API as other textures
Uint32 imageCount;
+ Uint32 width;
+ Uint32 height;
// Synchronization primitives
VkSemaphore imageAvailableSemaphore[MAX_FRAMES_IN_FLIGHT];
@@ -688,15 +694,6 @@ typedef struct VulkanSwapchainData
SDL_GPUFence *inFlightFences[MAX_FRAMES_IN_FLIGHT];
Uint32 frameCounter;
-} VulkanSwapchainData;
-
-typedef struct WindowData
-{
- SDL_Window *window;
- SDL_GPUSwapchainComposition swapchainComposition;
- SDL_GPUPresentMode presentMode;
- VulkanSwapchainData *swapchainData;
- bool needsSwapchainRecreate;
} WindowData;
typedef struct SwapchainSupportDetails
@@ -1863,7 +1860,7 @@ static Uint8 VULKAN_INTERNAL_BindImageMemory(
SDL_UnlockMutex(usedRegion->allocation->memoryLock);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkBindBufferMemory, 0)
+ CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkBindImageMemory, 0)
return 1;
}
@@ -3110,57 +3107,61 @@ static void VULKAN_INTERNAL_DestroySwapchain(
WindowData *windowData)
{
Uint32 i;
- VulkanSwapchainData *swapchainData;
if (windowData == NULL) {
return;
}
- swapchainData = windowData->swapchainData;
-
- if (swapchainData == NULL) {
- return;
- }
-
- for (i = 0; i < swapchainData->imageCount; i += 1) {
+ for (i = 0; i < windowData->imageCount; i += 1) {
VULKAN_INTERNAL_RemoveFramebuffersContainingView(
renderer,
- swapchainData->textureContainers[i].activeTexture->subresources[0].renderTargetViews[0]);
+ windowData->textureContainers[i].activeTexture->subresources[0].renderTargetViews[0]);
renderer->vkDestroyImageView(
renderer->logicalDevice,
- swapchainData->textureContainers[i].activeTexture->subresources[0].renderTargetViews[0],
+ windowData->textureContainers[i].activeTexture->subresources[0].renderTargetViews[0],
NULL);
- SDL_free(swapchainData->textureContainers[i].activeTexture->subresources[0].renderTargetViews);
- SDL_free(swapchainData->textureContainers[i].activeTexture->subresources);
- SDL_free(swapchainData->textureContainers[i].activeTexture);
+ SDL_free(windowData->textureContainers[i].activeTexture->subresources[0].renderTargetViews);
+ SDL_free(windowData->textureContainers[i].activeTexture->subresources);
+ SDL_free(windowData->textureContainers[i].activeTexture);
}
+ windowData->imageCount = 0;
- SDL_free(swapchainData->textureContainers);
-
- renderer->vkDestroySwapchainKHR(
- renderer->logicalDevice,
- swapchainData->swapchain,
- NULL);
-
- renderer->vkDestroySurfaceKHR(
- renderer->instance,
- swapchainData->surface,
- NULL);
+ SDL_free(windowData->textureContainers);
+ windowData->textureContainers = NULL;
- for (i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
- renderer->vkDestroySemaphore(
+ if (windowData->swapchain) {
+ renderer->vkDestroySwapchainKHR(
renderer->logicalDevice,
- swapchainData->imageAvailableSemaphore[i],
+ windowData->swapchain,
NULL);
+ windowData->swapchain = VK_NULL_HANDLE;
+ }
- renderer->vkDestroySemaphore(
- renderer->logicalDevice,
- swapchainData->renderFinishedSemaphore[i],
+ if (windowData->surface) {
+ renderer->vkDestroySurfaceKHR(
+ renderer->instance,
+ windowData->surface,
NULL);
+ windowData->surface = VK_NULL_HANDLE;
}
- windowData->swapchainData = NULL;
- SDL_free(swapchainData);
+ for (i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
+ if (windowData->imageAvailableSemaphore[i]) {
+ renderer->vkDestroySemaphore(
+ renderer->logicalDevice,
+ windowData->imageAvailableSemaphore[i],
+ NULL);
+ windowData->imageAvailableSemaphore[i] = VK_NULL_HANDLE;
+ }
+
+ if (windowData->renderFinishedSemaphore[i]) {
+ renderer->vkDestroySemaphore(
+ renderer->logicalDevice,
+ windowData->renderFinishedSemaphore[i],
+ NULL);
+ windowData->renderFinishedSemaphore[i] = VK_NULL_HANDLE;
+ }
+ }
}
static void VULKAN_INTERNAL_DestroyGraphicsPipelineResourceLayout(
@@ -4360,12 +4361,21 @@ static bool VULKAN_INTERNAL_VerifySwapPresentMode(
return false;
}
-static bool VULKAN_INTERNAL_CreateSwapchain(
+/* It would be nice if VULKAN_INTERNAL_CreateSwapchain could return a bool.
+ * Unfortunately, some Win32 NVIDIA drivers are stupid
+ * and will return surface extents of (0, 0)
+ * in certain edge cases, and the swapchain extents are not allowed to be 0.
+ * In this case, the client probably still wants to claim the window
+ * or recreate the swapchain, so we should return 2 to indicate retry.
+ * -cosmonaut
+ */
+#define VULKAN_INTERNAL_TRY_AGAIN 2
+
+static Uint32 VULKAN_INTERNAL_CreateSwapchain(
VulkanRenderer *renderer,
WindowData *windowData)
{
VkResult vulkanResult;
- VulkanSwapchainData *swapchainData;
VkSwapchainCreateInfoKHR swapchainCreateInfo;
VkImage *swapchainImages;
VkSemaphoreCreateInfo semaphoreCreateInfo;
@@ -4377,18 +4387,15 @@ static bool VULKAN_INTERNAL_CreateSwapchain(
SDL_assert(_this && _this->Vulkan_CreateSurface);
- swapchainData = SDL_malloc(sizeof(VulkanSwapchainData));
- swapchainData->frameCounter = 0;
+ windowData->frameCounter = 0;
// Each swapchain must have its own surface.
-
if (!_this->Vulkan_CreateSurface(
_this,
windowData->window,
renderer->instance,
NULL, // FIXME: VAllocationCallbacks
- &swapchainData->surface)) {
- SDL_free(swapchainData);
+ &windowData->surface)) {
SDL_LogError(
SDL_LOG_CATEGORY_GPU,
"Vulkan_CreateSurface failed: %s",
@@ -4399,11 +4406,11 @@ static bool VULKAN_INTERNAL_CreateSwapchain(
if (!VULKAN_INTERNAL_QuerySwapchainSupport(
renderer,
renderer->physicalDevice,
- swapchainData->surface,
+ windowData->surface,
&swapchainSupportDetails)) {
renderer->vkDestroySurfaceKHR(
renderer->instance,
- swapchainData->surface,
+ windowData->surface,
NULL);
if (swapchainSupportDetails.formatsLength > 0) {
SDL_free(swapchainSupportDetails.formats);
@@ -4411,61 +4418,41 @@ static bool VULKAN_INTERNAL_CreateSwapchain(
if (swapchainSupportDetails.presentModesLength > 0) {
SDL_free(swapchainSupportDetails.presentModes);
}
- SDL_free(swapchainData);
- return false;
- }
-
- if (swapchainSupportDetails.capabilities.currentExtent.width == 0 ||
- swapchainSupportDetails.capabilities.currentExtent.height == 0) {
- // Not an error, just minimize behavior!
- 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);
return false;
}
// Verify that we can use the requested composition and present mode
-
- swapchainData->format = SwapchainCompositionToFormat[windowData->swapchainComposition];
- swapchainData->colorSpace = SwapchainCompositionToColorSpace[windowData->swapchainComposition];
- swapchainData->swapchainSwizzle = SwapchainCompositionSwizzle[windowData->swapchainComposition];
- swapchainData->usingFallbackFormat = false;
+ windowData->format = SwapchainCompositionToFormat[windowData->swapchainComposition];
+ windowData->colorSpace = SwapchainCompositionToColorSpace[windowData->swapchainComposition];
+ windowData->swapchainSwizzle = SwapchainCompositionSwizzle[windowData->swapchainComposition];
+ windowData->usingFallbackFormat = false;
hasValidSwapchainComposition = VULKAN_INTERNAL_VerifySwapSurfaceFormat(
- swapchainData->format,
- swapchainData->colorSpace,
+ windowData->format,
+ windowData->colorSpace,
swapchainSupportDetails.formats,
swapchainSupportDetails.formatsLength);
if (!hasValidSwapchainComposition) {
// Let's try again with the fallback format...
- swapchainData->format = SwapchainCompositionToFallbackFormat[windowData->swapchainComposition];
- swapchainData->usingFallbackFormat = true;
+ windowData->format = SwapchainCompositionToFallbackFormat[windowData->swapchainComposition];
+ windowData->usingFallbackFormat = true;
hasValidSwapchainComposition = VULKAN_INTERNAL_VerifySwapSurfaceFormat(
- swapchainData->format,
- swapchainData->colorSpace,
+ windowData->format,
+ windowData->colorSpace,
swapchainSupportDetails.formats,
swapchainSupportDetails.formatsLength);
}
- swapchainData->presentMode = SDLToVK_PresentMode[windowData->presentMode];
hasValidPresentMode = VULKAN_INTERNAL_VerifySwapPresentMode(
- swapchainData->presentMode,
+ SDLToVK_PresentMode[windowData->presentMode],
swapchainSupportDetails.presentModes,
swapchainSupportDetails.presentModesLength);
if (!hasValidSwapchainComposition || !hasValidPresentMode) {
renderer->vkDestroySurfaceKHR(
renderer->instance,
- swapchainData->surface,
+ windowData->surface,
NULL);
if (swapchainSupportDetails.formatsLength > 0) {
@@ -4476,8 +4463,6 @@ static bool VULKAN_INTERNAL_CreateSwapchain(
SDL_free(swapchainSupportDetails.presentModes);
}
- SDL_free(swapchainData);
-
if (!hasValidSwapchainComposition) {
SET_STRING_ERROR_AND_RETURN("Device does not support requested swapchain composition!", false);
}
@@ -4487,6 +4472,22 @@ static bool VULKAN_INTERNAL_CreateSwapchain(
return false;
}
+ // NVIDIA + Win32 can return 0 extent when the window is minimized. Try again!
+ if (swapchainSupportDetails.capabilities.currentExtent.width == 0 ||
+ swapchainSupportDetails.capabilities.currentExtent.height == 0) {
+ renderer->vkDestroySurfaceKHR(
+ renderer->instance,
+ windowData->surface,
+ NULL);
+ if (swapchainSupportDetails.formatsLength > 0) {
+ SDL_free(swapchainSupportDetails.formats);
+ }
+ if (swapchainSupportDetails.presentModesLength > 0) {
+ SDL_free(swapchainSupportDetails.presentModes);
+ }
+ return VULKAN_INTERNAL_TRY_AGAIN;
+ }
+
// Sync now to be sure that our swapchain size is correct
SDL_SyncWindow(windowData->window);
SDL_GetWindowSizeInPixels(
@@ -4494,34 +4495,36 @@ static bool VULKAN_INTERNAL_CreateSwapchain(
&drawableWidth,
&drawableHeight);
- swapchainData->imageCount = MAX_FRAMES_IN_FLIGHT;
+ windowData->imageCount = MAX_FRAMES_IN_FLIGHT;
+ windowData->width = drawableWidth;
+ windowData->height = drawableHeight;
if (swapchainSupportDetails.capabilities.maxImageCount > 0 &&
- swapchainData->imageCount > swapchainSupportDetails.capabilities.maxImageCount) {
- swapchainData->imageCount = swapchainSupportDetails.capabilities.maxImageCount;
+ windowData->imageCount > swapchainSupportDetails.capabilities.maxImageCount) {
+ windowData->imageCount = swapchainSupportDetails.capabilities.maxImageCount;
}
- if (swapchainData->imageCount < swapchainSupportDetails.capabilities.minImageCount) {
- swapchainData->imageCount = swapchainSupportDetails.capabilities.minImageCount;
+ if (windowData->imageCount < swapchainSupportDetails.capabilities.minImageCount) {
+ windowData->imageCount = swapchainSupportDetails.capabilities.minImageCount;
}
- if (swapchainData->presentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
+ if (windowData->presentMode == SDL_GPU_PRESENTMODE_MAILBOX) {
/* Required for proper triple-buffering.
* Note that this is below the above maxImageCount check!
* If the driver advertises MAILBOX but does not support 3 swap
* images, it's not real mailbox support, so let it fail hard.
* -flibit
*/
- swapchainData->imageCount = SDL_max(swapchainData->imageCount, 3);
+ windowData->imageCount = SDL_max(windowData->imageCount, 3);
}
swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
swapchainCreateInfo.pNext = NULL;
swapchainCreateInfo.flags = 0;
- swapchainCreateInfo.surface = swapchainData->surface;
- swapchainCreateInfo.minImageCount = swapchainData->imageCount;
- swapchainCreateInfo.imageFormat = swapchainData->format;
- swapchainCreateInfo.imageColorSpace = swapchainData->colorSpace;
+ swapchainCreateInfo.surface = windowData->surface;
+ swapchainCreateInfo.minImageCount = windowData->imageCount;
+ swapchainCreateInfo.imageFormat = windowData->format;
+ swapchainCreateInfo.imageColorSpace = windowData->colorSpace;
swapchainCreateInfo.imageExtent.width = drawableWidth;
swapchainCreateInfo.imageExtent.height = drawableHeight;
swapchainCreateInfo.imageArrayLayers = 1;
@@ -4533,7 +4536,7 @@ static bool VULKAN_INTERNAL_CreateSwapchain(
swapchainCreateInfo.pQueueFamilyIndices = NULL;
swapchainCreateInfo.preTransform = swapchainSupportDetails.capabilities.currentTransform;
swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
- swapchainCreateInfo.presentMode = swapchainData->presentMode;
+ swapchainCreateInfo.presentMode = SDLToVK_PresentMode[windowData->presentMode];
swapchainCreateInfo.clipped = VK_TRUE;
swapchainCreateInfo.oldSwapchain = VK_NULL_HANDLE;
@@ -4541,7 +4544,7 @@ static bool VULKAN_INTERNAL_CreateSwapchain(
renderer->logicalDevice,
&swapchainCreateInfo,
NULL,
- &swapchainData->swapchain);
+ &windowData->swapchain);
if (swapchainSupportDetails.formatsLength > 0) {
SDL_free(swapchainSupportDetails.formats);
@@ -4553,87 +4556,83 @@ static bool VULKAN_INTERNAL_CreateSwapchain(
if (vulkanResult != VK_SUCCESS) {
renderer->vkDestroySurfaceKHR(
renderer->instance,
- swapchainData->surface,
+ windowData->surface,
NULL);
- SDL_free(swapchainData);
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateSwapchainKHR, false)
}
- renderer->vkGetSwapchainImagesKHR(
+ vulkanResult = renderer->vkGetSwapchainImagesKHR(
renderer->logicalDevice,
- swapchainData->swapchain,
- &swapchainData->imageCount,
+ windowData->swapchain,
+ &windowData->imageCount,
NULL);
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkGetSwapchainImagesKHR, false)
- swapchainData->textureContainers = SDL_malloc(
- sizeof(VulkanTextureContainer) * swapchainData->imageCount);
+ windowData->textureContainers = SDL_malloc(
+ sizeof(VulkanTextureContainer) * windowData->imageCount);
- if (!swapchainData->textureContainers) {
+ if (!windowData->textureContainers) {
renderer->vkDestroySurfaceKHR(
renderer->instance,
- swapchainData->surface,
+ windowData->surface,
NULL);
- SDL_free(swapchainData);
return false;
}
- swapchainImages = SDL_stack_alloc(VkImage, swapchainData->imageCount);
+ swapchainImages = SDL_stack_alloc(VkImage, windowData->imageCount);
vulkanResult = renderer->vkGetSwapchainImagesKHR(
renderer->logicalDevice,
- swapchainData->swapchain,
- &swapchainData->imageCount,
+ windowData->swapchain,
+ &windowData->imageCount,
swapchainImages);
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkGetSwapchainImagesKHR, false)
- for (i = 0; i < swapchainData->imageCount; i += 1) {
+ for (i = 0; i < windowData->imageCount; i += 1) {
// Initialize dummy container
- SDL_zero(swapchainData->textureContainers[i]);
- swapchainData->textureContainers[i].canBeCycled = false;
- swapchainData->textureContainers[i].header.info.width = drawableWidth;
- swapchainData->textureContainers[i].header.info.height = drawableHeight;
- swapchainData->textureContainers[i].header.info.layer_count_or_depth = 1;
- swapchainData->textureContainers[i].header.info.format = SwapchainCompositionToSDLFormat(
+ SDL_zero(windowData->textureContainers[i]);
+ windowData->textureContainers[i].canBeCycled = false;
+ windowData->textureContainers[i].header.info.width = drawableWidth;
+ windowData->textureContainers[i].header.info.height = drawableHeight;
+ windowData->text
(Patch may be truncated, please check the link at the top of this post.)