mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-05-23 21:19:11 +00:00
GPU: Revise swapchain acquisition (#11633)
--------- Co-authored-by: Lucas Murray <22484+lmurray@users.noreply.github.com>
This commit is contained in:
parent
bbd4eeb287
commit
3ee39f6c3f
9 changed files with 337 additions and 51 deletions
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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: *;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue