diff --git a/include/SDL3/SDL_gpu.h b/include/SDL3/SDL_gpu.h index 8b7417f16b..40f11a5fc2 100644 --- a/include/SDL3/SDL_gpu.h +++ b/include/SDL3/SDL_gpu.h @@ -1068,8 +1068,7 @@ typedef enum SDL_GPUSamplerAddressMode * Specifies the timing that will be used to present swapchain textures to the * OS. * - * Note that this value affects the behavior of - * SDL_AcquireGPUSwapchainTexture. VSYNC mode will always be supported. + * VSYNC mode will always be supported. * IMMEDIATE and MAILBOX modes may not be supported on certain systems. * * It is recommended to query SDL_WindowSupportsGPUPresentMode after claiming @@ -1077,17 +1076,12 @@ typedef enum SDL_GPUSamplerAddressMode * * - VSYNC: Waits for vblank before presenting. No tearing is possible. If * there is a pending image to present, the new image is enqueued for - * presentation. Disallows tearing at the cost of visual latency. When using - * this present mode, AcquireGPUSwapchainTexture will block if too many - * frames are in flight. + * presentation. Disallows tearing at the cost of visual latency. * - IMMEDIATE: Immediately presents. Lowest latency option, but tearing may - * occur. When using this mode, AcquireGPUSwapchainTexture will fill the - * swapchain texture pointer with NULL if too many frames are in flight. + * occur. * - MAILBOX: Waits for vblank before presenting. No tearing is possible. If * there is a pending image to present, the pending image is replaced by the - * new image. Similar to VSYNC, but with reduced visual latency. When using - * this mode, AcquireGPUSwapchainTexture will fill the swapchain texture - * pointer with NULL if too many frames are in flight. + * new image. Similar to VSYNC, but with reduced visual latency. * * \since This enum is available since SDL 3.1.3 * @@ -3442,6 +3436,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_WindowSupportsGPUPresentMode( * \returns true on success, or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function should only be called from the thread that created the window. + * * \since This function is available since SDL 3.1.3. * * \sa SDL_AcquireGPUSwapchainTexture @@ -3501,8 +3497,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetGPUSwapchainParameters( * * The default value when the device is created is 2. This means that after * you have submitted 2 frames for presentation, if the GPU has not finished - * working on the first frame, SDL_AcquireGPUSwapchainTexture() will block or - * return false depending on the present mode. + * working on the first frame, SDL_AcquireGPUSwapchainTexture() will fill the swapchain texture pointer with NULL, + * and SDL_WaitAndAcquireGPUSwapchainTexture() will block. * * Higher values increase throughput at the expense of visual latency. Lower * values decrease visual latency at the expense of throughput. @@ -3514,9 +3510,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetGPUSwapchainParameters( * * \param device a GPU context. * \param allowed_frames_in_flight the maximum number of frames that can be - * pending on the GPU before - * AcquireSwapchainTexture blocks or returns - * false. + * pending on the GPU. * \returns true if successful, false on error; call SDL_GetError() for more * information. * @@ -3547,20 +3541,17 @@ 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 filled in - * with NULL under certain conditions. This is not necessarily an error. If - * this function returns false then there is an error. + * buffer used to acquire it. + * + * This function will fill the swapchain texture handle with NULL if too many frames are in flight. + * This is not an error. + * The best practice is to call SDL_CancelGPUCommandBuffer if the swapchain texture + * handle is NULL to avoid enqueuing needless work on the GPU. * * 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. * - * When using SDL_GPU_PRESENTMODE_VSYNC, this function will block if too many - * frames are in flight. Otherwise, this function will fill the swapchain - * texture handle with NULL if too many frames are in flight. The best - * practice is to call SDL_CancelGPUCommandBuffer if the swapchain texture - * handle is NULL to avoid enqueuing needless work on the GPU. - * * \param command_buffer a command buffer. * \param window a window that has been claimed. * \param swapchain_texture a pointer filled in with a swapchain texture @@ -3572,14 +3563,17 @@ extern SDL_DECLSPEC SDL_GPUTextureFormat SDLCALL SDL_GetGPUSwapchainTextureForma * \returns true on success, false on error; call SDL_GetError() for more * information. * + * \threadsafety This function should only be called from the thread that created the window. + * * \since This function is available since SDL 3.1.3. * - * \sa SDL_GPUPresentMode * \sa SDL_ClaimWindowForGPUDevice * \sa SDL_SubmitGPUCommandBuffer * \sa SDL_SubmitGPUCommandBufferAndAcquireFence * \sa SDL_CancelGPUCommandBuffer * \sa SDL_GetWindowSizeInPixels + * \sa SDL_WaitForGPUSwapchain + * \sa SDL_SetGPUAllowedFramesInFlight */ extern SDL_DECLSPEC bool SDLCALL SDL_AcquireGPUSwapchainTexture( SDL_GPUCommandBuffer *command_buffer, @@ -3588,6 +3582,62 @@ extern SDL_DECLSPEC bool SDLCALL SDL_AcquireGPUSwapchainTexture( Uint32 *swapchain_texture_width, Uint32 *swapchain_texture_height); +/** + * Blocks the thread until a swapchain texture is available to be acquired. + * + * \param device a GPU context. + * \param window a window that has been claimed. + * \returns true on success, false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should only be called from the thread that created the window. + * + * \since This function is available since SDL 3.2.0. + * + * \sa SDL_AcquireGPUSwapchainTexture + * \sa SDL_SetGPUAllowedFramesInFlight + */ +extern SDL_DECLSPEC bool SDLCALL SDL_WaitForGPUSwapchain( + SDL_GPUDevice *device, + SDL_Window *window); + +/** + * Blocks the thread until a swapchain texture is available to be acquired, and then acquires it. + * + * 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. It is an error to call SDL_CancelGPUCommandBuffer() after a swapchain texture is acquired. + * + * 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 swapchain_texture a pointer filled in with a swapchain texture + * handle. + * \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. + * + * \threadsafety This function should only be called from the thread that created the window. + * + * \since This function is available since SDL 3.2.0. + * + * \sa SDL_SubmitGPUCommandBuffer + * \sa SDL_SubmitGPUCommandBufferAndAcquireFence + */ +extern SDL_DECLSPEC bool SDLCALL SDL_WaitAndAcquireGPUSwapchainTexture( + SDL_GPUCommandBuffer *command_buffer, + SDL_Window *window, + 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.sym b/src/dynapi/SDL_dynapi.sym index cba2c63729..d575bcef93 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -974,6 +974,7 @@ SDL3_0.0.0 { SDL_WaitEventTimeout; SDL_WaitForGPUFences; SDL_WaitForGPUIdle; + SDL_WaitForGPUSwapchain; SDL_WaitProcess; SDL_WaitSemaphore; SDL_WaitSemaphoreTimeout; @@ -1205,6 +1206,7 @@ SDL3_0.0.0 { SDL_RunOnMainThread; SDL_SetGPUAllowedFramesInFlight; SDL_RenderTextureAffine; + SDL_WaitAndAcquireGPUSwapchainTexture; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 7dd37385ad..608d59ca1e 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -999,6 +999,7 @@ #define SDL_WaitEventTimeout SDL_WaitEventTimeout_REAL #define SDL_WaitForGPUFences SDL_WaitForGPUFences_REAL #define SDL_WaitForGPUIdle SDL_WaitForGPUIdle_REAL +#define SDL_WaitForGPUSwapchain SDL_WaitForGPUSwapchain_REAL #define SDL_WaitProcess SDL_WaitProcess_REAL #define SDL_WaitSemaphore SDL_WaitSemaphore_REAL #define SDL_WaitSemaphoreTimeout SDL_WaitSemaphoreTimeout_REAL @@ -1230,3 +1231,4 @@ #define SDL_RunOnMainThread SDL_RunOnMainThread_REAL #define SDL_SetGPUAllowedFramesInFlight SDL_SetGPUAllowedFramesInFlight_REAL #define SDL_RenderTextureAffine SDL_RenderTextureAffine_REAL +#define SDL_WaitAndAcquireGPUSwapchainTexture SDL_WaitAndAcquireGPUSwapchainTexture_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 1a9acd5001..4611595282 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -1009,6 +1009,7 @@ SDL_DYNAPI_PROC(bool,SDL_WaitEvent,(SDL_Event *a),(a),return) SDL_DYNAPI_PROC(bool,SDL_WaitEventTimeout,(SDL_Event *a, Sint32 b),(a,b),return) SDL_DYNAPI_PROC(bool,SDL_WaitForGPUFences,(SDL_GPUDevice *a, bool b, SDL_GPUFence *const *c, Uint32 d),(a,b,c,d),return) SDL_DYNAPI_PROC(bool,SDL_WaitForGPUIdle,(SDL_GPUDevice *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_WaitForGPUSwapchain,(SDL_GPUDevice *a, SDL_Window *b),(a,b),return) SDL_DYNAPI_PROC(bool,SDL_WaitProcess,(SDL_Process *a, bool b, int *c),(a,b,c),return) SDL_DYNAPI_PROC(void,SDL_WaitSemaphore,(SDL_Semaphore *a),(a),) SDL_DYNAPI_PROC(bool,SDL_WaitSemaphoreTimeout,(SDL_Semaphore *a, Sint32 b),(a,b),return) @@ -1236,3 +1237,4 @@ SDL_DYNAPI_PROC(bool,SDL_IsMainThread,(void),(),return) SDL_DYNAPI_PROC(bool,SDL_RunOnMainThread,(SDL_MainThreadCallback a,void *b,bool c),(a,b,c),return) SDL_DYNAPI_PROC(bool,SDL_SetGPUAllowedFramesInFlight,(SDL_GPUDevice *a,Uint32 b),(a,b),return) SDL_DYNAPI_PROC(bool,SDL_RenderTextureAffine,(SDL_Renderer *a,SDL_Texture *b,const SDL_FRect *c,const SDL_FPoint *d,const SDL_FPoint *e,const SDL_FPoint *f),(a,b,c,d,e,f),return) +SDL_DYNAPI_PROC(bool,SDL_WaitAndAcquireGPUSwapchainTexture,(SDL_GPUCommandBuffer *a,SDL_Window *b,SDL_GPUTexture **c,Uint32 *d,Uint32 *e),(a,b,c,d,e),return) diff --git a/src/gpu/SDL_gpu.c b/src/gpu/SDL_gpu.c index 5763e793dd..bc1cb1a288 100644 --- a/src/gpu/SDL_gpu.c +++ b/src/gpu/SDL_gpu.c @@ -2694,16 +2694,13 @@ bool SDL_AcquireGPUSwapchainTexture( CommandBufferCommonHeader *commandBufferHeader = (CommandBufferCommonHeader *)command_buffer; if (command_buffer == NULL) { - SDL_InvalidParamError("command_buffer"); - return false; + return SDL_InvalidParamError("command_buffer"); } if (window == NULL) { - SDL_InvalidParamError("window"); - return false; + return SDL_InvalidParamError("window"); } if (swapchain_texture == NULL) { - SDL_InvalidParamError("swapchain_texture"); - return false; + return SDL_InvalidParamError("swapchain_texture"); } if (COMMAND_BUFFER_DEVICE->debug_mode) { @@ -2725,6 +2722,59 @@ bool SDL_AcquireGPUSwapchainTexture( return result; } +bool SDL_WaitForGPUSwapchain( + SDL_GPUDevice *device, + SDL_Window *window) +{ + CHECK_DEVICE_MAGIC(device, false); + + if (window == NULL) { + return SDL_InvalidParamError("window"); + } + + return device->WaitForSwapchain( + device->driverData, + window); +} + +bool SDL_WaitAndAcquireGPUSwapchainTexture( + SDL_GPUCommandBuffer *command_buffer, + SDL_Window *window, + SDL_GPUTexture **swapchain_texture, + Uint32 *swapchain_texture_width, + Uint32 *swapchain_texture_height) +{ + CommandBufferCommonHeader *commandBufferHeader = (CommandBufferCommonHeader *)command_buffer; + + if (command_buffer == NULL) { + return SDL_InvalidParamError("command_buffer"); + } + if (window == NULL) { + return SDL_InvalidParamError("window"); + } + if (swapchain_texture == NULL) { + return SDL_InvalidParamError("swapchain_texture"); + } + + if (COMMAND_BUFFER_DEVICE->debug_mode) { + CHECK_COMMAND_BUFFER_RETURN_FALSE + CHECK_ANY_PASS_IN_PROGRESS("Cannot acquire a swapchain texture during a pass!", false) + } + + bool result = COMMAND_BUFFER_DEVICE->WaitAndAcquireSwapchainTexture( + command_buffer, + window, + swapchain_texture, + swapchain_texture_width, + swapchain_texture_height); + + if (*swapchain_texture != NULL){ + commandBufferHeader->swapchain_texture_acquired = true; + } + + return result; +} + bool SDL_SubmitGPUCommandBuffer( SDL_GPUCommandBuffer *command_buffer) { diff --git a/src/gpu/SDL_sysgpu.h b/src/gpu/SDL_sysgpu.h index 2cf8f6459b..901fd9aba2 100644 --- a/src/gpu/SDL_sysgpu.h +++ b/src/gpu/SDL_sysgpu.h @@ -811,6 +811,17 @@ struct SDL_GPUDevice Uint32 *swapchainTextureWidth, Uint32 *swapchainTextureHeight); + bool (*WaitForSwapchain)( + SDL_GPURenderer *driverData, + SDL_Window *window); + + bool (*WaitAndAcquireSwapchainTexture)( + SDL_GPUCommandBuffer *commandBuffer, + SDL_Window *window, + SDL_GPUTexture **swapchainTexture, + Uint32 *swapchainTextureWidth, + Uint32 *swapchainTextureHeight); + bool (*Submit)( SDL_GPUCommandBuffer *commandBuffer); @@ -937,6 +948,8 @@ struct SDL_GPUDevice ASSIGN_DRIVER_FUNC(GetSwapchainTextureFormat, name) \ ASSIGN_DRIVER_FUNC(AcquireCommandBuffer, name) \ ASSIGN_DRIVER_FUNC(AcquireSwapchainTexture, name) \ + ASSIGN_DRIVER_FUNC(WaitForSwapchain, name) \ + ASSIGN_DRIVER_FUNC(WaitAndAcquireSwapchainTexture, name)\ ASSIGN_DRIVER_FUNC(Submit, name) \ ASSIGN_DRIVER_FUNC(SubmitAndAcquireFence, name) \ ASSIGN_DRIVER_FUNC(Cancel, name) \ diff --git a/src/gpu/d3d12/SDL_gpu_d3d12.c b/src/gpu/d3d12/SDL_gpu_d3d12.c index 7b024f0b02..f42c72bf80 100644 --- a/src/gpu/d3d12/SDL_gpu_d3d12.c +++ b/src/gpu/d3d12/SDL_gpu_d3d12.c @@ -7124,7 +7124,32 @@ static SDL_GPUCommandBuffer *D3D12_AcquireCommandBuffer( return (SDL_GPUCommandBuffer *)commandBuffer; } -static bool D3D12_AcquireSwapchainTexture( +static bool D3D12_WaitForSwapchain( + SDL_GPURenderer *driverData, + SDL_Window *window) +{ + D3D12Renderer *renderer = (D3D12Renderer *)driverData; + D3D12WindowData *windowData = D3D12_INTERNAL_FetchWindowData(window); + + if (windowData == NULL) { + SET_STRING_ERROR_AND_RETURN("Cannot wait for a swapchain from an unclaimed window!", false); + } + + if (windowData->inFlightFences[windowData->frameCounter] != NULL) { + if (!D3D12_WaitForFences( + driverData, + true, + &windowData->inFlightFences[windowData->frameCounter], + 1)) { + return false; + } + } + + return true; +} + +static bool D3D12_INTERNAL_AcquireSwapchainTexture( + bool block, SDL_GPUCommandBuffer *commandBuffer, SDL_Window *window, SDL_GPUTexture **swapchainTexture, @@ -7164,7 +7189,7 @@ static bool D3D12_AcquireSwapchainTexture( } if (windowData->inFlightFences[windowData->frameCounter] != NULL) { - if (windowData->present_mode == SDL_GPU_PRESENTMODE_VSYNC) { + if (block) { // In VSYNC mode, block until the least recent presented frame is done if (!D3D12_WaitForFences( (SDL_GPURenderer *)renderer, @@ -7174,13 +7199,11 @@ static bool D3D12_AcquireSwapchainTexture( return false; } } else { + // If we are not blocking and the least recent fence is not signaled, + // return true to indicate that there is no error but rendering should be skipped. if (!D3D12_QueryFence( (SDL_GPURenderer *)renderer, windowData->inFlightFences[windowData->frameCounter])) { - /* - * In MAILBOX or IMMEDIATE mode, if the least recent fence is not signaled, - * return true to indicate that there is no error but rendering should be skipped - */ return true; } } @@ -7238,6 +7261,38 @@ static bool D3D12_AcquireSwapchainTexture( return true; } +static bool D3D12_AcquireSwapchainTexture( + SDL_GPUCommandBuffer *command_buffer, + SDL_Window *window, + SDL_GPUTexture **swapchain_texture, + Uint32 *swapchain_texture_width, + Uint32 *swapchain_texture_height +) { + return D3D12_INTERNAL_AcquireSwapchainTexture( + false, + command_buffer, + window, + swapchain_texture, + swapchain_texture_width, + swapchain_texture_height); +} + +static bool D3D12_WaitAndAcquireSwapchainTexture( + SDL_GPUCommandBuffer *command_buffer, + SDL_Window *window, + SDL_GPUTexture **swapchain_texture, + Uint32 *swapchain_texture_width, + Uint32 *swapchain_texture_height +) { + return D3D12_INTERNAL_AcquireSwapchainTexture( + true, + command_buffer, + window, + swapchain_texture, + swapchain_texture_width, + swapchain_texture_height); +} + static void D3D12_INTERNAL_PerformPendingDestroys(D3D12Renderer *renderer) { SDL_LockMutex(renderer->disposeLock); diff --git a/src/gpu/metal/SDL_gpu_metal.m b/src/gpu/metal/SDL_gpu_metal.m index 981355a3ad..be64b366ff 100644 --- a/src/gpu/metal/SDL_gpu_metal.m +++ b/src/gpu/metal/SDL_gpu_metal.m @@ -3671,7 +3671,34 @@ static void METAL_ReleaseWindow( } } -static bool METAL_AcquireSwapchainTexture( +static bool METAL_WaitForSwapchain( + SDL_GPURenderer *driverData, + SDL_Window *window) +{ + @autoreleasepool { + MetalRenderer *renderer = (MetalRenderer *)driverData; + MetalWindowData *windowData = METAL_INTERNAL_FetchWindowData(window); + + if (windowData == NULL) { + SET_STRING_ERROR_AND_RETURN("Cannot wait for a swapchain from an unclaimed window!", false); + } + + if (windowData->inFlightFences[windowData->frameCounter] != NULL) { + if (!METAL_WaitForFences( + driverData, + true, + &windowData->inFlightFences[windowData->frameCounter], + 1)) { + return false; + } + } + + return true; + } +} + +static bool METAL_INTERNAL_AcquireSwapchainTexture( + bool block, SDL_GPUCommandBuffer *commandBuffer, SDL_Window *window, SDL_GPUTexture **texture, @@ -3709,8 +3736,8 @@ static bool METAL_AcquireSwapchainTexture( } 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 + if (block) { + // If we are blocking, just wait for the fence! if (!METAL_WaitForFences( (SDL_GPURenderer *)renderer, true, @@ -3719,13 +3746,11 @@ static bool METAL_AcquireSwapchainTexture( return false; } } else { + // If we are not blocking and the least recent fence is not signaled, + // return true to indicate that there is no error but rendering should be skipped. if (!METAL_QueryFence( (SDL_GPURenderer *)metalCommandBuffer->renderer, windowData->inFlightFences[windowData->frameCounter])) { - /* - * In IMMEDIATE mode, if the least recent fence is not signaled, - * return true to indicate that there is no error but rendering should be skipped - */ return true; } } @@ -3757,6 +3782,38 @@ static bool METAL_AcquireSwapchainTexture( } } +static bool METAL_AcquireSwapchainTexture( + SDL_GPUCommandBuffer *command_buffer, + SDL_Window *window, + SDL_GPUTexture **swapchain_texture, + Uint32 *swapchain_texture_width, + Uint32 *swapchain_texture_height +) { + return METAL_INTERNAL_AcquireSwapchainTexture( + false, + command_buffer, + window, + swapchain_texture, + swapchain_texture_width, + swapchain_texture_height); +} + +static bool METAL_WaitAndAcquireSwapchainTexture( + SDL_GPUCommandBuffer *command_buffer, + SDL_Window *window, + SDL_GPUTexture **swapchain_texture, + Uint32 *swapchain_texture_width, + Uint32 *swapchain_texture_height +) { + return METAL_INTERNAL_AcquireSwapchainTexture( + true, + command_buffer, + window, + swapchain_texture, + swapchain_texture_width, + swapchain_texture_height); +} + static SDL_GPUTextureFormat METAL_GetSwapchainTextureFormat( SDL_GPURenderer *driverData, SDL_Window *window) diff --git a/src/gpu/vulkan/SDL_gpu_vulkan.c b/src/gpu/vulkan/SDL_gpu_vulkan.c index 359aecdfeb..277e4246b4 100644 --- a/src/gpu/vulkan/SDL_gpu_vulkan.c +++ b/src/gpu/vulkan/SDL_gpu_vulkan.c @@ -9655,7 +9655,32 @@ static Uint32 VULKAN_INTERNAL_RecreateSwapchain( return VULKAN_INTERNAL_CreateSwapchain(renderer, windowData); } -static bool VULKAN_AcquireSwapchainTexture( +static bool VULKAN_WaitForSwapchain( + SDL_GPURenderer *driverData, + SDL_Window *window) +{ + VulkanRenderer *renderer = (VulkanRenderer *)driverData; + WindowData *windowData = VULKAN_INTERNAL_FetchWindowData(window); + + if (windowData == NULL) { + SET_STRING_ERROR_AND_RETURN("Cannot wait for a swapchain from an unclaimed window!", false); + } + + if (windowData->inFlightFences[windowData->frameCounter] != NULL) { + if (!VULKAN_WaitForFences( + driverData, + true, + &windowData->inFlightFences[windowData->frameCounter], + 1)) { + return false; + } + } + + return true; +} + +static bool VULKAN_INTERNAL_AcquireSwapchainTexture( + bool block, SDL_GPUCommandBuffer *commandBuffer, SDL_Window *window, SDL_GPUTexture **swapchainTexture, @@ -9708,8 +9733,8 @@ static bool VULKAN_AcquireSwapchainTexture( } 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 + if (block) { + // If we are blocking, just wait for the fence! if (!VULKAN_WaitForFences( (SDL_GPURenderer *)renderer, true, @@ -9718,13 +9743,11 @@ static bool VULKAN_AcquireSwapchainTexture( return false; } } else { + // If we are not blocking and the least recent fence is not signaled, + // return true to indicate that there is no error but rendering should be skipped. if (!VULKAN_QueryFence( (SDL_GPURenderer *)renderer, windowData->inFlightFences[windowData->frameCounter])) { - /* - * In MAILBOX or IMMEDIATE mode, if the least recent fence is not signaled, - * return true to indicate that there is no error but rendering should be skipped - */ return true; } } @@ -9843,6 +9866,38 @@ static bool VULKAN_AcquireSwapchainTexture( return true; } +static bool VULKAN_AcquireSwapchainTexture( + SDL_GPUCommandBuffer *command_buffer, + SDL_Window *window, + SDL_GPUTexture **swapchain_texture, + Uint32 *swapchain_texture_width, + Uint32 *swapchain_texture_height +) { + return VULKAN_INTERNAL_AcquireSwapchainTexture( + false, + command_buffer, + window, + swapchain_texture, + swapchain_texture_width, + swapchain_texture_height); +} + +static bool VULKAN_WaitAndAcquireSwapchainTexture( + SDL_GPUCommandBuffer *command_buffer, + SDL_Window *window, + SDL_GPUTexture **swapchain_texture, + Uint32 *swapchain_texture_width, + Uint32 *swapchain_texture_height +) { + return VULKAN_INTERNAL_AcquireSwapchainTexture( + true, + command_buffer, + window, + swapchain_texture, + swapchain_texture_width, + swapchain_texture_height); +} + static SDL_GPUTextureFormat VULKAN_GetSwapchainTextureFormat( SDL_GPURenderer *driverData, SDL_Window *window)