Skip to content

Commit

Permalink
Add SDL_WaitAndAcquireGPUSwapchainTexture and implement on Vulkan
Browse files Browse the repository at this point in the history
  • Loading branch information
thatcosmonaut committed Dec 11, 2024
1 parent 77c954e commit d863b36
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 53 deletions.
90 changes: 60 additions & 30 deletions include/SDL3/SDL_gpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -3547,20 +3547,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
Expand All @@ -3574,13 +3571,13 @@ extern SDL_DECLSPEC SDL_GPUTextureFormat SDLCALL SDL_GetGPUSwapchainTextureForma
*
* \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,
Expand All @@ -3589,6 +3586,58 @@ 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.
*
* \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.
*
* 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.
*
* \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.
*
Expand Down Expand Up @@ -3675,25 +3724,6 @@ extern SDL_DECLSPEC bool SDLCALL SDL_CancelGPUCommandBuffer(
extern SDL_DECLSPEC bool SDLCALL SDL_WaitForGPUIdle(
SDL_GPUDevice *device);

/**
* Blocks the thread until a swapchain texture is available to be acquired.
* Calling this function before SDL_AcquireGPUSwapchainTexture() will ensure
* that the acquire will immediately return a swapchain texture under most, but
* not all, conditions.
*
* \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.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_AcquireGPUSwapchainTexture
*/
extern SDL_DECLSPEC bool SDLCALL SDL_WaitForGPUSwapchain(
SDL_GPUDevice *device,
SDL_Window *window);

/**
* Blocks the thread until the given fences are signaled.
*
Expand Down
63 changes: 52 additions & 11 deletions src/gpu/SDL_gpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -2725,6 +2725,58 @@ bool SDL_AcquireGPUSwapchainTexture(
return result;
}

bool SDL_WaitForGPUSwapchain(
SDL_GPUDevice *device,
SDL_Window *window)
{
CHECK_DEVICE_MAGIC(device, false);

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) {
SDL_InvalidParamError("command_buffer");
return false;
}
if (window == NULL) {
SDL_InvalidParamError("window");
return false;
}
if (swapchain_texture == NULL) {
SDL_InvalidParamError("swapchain_texture");
return false;
}

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)
{
Expand Down Expand Up @@ -2809,17 +2861,6 @@ bool SDL_WaitForGPUIdle(
device->driverData);
}

bool SDL_WaitForGPUSwapchain(
SDL_GPUDevice *device,
SDL_Window *window)
{
CHECK_DEVICE_MAGIC(device, false);

return device->WaitForSwapchain(
device->driverData,
window);
}

bool SDL_WaitForGPUFences(
SDL_GPUDevice *device,
bool wait_all,
Expand Down
18 changes: 13 additions & 5 deletions src/gpu/SDL_sysgpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -823,10 +834,6 @@ struct SDL_GPUDevice
bool (*Wait)(
SDL_GPURenderer *driverData);

bool (*WaitForSwapchain)(
SDL_GPURenderer *driverData,
SDL_Window *window);

bool (*WaitForFences)(
SDL_GPURenderer *driverData,
bool waitAll,
Expand Down Expand Up @@ -941,11 +948,12 @@ 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) \
ASSIGN_DRIVER_FUNC(Wait, name) \
ASSIGN_DRIVER_FUNC(WaitForSwapchain, name) \
ASSIGN_DRIVER_FUNC(WaitForFences, name) \
ASSIGN_DRIVER_FUNC(QueryFence, name) \
ASSIGN_DRIVER_FUNC(ReleaseFence, name) \
Expand Down
45 changes: 38 additions & 7 deletions src/gpu/vulkan/SDL_gpu_vulkan.c
Original file line number Diff line number Diff line change
Expand Up @@ -9679,7 +9679,8 @@ static bool VULKAN_WaitForSwapchain(
return true;
}

static bool VULKAN_AcquireSwapchainTexture(
static bool VULKAN_INTERNAL_AcquireSwapchainTexture(
bool block,
SDL_GPUCommandBuffer *commandBuffer,
SDL_Window *window,
SDL_GPUTexture **swapchainTexture,
Expand Down Expand Up @@ -9732,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,
Expand All @@ -9742,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;
}
}
Expand Down Expand Up @@ -9867,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)
Expand Down

0 comments on commit d863b36

Please sign in to comment.