Browse Source

GPU: More robust error reporting (#10958)

---------

Co-authored-by: Ethan Lee <[email protected]>
Co-authored-by: Caleb Cornett <[email protected]>
Evan Hemsley 10 months ago
parent
commit
be401dd1e3

+ 33 - 30
include/SDL3/SDL_gpu.h

@@ -877,15 +877,15 @@ 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, AcquireSwapchainTexture will block if too many frames
+ *   this present mode, AcquireGPUSwapchainTexture will block if too many frames
  *   are in flight.
  * - IMMEDIATE: Immediately presents. Lowest latency option, but tearing may
- *   occur. When using this mode, AcquireSwapchainTexture will return NULL if
+ *   occur. When using this mode, AcquireGPUSwapchainTexture will return NULL if
  *   too many frames are in flight.
  * - 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, AcquireSwapchainTexture will return NULL if too many frames
+ *   this mode, AcquireGPUSwapchainTexture will return NULL if too many frames
  *   are in flight.
  *
  * \since This enum is available since SDL 3.0.0
@@ -1623,6 +1623,7 @@ typedef struct SDL_GPUBlitInfo {
     Uint8 padding2;
     Uint8 padding3;
 } SDL_GPUBlitInfo;
+
 /* Binding structs */
 
 /**
@@ -1731,7 +1732,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GPUSupportsProperties(
  * \param debug_mode enable debug mode properties and validations.
  * \param name the preferred GPU driver, or NULL to let SDL pick the optimal
  *             driver.
- * \returns a GPU context on success or NULL on failure.
+ * \returns a GPU context on success or NULL on failure; call SDL_GetError() for more information.
  *
  * \since This function is available since SDL 3.0.0.
  *
@@ -1778,7 +1779,7 @@ extern SDL_DECLSPEC SDL_GPUDevice *SDLCALL SDL_CreateGPUDevice(
  *   use for all vertex semantics, default is "TEXCOORD".
  *
  * \param props the properties to use.
- * \returns a GPU context on success or NULL on failure.
+ * \returns a GPU context on success or NULL on failure; call SDL_GetError() for more information.
  *
  * \since This function is available since SDL 3.0.0.
  *
@@ -1904,7 +1905,7 @@ extern SDL_DECLSPEC SDL_GPUShaderFormat SDLCALL SDL_GetGPUShaderFormats(SDL_GPUD
  * \param device a GPU Context.
  * \param createinfo a struct describing the state of the compute pipeline to
  *                   create.
- * \returns a compute pipeline object on success, or NULL on failure.
+ * \returns a compute pipeline object on success, or NULL on failure; call SDL_GetError() for more information.
  *
  * \since This function is available since SDL 3.0.0.
  *
@@ -1921,7 +1922,7 @@ extern SDL_DECLSPEC SDL_GPUComputePipeline *SDLCALL SDL_CreateGPUComputePipeline
  * \param device a GPU Context.
  * \param createinfo a struct describing the state of the graphics pipeline to
  *                   create.
- * \returns a graphics pipeline object on success, or NULL on failure.
+ * \returns a graphics pipeline object on success, or NULL on failure; call SDL_GetError() for more information.
  *
  * \since This function is available since SDL 3.0.0.
  *
@@ -1939,7 +1940,7 @@ extern SDL_DECLSPEC SDL_GPUGraphicsPipeline *SDLCALL SDL_CreateGPUGraphicsPipeli
  *
  * \param device a GPU Context.
  * \param createinfo a struct describing the state of the sampler to create.
- * \returns a sampler object on success, or NULL on failure.
+ * \returns a sampler object on success, or NULL on failure; call SDL_GetError() for more information.
  *
  * \since This function is available since SDL 3.0.0.
  *
@@ -2008,7 +2009,7 @@ extern SDL_DECLSPEC SDL_GPUSampler *SDLCALL SDL_CreateGPUSampler(
  *
  * \param device a GPU Context.
  * \param createinfo a struct describing the state of the shader to create.
- * \returns a shader object on success, or NULL on failure.
+ * \returns a shader object on success, or NULL on failure; call SDL_GetError() for more information.
  *
  * \since This function is available since SDL 3.0.0.
  *
@@ -2034,7 +2035,7 @@ extern SDL_DECLSPEC SDL_GPUShader *SDLCALL SDL_CreateGPUShader(
  *
  * \param device a GPU Context.
  * \param createinfo a struct describing the state of the texture to create.
- * \returns a texture object on success, or NULL on failure.
+ * \returns a texture object on success, or NULL on failure; call SDL_GetError() for more information.
  *
  * \since This function is available since SDL 3.0.0.
  *
@@ -2064,7 +2065,7 @@ extern SDL_DECLSPEC SDL_GPUTexture *SDLCALL SDL_CreateGPUTexture(
  *
  * \param device a GPU Context.
  * \param createinfo a struct describing the state of the buffer to create.
- * \returns a buffer object on success, or NULL on failure.
+ * \returns a buffer object on success, or NULL on failure; call SDL_GetError() for more information.
  *
  * \since This function is available since SDL 3.0.0.
  *
@@ -2093,7 +2094,7 @@ extern SDL_DECLSPEC SDL_GPUBuffer *SDLCALL SDL_CreateGPUBuffer(
  * \param device a GPU Context.
  * \param createinfo a struct describing the state of the transfer buffer to
  *                   create.
- * \returns a transfer buffer on success, or NULL on failure.
+ * \returns a transfer buffer on success, or NULL on failure; call SDL_GetError() for more information.
  *
  * \since This function is available since SDL 3.0.0.
  *
@@ -2301,7 +2302,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_ReleaseGPUGraphicsPipeline(
  * acquired on.
  *
  * \param device a GPU context.
- * \returns a command buffer.
+ * \returns a command buffer, or NULL on failure; call SDL_GetError() for more information.
  *
  * \since This function is available since SDL 3.0.0.
  *
@@ -2967,7 +2968,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_EndGPUComputePass(
  * \param device a GPU context.
  * \param transfer_buffer a transfer buffer.
  * \param cycle if true, cycles the transfer buffer if it is already bound.
- * \returns the address of the mapped transfer buffer memory.
+ * \returns the address of the mapped transfer buffer memory, or NULL on failure; call SDL_GetError() for more information.
  *
  * \since This function is available since SDL 3.0.0.
  */
@@ -3183,7 +3184,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_BlitGPUTexture(
  * \param device a GPU context.
  * \param window an SDL_Window.
  * \param swapchain_composition the swapchain composition to check.
- * \returns true if supported, false if unsupported (or on error).
+ * \returns true if supported, false if unsupported.
  *
  * \since This function is available since SDL 3.0.0.
  *
@@ -3202,7 +3203,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_WindowSupportsGPUSwapchainComposition(
  * \param device a GPU context.
  * \param window an SDL_Window.
  * \param present_mode the presentation mode to check.
- * \returns true if supported, false if unsupported (or on error).
+ * \returns true if supported, false if unsupported.
  *
  * \since This function is available since SDL 3.0.0.
  *
@@ -3226,7 +3227,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_WindowSupportsGPUPresentMode(
  *
  * \param device a GPU context.
  * \param window an SDL_Window.
- * \returns true on success, otherwise false.
+ * \returns true on success, or false on failure; call SDL_GetError() for more information.
  *
  * \since This function is available since SDL 3.0.0.
  *
@@ -3283,6 +3284,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetGPUSwapchainParameters(
 
 /**
  * Obtains the texture format of the swapchain for the given window.
+ * Note that this format can change if the swapchain parameters change.
  *
  * \param device a GPU context.
  * \param window an SDL_Window that has been claimed.
@@ -3300,16 +3302,15 @@ 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. May return NULL under certain conditions. This
- * is not necessarily an error. This texture is managed by the implementation
- * and must not be freed by the user. You MUST NOT call this function from any
+ * buffer used to acquire it. The swapchain texture handle can be NULL under certain conditions. This
+ * is not necessarily an error. If this function returns false then there is an error. This texture is managed by the implementation
+ * and must not be freed by the user. The texture dimensions will be the height and width of the claimed window. 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 w a pointer filled in with the swapchain width.
- * \param h a pointer filled in with the swapchain height.
- * \returns a swapchain texture.
+ * \param swapchainTexture a pointer filled in with a swapchain texture handle
+ * \returns true on success, false on error.
  *
  * \since This function is available since SDL 3.0.0.
  *
@@ -3317,11 +3318,10 @@ extern SDL_DECLSPEC SDL_GPUTextureFormat SDLCALL SDL_GetGPUSwapchainTextureForma
  * \sa SDL_SubmitGPUCommandBuffer
  * \sa SDL_SubmitGPUCommandBufferAndAcquireFence
  */
-extern SDL_DECLSPEC SDL_GPUTexture *SDLCALL SDL_AcquireGPUSwapchainTexture(
+extern SDL_DECLSPEC bool SDLCALL SDL_AcquireGPUSwapchainTexture(
     SDL_GPUCommandBuffer *command_buffer,
     SDL_Window *window,
-    Uint32 *w,
-    Uint32 *h);
+    SDL_GPUTexture **swapchainTexture);
 
 /**
  * Submits a command buffer so its commands can be processed on the GPU.
@@ -3334,6 +3334,7 @@ extern SDL_DECLSPEC SDL_GPUTexture *SDLCALL SDL_AcquireGPUSwapchainTexture(
  * command in a subsequent submission begins executing.
  *
  * \param command_buffer a command buffer.
+ * \returns true on success, false on failure; call SDL_GetError() for more information.
  *
  * \since This function is available since SDL 3.0.0.
  *
@@ -3341,7 +3342,7 @@ extern SDL_DECLSPEC SDL_GPUTexture *SDLCALL SDL_AcquireGPUSwapchainTexture(
  * \sa SDL_AcquireGPUSwapchainTexture
  * \sa SDL_SubmitGPUCommandBufferAndAcquireFence
  */
-extern SDL_DECLSPEC void SDLCALL SDL_SubmitGPUCommandBuffer(
+extern SDL_DECLSPEC bool SDLCALL SDL_SubmitGPUCommandBuffer(
     SDL_GPUCommandBuffer *command_buffer);
 
 /**
@@ -3357,7 +3358,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_SubmitGPUCommandBuffer(
  * command in a subsequent submission begins executing.
  *
  * \param command_buffer a command buffer.
- * \returns a fence associated with the command buffer.
+ * \returns a fence associated with the command buffer, or NULL on failure; call SDL_GetError() for more information.
  *
  * \since This function is available since SDL 3.0.0.
  *
@@ -3373,12 +3374,13 @@ extern SDL_DECLSPEC SDL_GPUFence *SDLCALL SDL_SubmitGPUCommandBufferAndAcquireFe
  * Blocks the thread until the GPU is completely idle.
  *
  * \param device a GPU context.
+ * \returns true on success, false on failure; call SDL_GetError() for more information.
  *
  * \since This function is available since SDL 3.0.0.
  *
  * \sa SDL_WaitForGPUFences
  */
-extern SDL_DECLSPEC void SDLCALL SDL_WaitForGPUIdle(
+extern SDL_DECLSPEC bool SDLCALL SDL_WaitForGPUIdle(
     SDL_GPUDevice *device);
 
 /**
@@ -3389,13 +3391,14 @@ extern SDL_DECLSPEC void SDLCALL SDL_WaitForGPUIdle(
  *                 fences to be signaled.
  * \param fences an array of fences to wait on.
  * \param num_fences the number of fences in the fences array.
+ * \returns true on success, false on failure; call SDL_GetError() for more information.
  *
  * \since This function is available since SDL 3.0.0.
  *
  * \sa SDL_SubmitGPUCommandBufferAndAcquireFence
  * \sa SDL_WaitForGPUIdle
  */
-extern SDL_DECLSPEC void SDLCALL SDL_WaitForGPUFences(
+extern SDL_DECLSPEC bool SDLCALL SDL_WaitForGPUFences(
     SDL_GPUDevice *device,
     bool wait_all,
     SDL_GPUFence *const *fences,

+ 4 - 4
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(SDL_GPUTexture*,SDL_AcquireGPUSwapchainTexture,(SDL_GPUCommandBuffer *a, SDL_Window *b, Uint32 *c, Uint32 *d),(a,b,c,d),return)
+SDL_DYNAPI_PROC(bool,SDL_AcquireGPUSwapchainTexture,(SDL_GPUCommandBuffer *a, SDL_Window *b, SDL_GPUTexture **c),(a,b,c),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)
@@ -953,7 +953,7 @@ SDL_DYNAPI_PROC(bool,SDL_StopHapticRumble,(SDL_Haptic *a),(a),return)
 SDL_DYNAPI_PROC(bool,SDL_StopTextInput,(SDL_Window *a),(a),return)
 SDL_DYNAPI_PROC(bool,SDL_StorageReady,(SDL_Storage *a),(a),return)
 SDL_DYNAPI_PROC(SDL_GUID,SDL_StringToGUID,(const char *a),(a),return)
-SDL_DYNAPI_PROC(void,SDL_SubmitGPUCommandBuffer,(SDL_GPUCommandBuffer *a),(a),)
+SDL_DYNAPI_PROC(bool,SDL_SubmitGPUCommandBuffer,(SDL_GPUCommandBuffer *a),(a),return)
 SDL_DYNAPI_PROC(SDL_GPUFence*,SDL_SubmitGPUCommandBufferAndAcquireFence,(SDL_GPUCommandBuffer *a),(a),return)
 SDL_DYNAPI_PROC(bool,SDL_SurfaceHasAlternateImages,(SDL_Surface *a),(a),return)
 SDL_DYNAPI_PROC(bool,SDL_SurfaceHasColorKey,(SDL_Surface *a),(a),return)
@@ -1006,8 +1006,8 @@ SDL_DYNAPI_PROC(void,SDL_WaitCondition,(SDL_Condition *a, SDL_Mutex *b),(a,b),)
 SDL_DYNAPI_PROC(bool,SDL_WaitConditionTimeout,(SDL_Condition *a, SDL_Mutex *b, Sint32 c),(a,b,c),return)
 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(void,SDL_WaitForGPUFences,(SDL_GPUDevice *a, bool b, SDL_GPUFence *const *c, Uint32 d),(a,b,c,d),)
-SDL_DYNAPI_PROC(void,SDL_WaitForGPUIdle,(SDL_GPUDevice *a),(a),)
+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_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)

+ 34 - 34
src/gpu/SDL_gpu.c

@@ -28,16 +28,22 @@
         return retval;                      \
     }
 
-#define CHECK_COMMAND_BUFFER                                       \
+#define CHECK_COMMAND_BUFFER                                        \
     if (((CommandBufferCommonHeader *)command_buffer)->submitted) { \
-        SDL_assert_release(!"Command buffer already submitted!");  \
-        return;                                                    \
+        SDL_assert_release(!"Command buffer already submitted!");   \
+        return;                                                     \
     }
 
-#define CHECK_COMMAND_BUFFER_RETURN_NULL                           \
+#define CHECK_COMMAND_BUFFER_RETURN_FALSE                           \
     if (((CommandBufferCommonHeader *)command_buffer)->submitted) { \
-        SDL_assert_release(!"Command buffer already submitted!");  \
-        return NULL;                                               \
+        SDL_assert_release(!"Command buffer already submitted!");   \
+        return false;                                               \
+    }
+
+#define CHECK_COMMAND_BUFFER_RETURN_NULL                            \
+    if (((CommandBufferCommonHeader *)command_buffer)->submitted) { \
+        SDL_assert_release(!"Command buffer already submitted!");   \
+        return NULL;                                                \
     }
 
 #define CHECK_ANY_PASS_IN_PROGRESS(msg, retval)                                 \
@@ -2594,65 +2600,59 @@ SDL_GPUTextureFormat SDL_GetGPUSwapchainTextureFormat(
         window);
 }
 
-SDL_GPUTexture *SDL_AcquireGPUSwapchainTexture(
+bool SDL_AcquireGPUSwapchainTexture(
     SDL_GPUCommandBuffer *command_buffer,
     SDL_Window *window,
-    Uint32 *w,
-    Uint32 *h)
+    SDL_GPUTexture **swapchainTexture)
 {
     if (command_buffer == NULL) {
         SDL_InvalidParamError("command_buffer");
-        return NULL;
+        return false;
     }
     if (window == NULL) {
         SDL_InvalidParamError("window");
-        return NULL;
-    }
-    if (w == NULL) {
-        SDL_InvalidParamError("w");
-        return NULL;
+        return false;
     }
-    if (h == NULL) {
-        SDL_InvalidParamError("h");
-        return NULL;
+    if (swapchainTexture == NULL) {
+        SDL_InvalidParamError("swapchainTexture");
+        return false;
     }
 
     if (COMMAND_BUFFER_DEVICE->debug_mode) {
-        CHECK_COMMAND_BUFFER_RETURN_NULL
-        CHECK_ANY_PASS_IN_PROGRESS("Cannot acquire a swapchain texture during a pass!", NULL)
+        CHECK_COMMAND_BUFFER_RETURN_FALSE
+        CHECK_ANY_PASS_IN_PROGRESS("Cannot acquire a swapchain texture during a pass!", false)
     }
 
     return COMMAND_BUFFER_DEVICE->AcquireSwapchainTexture(
         command_buffer,
         window,
-        w,
-        h);
+        swapchainTexture);
 }
 
-void SDL_SubmitGPUCommandBuffer(
+bool SDL_SubmitGPUCommandBuffer(
     SDL_GPUCommandBuffer *command_buffer)
 {
     CommandBufferCommonHeader *commandBufferHeader = (CommandBufferCommonHeader *)command_buffer;
 
     if (command_buffer == NULL) {
         SDL_InvalidParamError("command_buffer");
-        return;
+        return false;
     }
 
     if (COMMAND_BUFFER_DEVICE->debug_mode) {
-        CHECK_COMMAND_BUFFER
+        CHECK_COMMAND_BUFFER_RETURN_FALSE
         if (
             commandBufferHeader->render_pass.in_progress ||
             commandBufferHeader->compute_pass.in_progress ||
             commandBufferHeader->copy_pass.in_progress) {
             SDL_assert_release(!"Cannot submit command buffer while a pass is in progress!");
-            return;
+            return false;
         }
     }
 
     commandBufferHeader->submitted = true;
 
-    COMMAND_BUFFER_DEVICE->Submit(
+    return COMMAND_BUFFER_DEVICE->Submit(
         command_buffer);
 }
 
@@ -2683,28 +2683,28 @@ SDL_GPUFence *SDL_SubmitGPUCommandBufferAndAcquireFence(
         command_buffer);
 }
 
-void SDL_WaitForGPUIdle(
+bool SDL_WaitForGPUIdle(
     SDL_GPUDevice *device)
 {
-    CHECK_DEVICE_MAGIC(device, );
+    CHECK_DEVICE_MAGIC(device, false);
 
-    device->Wait(
+    return device->Wait(
         device->driverData);
 }
 
-void SDL_WaitForGPUFences(
+bool SDL_WaitForGPUFences(
     SDL_GPUDevice *device,
     bool wait_all,
     SDL_GPUFence *const *fences,
     Uint32 num_fences)
 {
-    CHECK_DEVICE_MAGIC(device, );
+    CHECK_DEVICE_MAGIC(device, false);
     if (fences == NULL && num_fences > 0) {
         SDL_InvalidParamError("fences");
-        return;
+        return false;
     }
 
-    device->WaitForFences(
+    return device->WaitForFences(
         device->driverData,
         wait_all,
         fences,

+ 5 - 6
src/gpu/SDL_sysgpu.h

@@ -648,22 +648,21 @@ struct SDL_GPUDevice
     SDL_GPUCommandBuffer *(*AcquireCommandBuffer)(
         SDL_GPURenderer *driverData);
 
-    SDL_GPUTexture *(*AcquireSwapchainTexture)(
+    bool (*AcquireSwapchainTexture)(
         SDL_GPUCommandBuffer *commandBuffer,
         SDL_Window *window,
-        Uint32 *w,
-        Uint32 *h);
+        SDL_GPUTexture **swapchainTexture);
 
-    void (*Submit)(
+    bool (*Submit)(
         SDL_GPUCommandBuffer *commandBuffer);
 
     SDL_GPUFence *(*SubmitAndAcquireFence)(
         SDL_GPUCommandBuffer *commandBuffer);
 
-    void (*Wait)(
+    bool (*Wait)(
         SDL_GPURenderer *driverData);
 
-    void (*WaitForFences)(
+    bool (*WaitForFences)(
         SDL_GPURenderer *driverData,
         bool waitAll,
         SDL_GPUFence *const *fences,

+ 138 - 171
src/gpu/d3d11/SDL_gpu_d3d11.c

@@ -108,20 +108,18 @@ static const GUID D3D_IID_DXGI_DEBUG_ALL = { 0xe48ae283, 0xda80, 0x490b, { 0x87,
 
 // Macros
 
-#define ERROR_LOG(msg)                                       \
-    if (FAILED(res)) {                                       \
-        D3D11_INTERNAL_LogError(renderer->device, msg, res); \
-    }
+#define SET_ERROR_AND_RETURN(fmt, msg, ret)           \
+    if (renderer->debugMode) {                        \
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, fmt, msg); \
+    }                                                 \
+    SDL_SetError(fmt, msg);                           \
+    return ret;                                       \
 
-#define ERROR_LOG_RETURN(msg, ret)                           \
-    if (FAILED(res)) {                                       \
-        D3D11_INTERNAL_LogError(renderer->device, msg, res); \
-        return ret;                                          \
-    }
+#define SET_STRING_ERROR_AND_RETURN(msg, ret) SET_ERROR_AND_RETURN("%s", msg, ret)
 
-#define ERROR_SET_RETURN(msg, ret)                           \
+#define CHECK_D3D11_ERROR_AND_RETURN(msg, ret)               \
     if (FAILED(res)) {                                       \
-        D3D11_INTERNAL_SetError(renderer->device, msg, res); \
+        D3D11_INTERNAL_SetError(renderer, msg, res);         \
         return ret;                                          \
     }
 
@@ -146,7 +144,7 @@ static const GUID D3D_IID_DXGI_DEBUG_ALL = { 0xe48ae283, 0xda80, 0x490b, { 0x87,
 
 // Forward Declarations
 
-static void D3D11_Wait(SDL_GPURenderer *driverData);
+static bool D3D11_Wait(SDL_GPURenderer *driverData);
 static void D3D11_ReleaseWindow(
     SDL_GPURenderer *driverData,
     SDL_Window *window);
@@ -800,7 +798,7 @@ struct D3D11Renderer
 // Logging
 
 static void D3D11_INTERNAL_SetError(
-    ID3D11Device1 *device,
+    D3D11Renderer *renderer,
     const char *msg,
     HRESULT res)
 {
@@ -811,7 +809,7 @@ static void D3D11_INTERNAL_SetError(
     DWORD dwChars; // Number of chars returned.
 
     if (res == DXGI_ERROR_DEVICE_REMOVED) {
-        res = ID3D11Device_GetDeviceRemovedReason(device);
+        res = ID3D11Device_GetDeviceRemovedReason(renderer->device);
     }
 
     // Try to get the message from the system errors.
@@ -831,6 +829,9 @@ static void D3D11_INTERNAL_SetError(
 
     // No message? Screw it, just post the code.
     if (dwChars == 0) {
+        if (renderer->debugMode) {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s! Error Code: " HRESULT_FMT, msg, res);
+        }
         SDL_SetError("%s! Error Code: " HRESULT_FMT, msg, res);
         return;
     }
@@ -850,61 +851,10 @@ static void D3D11_INTERNAL_SetError(
     // Ensure null-terminated string
     wszMsgBuff[dwChars] = '\0';
 
-    SDL_SetError("%s! Error Code: %s " HRESULT_FMT, msg, wszMsgBuff, res);
-}
-
-static void D3D11_INTERNAL_LogError(
-    ID3D11Device1 *device,
-    const char *msg,
-    HRESULT res)
-{
-#define MAX_ERROR_LEN 1024 // FIXME: Arbitrary!
-
-    // Buffer for text, ensure space for \0 terminator after buffer
-    char wszMsgBuff[MAX_ERROR_LEN + 1];
-    DWORD dwChars; // Number of chars returned.
-
-    if (res == DXGI_ERROR_DEVICE_REMOVED) {
-        res = ID3D11Device_GetDeviceRemovedReason(device);
-    }
-
-    // Try to get the message from the system errors.
-#ifdef _WIN32
-    dwChars = FormatMessageA(
-        FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
-        NULL,
-        res,
-        0,
-        wszMsgBuff,
-        MAX_ERROR_LEN,
-        NULL);
-#else
-    // FIXME: Do we have error strings in dxvk-native? -flibit
-    dwChars = 0;
-#endif
-
-    // No message? Screw it, just post the code.
-    if (dwChars == 0) {
-        SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s! Error Code: " HRESULT_FMT, msg, res);
-        return;
-    }
-
-    // Ensure valid range
-    dwChars = SDL_min(dwChars, MAX_ERROR_LEN);
-
-    // Trim whitespace from tail of message
-    while (dwChars > 0) {
-        if (wszMsgBuff[dwChars - 1] <= ' ') {
-            dwChars--;
-        } else {
-            break;
-        }
+    if (renderer->debugMode) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s! Error Code: %s " HRESULT_FMT, msg, wszMsgBuff, res);
     }
-
-    // Ensure null-terminated string
-    wszMsgBuff[dwChars] = '\0';
-
-    SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s! Error Code: %s " HRESULT_FMT, msg, wszMsgBuff, res);
+    SDL_SetError("%s! Error Code: %s " HRESULT_FMT, msg, wszMsgBuff, res);
 }
 
 // Helper Functions
@@ -1348,7 +1298,7 @@ static ID3D11BlendState *D3D11_INTERNAL_FetchBlendState(
         renderer->device,
         &blendDesc,
         &result);
-    ERROR_LOG_RETURN("Could not create blend state", NULL);
+    CHECK_D3D11_ERROR_AND_RETURN("Could not create blend state", NULL);
 
     return result;
 }
@@ -1386,7 +1336,7 @@ static ID3D11DepthStencilState *D3D11_INTERNAL_FetchDepthStencilState(
         renderer->device,
         &dsDesc,
         &result);
-    ERROR_LOG_RETURN("Could not create depth-stencil state", NULL);
+    CHECK_D3D11_ERROR_AND_RETURN("Could not create depth-stencil state", NULL);
 
     return result;
 }
@@ -1417,7 +1367,7 @@ static ID3D11RasterizerState *D3D11_INTERNAL_FetchRasterizerState(
         renderer->device,
         &rasterizerDesc,
         &result);
-    ERROR_LOG_RETURN("Could not create rasterizer state", NULL);
+    CHECK_D3D11_ERROR_AND_RETURN("Could not create rasterizer state", NULL);
 
     return result;
 }
@@ -1486,8 +1436,8 @@ static ID3D11InputLayout *D3D11_INTERNAL_FetchInputLayout(
         shaderByteLength,
         &result);
     if (FAILED(res)) {
-        SDL_SetError("Could not create input layout! Error: " HRESULT_FMT, res);
         SDL_stack_free(elementDescs);
+        CHECK_D3D11_ERROR_AND_RETURN("Could not create input layout!", NULL)
         return NULL;
     }
 
@@ -1522,10 +1472,7 @@ static ID3D11DeviceChild *D3D11_INTERNAL_CreateID3D11Shader(
             codeSize,
             NULL,
             (ID3D11VertexShader **)&handle);
-        if (FAILED(res)) {
-            D3D11_INTERNAL_LogError(renderer->device, "Could not create vertex shader", res);
-            return NULL;
-        }
+        CHECK_D3D11_ERROR_AND_RETURN("Could not create vertex shader", NULL)
     } else if (stage == SDL_GPU_SHADERSTAGE_FRAGMENT) {
         res = ID3D11Device_CreatePixelShader(
             renderer->device,
@@ -1533,10 +1480,7 @@ static ID3D11DeviceChild *D3D11_INTERNAL_CreateID3D11Shader(
             codeSize,
             NULL,
             (ID3D11PixelShader **)&handle);
-        if (FAILED(res)) {
-            D3D11_INTERNAL_LogError(renderer->device, "Could not create pixel shader", res);
-            return NULL;
-        }
+        CHECK_D3D11_ERROR_AND_RETURN("Could not create pixel shader", NULL)
     } else if (stage == SDL_GPU_SHADERSTAGE_COMPUTE) {
         res = ID3D11Device_CreateComputeShader(
             renderer->device,
@@ -1544,10 +1488,7 @@ static ID3D11DeviceChild *D3D11_INTERNAL_CreateID3D11Shader(
             codeSize,
             NULL,
             (ID3D11ComputeShader **)&handle);
-        if (FAILED(res)) {
-            D3D11_INTERNAL_LogError(renderer->device, "Could not create compute shader", res);
-            return NULL;
-        }
+        CHECK_D3D11_ERROR_AND_RETURN("Could not create compute shader", NULL)
     }
 
     if (pBytecode != NULL) {
@@ -1576,7 +1517,6 @@ static SDL_GPUComputePipeline *D3D11_CreateComputePipeline(
         NULL,
         NULL);
     if (shader == NULL) {
-        SDL_SetError("Failed to create compute pipeline!");
         return NULL;
     }
 
@@ -1609,6 +1549,10 @@ static SDL_GPUGraphicsPipeline *D3D11_CreateGraphicsPipeline(
         createinfo->target_info.num_color_targets,
         createinfo->target_info.color_target_descriptions);
 
+    if (pipeline->colorTargetBlendState == NULL) {
+        return NULL;
+    }
+
     pipeline->numColorTargets = createinfo->target_info.num_color_targets;
     for (Sint32 i = 0; i < pipeline->numColorTargets; i += 1) {
         pipeline->colorTargetFormats[i] = SDLToD3D11_TextureFormat[createinfo->target_info.color_target_descriptions[i].format];
@@ -1627,6 +1571,10 @@ static SDL_GPUGraphicsPipeline *D3D11_CreateGraphicsPipeline(
         renderer,
         createinfo->depth_stencil_state);
 
+    if (pipeline->depthStencilState == NULL) {
+        return NULL;
+    }
+
     pipeline->hasDepthStencilTarget = createinfo->target_info.has_depth_stencil_target;
     pipeline->depthStencilTargetFormat = SDLToD3D11_TextureFormat[createinfo->target_info.depth_stencil_format];
 
@@ -1637,6 +1585,10 @@ static SDL_GPUGraphicsPipeline *D3D11_CreateGraphicsPipeline(
         renderer,
         createinfo->rasterizer_state);
 
+    if (pipeline->rasterizerState == NULL) {
+        return NULL;
+    }
+
     // Shaders
 
     pipeline->vertexShader = (ID3D11VertexShader *)vertShader->handle;
@@ -1875,7 +1827,7 @@ static SDL_GPUSampler *D3D11_CreateSampler(
         renderer->device,
         &samplerDesc,
         &samplerStateHandle);
-    ERROR_SET_RETURN("Could not create sampler state", NULL);
+    CHECK_D3D11_ERROR_AND_RETURN("Could not create sampler state", NULL);
 
     d3d11Sampler = (D3D11Sampler *)SDL_malloc(sizeof(D3D11Sampler));
     d3d11Sampler->handle = samplerStateHandle;
@@ -1901,7 +1853,7 @@ SDL_GPUShader *D3D11_CreateShader(
         createinfo->entrypoint,
         createinfo->stage == SDL_GPU_SHADERSTAGE_VERTEX ? &bytecode : NULL,
         createinfo->stage == SDL_GPU_SHADERSTAGE_VERTEX ? &bytecodeSize : NULL);
-    if (!handle) {
+    if (handle == NULL) {
         return NULL;
     }
 
@@ -1994,7 +1946,7 @@ static D3D11Texture *D3D11_INTERNAL_CreateTexture(
             &desc2D,
             initialData,
             (ID3D11Texture2D **)&textureHandle);
-        ERROR_LOG_RETURN("Could not create Texture2D", NULL);
+        CHECK_D3D11_ERROR_AND_RETURN("Could not create Texture2D", NULL);
 
         // Create the SRV, if applicable
         if (needsSRV) {
@@ -2030,7 +1982,7 @@ static D3D11Texture *D3D11_INTERNAL_CreateTexture(
                 &srv);
             if (FAILED(res)) {
                 ID3D11Resource_Release(textureHandle);
-                D3D11_INTERNAL_LogError(renderer->device, "Could not create SRV for 2D texture", res);
+                D3D11_INTERNAL_SetError(renderer, "Could not create SRV for 2D texture", res);
                 return NULL;
             }
         }
@@ -2062,7 +2014,7 @@ static D3D11Texture *D3D11_INTERNAL_CreateTexture(
             &desc3D,
             initialData,
             (ID3D11Texture3D **)&textureHandle);
-        ERROR_LOG_RETURN("Could not create Texture3D", NULL);
+        CHECK_D3D11_ERROR_AND_RETURN("Could not create Texture3D", NULL);
 
         // Create the SRV, if applicable
         if (needsSRV) {
@@ -2079,7 +2031,7 @@ static D3D11Texture *D3D11_INTERNAL_CreateTexture(
                 &srv);
             if (FAILED(res)) {
                 ID3D11Resource_Release(textureHandle);
-                D3D11_INTERNAL_LogError(renderer->device, "Could not create SRV for 3D texture", res);
+                D3D11_INTERNAL_SetError(renderer, "Could not create SRV for 3D texture", res);
                 return NULL;
             }
         }
@@ -2131,7 +2083,7 @@ static D3D11Texture *D3D11_INTERNAL_CreateTexture(
                     d3d11Texture->handle,
                     &dsvDesc,
                     &d3d11Texture->subresources[subresourceIndex].depthStencilTargetView);
-                ERROR_LOG_RETURN("Could not create DSV!", NULL);
+                CHECK_D3D11_ERROR_AND_RETURN("Could not create DSV!", NULL);
 
             } else if (isColorTarget) {
 
@@ -2163,7 +2115,7 @@ static D3D11Texture *D3D11_INTERNAL_CreateTexture(
                         d3d11Texture->handle,
                         &rtvDesc,
                         &d3d11Texture->subresources[subresourceIndex].colorTargetViews[depthIndex]);
-                    ERROR_LOG_RETURN("Could not create RTV!", NULL);
+                    CHECK_D3D11_ERROR_AND_RETURN("Could not create RTV!", NULL);
                 }
             }
 
@@ -2191,7 +2143,7 @@ static D3D11Texture *D3D11_INTERNAL_CreateTexture(
                     d3d11Texture->handle,
                     &uavDesc,
                     &d3d11Texture->subresources[subresourceIndex].uav);
-                ERROR_LOG_RETURN("Could not create UAV!", NULL);
+                CHECK_D3D11_ERROR_AND_RETURN("Could not create UAV!", NULL);
             }
         }
     }
@@ -2230,7 +2182,6 @@ static SDL_GPUTexture *D3D11_CreateTexture(
         NULL);
 
     if (texture == NULL) {
-        SDL_SetError("Failed to create texture!");
         return NULL;
     }
 
@@ -2267,7 +2218,6 @@ static void D3D11_INTERNAL_CycleActiveTexture(
         &container->header.info,
         NULL);
     if (texture == NULL) {
-        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to cycle active texture!");
         return;
     }
 
@@ -2355,7 +2305,7 @@ static D3D11Buffer *D3D11_INTERNAL_CreateBuffer(
         bufferDesc,
         NULL,
         &bufferHandle);
-    ERROR_LOG_RETURN("Could not create buffer", NULL);
+    CHECK_D3D11_ERROR_AND_RETURN("Could not create buffer", NULL);
 
     // Storage buffer
     if (bufferDesc->MiscFlags & D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS) {
@@ -2375,7 +2325,7 @@ static D3D11Buffer *D3D11_INTERNAL_CreateBuffer(
             &uav);
         if (FAILED(res)) {
             ID3D11Buffer_Release(bufferHandle);
-            ERROR_LOG_RETURN("Could not create UAV for buffer!", NULL);
+            CHECK_D3D11_ERROR_AND_RETURN("Could not create UAV for buffer!", NULL);
         }
 
         // Create a SRV for the buffer
@@ -2394,7 +2344,7 @@ static D3D11Buffer *D3D11_INTERNAL_CreateBuffer(
             &srv);
         if (FAILED(res)) {
             ID3D11Buffer_Release(bufferHandle);
-            ERROR_LOG_RETURN("Could not create SRV for buffer!", NULL);
+            CHECK_D3D11_ERROR_AND_RETURN("Could not create SRV for buffer!", NULL);
         }
     }
 
@@ -2456,7 +2406,6 @@ static SDL_GPUBuffer *D3D11_CreateBuffer(
         size);
 
     if (buffer == NULL) {
-        SDL_SetError("Failed to create buffer!");
         return NULL;
     }
 
@@ -2494,7 +2443,7 @@ static D3D11UniformBuffer *D3D11_INTERNAL_CreateUniformBuffer(
         &bufferDesc,
         NULL,
         &buffer);
-    ERROR_LOG_RETURN("Could not create uniform buffer", NULL)
+    CHECK_D3D11_ERROR_AND_RETURN("Could not create uniform buffer", NULL)
 
     uniformBuffer = SDL_malloc(sizeof(D3D11UniformBuffer));
     uniformBuffer->buffer = buffer;
@@ -2738,7 +2687,6 @@ static void D3D11_UploadToTexture(
         &initialData);
 
     if (stagingTexture == NULL) {
-        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Staging texture creation failed");
         return;
     }
 
@@ -2797,7 +2745,7 @@ static void D3D11_UploadToBuffer(
         &stagingBufferDesc,
         &stagingBufferData,
         &stagingBuffer);
-    ERROR_LOG_RETURN("Could not create staging buffer", )
+    CHECK_D3D11_ERROR_AND_RETURN("Could not create staging buffer", )
 
     // Copy from staging buffer to buffer
     ID3D11DeviceContext1_CopySubresourceRegion(
@@ -2880,7 +2828,7 @@ static void D3D11_DownloadFromTexture(
             &stagingDesc2D,
             NULL,
             (ID3D11Texture2D **)&textureDownload->stagingTexture);
-        ERROR_LOG_RETURN("Staging texture creation failed", )
+        CHECK_D3D11_ERROR_AND_RETURN("Staging texture creation failed", )
     } else {
         stagingDesc3D.Width = source->w;
         stagingDesc3D.Height = source->h;
@@ -2959,7 +2907,7 @@ static void D3D11_DownloadFromBuffer(
         &stagingBufferDesc,
         NULL,
         &bufferDownload->stagingBuffer);
-    ERROR_LOG_RETURN("Could not create staging buffer", )
+    CHECK_D3D11_ERROR_AND_RETURN("Could not create staging buffer", )
 
     ID3D11DeviceContext1_CopySubresourceRegion1(
         d3d11CommandBuffer->context,
@@ -3103,7 +3051,7 @@ static void D3D11_INTERNAL_AllocateCommandBuffers(
             renderer->device,
             0,
             &commandBuffer->context);
-        ERROR_LOG("Could not create deferred context");
+        CHECK_D3D11_ERROR_AND_RETURN("Could not create deferred context", );
 
         // Initialize debug annotation support, if available
         ID3D11DeviceContext_QueryInterface(
@@ -3174,7 +3122,7 @@ static bool D3D11_INTERNAL_CreateFence(
         renderer->device,
         &queryDesc,
         &queryHandle);
-    ERROR_LOG_RETURN("Could not create query", 0);
+    CHECK_D3D11_ERROR_AND_RETURN("Could not create query", false);
 
     fence = SDL_malloc(sizeof(D3D11Fence));
     fence->handle = queryHandle;
@@ -3207,7 +3155,6 @@ static bool D3D11_INTERNAL_AcquireFence(
     if (renderer->availableFenceCount == 0) {
         if (!D3D11_INTERNAL_CreateFence(renderer)) {
             SDL_UnlockMutex(renderer->fenceLock);
-            SDL_SetError("Failed to create fence!");
             return false;
         }
     }
@@ -3408,7 +3355,7 @@ static void D3D11_INTERNAL_PushUniformData(
             D3D11_MAP_WRITE_DISCARD,
             0,
             &subres);
-        ERROR_LOG_RETURN("Failed to map uniform buffer", )
+        CHECK_D3D11_ERROR_AND_RETURN("Failed to map uniform buffer", )
 
         d3d11UniformBuffer->mappedData = subres.pData;
     }
@@ -4721,7 +4668,7 @@ static void D3D11_ReleaseFence(
  * wait until the command buffer has finished executing to map the staging resource.
  */
 
-static void D3D11_INTERNAL_MapAndCopyBufferDownload(
+static bool D3D11_INTERNAL_MapAndCopyBufferDownload(
     D3D11Renderer *renderer,
     D3D11TransferBuffer *transferBuffer,
     D3D11BufferDownload *bufferDownload)
@@ -4737,13 +4684,16 @@ static void D3D11_INTERNAL_MapAndCopyBufferDownload(
         D3D11_MAP_READ,
         0,
         &subres);
-    ERROR_LOG_RETURN("Failed to map staging buffer", )
+    SDL_UnlockMutex(renderer->contextLock);
+
+    CHECK_D3D11_ERROR_AND_RETURN("Failed to map staging buffer", false)
 
     SDL_memcpy(
         ((Uint8 *)transferBuffer->data) + bufferDownload->dstOffset,
         ((Uint8 *)subres.pData),
         bufferDownload->size);
 
+    SDL_LockMutex(renderer->contextLock);
     ID3D11DeviceContext_Unmap(
         renderer->immediateContext,
         (ID3D11Resource *)bufferDownload->stagingBuffer,
@@ -4751,9 +4701,11 @@ static void D3D11_INTERNAL_MapAndCopyBufferDownload(
     SDL_UnlockMutex(renderer->contextLock);
 
     ID3D11Buffer_Release(bufferDownload->stagingBuffer);
+
+    return true;
 }
 
-static void D3D11_INTERNAL_MapAndCopyTextureDownload(
+static bool D3D11_INTERNAL_MapAndCopyTextureDownload(
     D3D11Renderer *renderer,
     D3D11TransferBuffer *transferBuffer,
     D3D11TextureDownload *textureDownload)
@@ -4771,7 +4723,9 @@ static void D3D11_INTERNAL_MapAndCopyTextureDownload(
         D3D11_MAP_READ,
         0,
         &subres);
-    ERROR_LOG_RETURN("Could not map staging texture", )
+    SDL_UnlockMutex(renderer->contextLock);
+
+    CHECK_D3D11_ERROR_AND_RETURN("Could not map staging texture", false)
 
     for (depth = 0; depth < textureDownload->depth; depth += 1) {
         dataPtrOffset = textureDownload->bufferOffset + (depth * textureDownload->bytesPerDepthSlice);
@@ -4785,21 +4739,24 @@ static void D3D11_INTERNAL_MapAndCopyTextureDownload(
         }
     }
 
+    SDL_LockMutex(renderer->contextLock);
     ID3D11DeviceContext_Unmap(
         renderer->immediateContext,
         textureDownload->stagingTexture,
         0);
-
     SDL_UnlockMutex(renderer->contextLock);
 
     ID3D11Resource_Release(textureDownload->stagingTexture);
+
+    return true;
 }
 
-static void D3D11_INTERNAL_CleanCommandBuffer(
+static bool D3D11_INTERNAL_CleanCommandBuffer(
     D3D11Renderer *renderer,
     D3D11CommandBuffer *commandBuffer)
 {
     Uint32 i, j;
+    bool result = true;
 
     // Perform deferred download map and copy
 
@@ -4807,14 +4764,14 @@ static void D3D11_INTERNAL_CleanCommandBuffer(
         D3D11TransferBuffer *transferBuffer = commandBuffer->usedTransferBuffers[i];
 
         for (j = 0; j < transferBuffer->bufferDownloadCount; j += 1) {
-            D3D11_INTERNAL_MapAndCopyBufferDownload(
+            result &= D3D11_INTERNAL_MapAndCopyBufferDownload(
                 renderer,
                 transferBuffer,
                 &transferBuffer->bufferDownloads[j]);
         }
 
         for (j = 0; j < transferBuffer->textureDownloadCount; j += 1) {
-            D3D11_INTERNAL_MapAndCopyTextureDownload(
+            result &= D3D11_INTERNAL_MapAndCopyTextureDownload(
                 renderer,
                 transferBuffer,
                 &transferBuffer->textureDownloads[j]);
@@ -4883,6 +4840,8 @@ static void D3D11_INTERNAL_CleanCommandBuffer(
             renderer->submittedCommandBufferCount -= 1;
         }
     }
+
+    return result;
 }
 
 static void D3D11_INTERNAL_PerformPendingDestroys(
@@ -4961,7 +4920,7 @@ static void D3D11_INTERNAL_WaitForFence(
     SDL_UnlockMutex(renderer->contextLock);
 }
 
-static void D3D11_WaitForFences(
+static bool D3D11_WaitForFences(
     SDL_GPURenderer *driverData,
     bool waitAll,
     SDL_GPUFence *const *fences,
@@ -5000,6 +4959,7 @@ static void D3D11_WaitForFences(
 
     SDL_LockMutex(renderer->contextLock);
 
+    bool result = true;
     // Check if we can perform any cleanups
     for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
         res = ID3D11DeviceContext_GetData(
@@ -5009,7 +4969,7 @@ static void D3D11_WaitForFences(
             sizeof(queryData),
             0);
         if (res == S_OK) {
-            D3D11_INTERNAL_CleanCommandBuffer(
+            result &= D3D11_INTERNAL_CleanCommandBuffer(
                 renderer,
                 renderer->submittedCommandBuffers[i]);
         }
@@ -5018,6 +4978,8 @@ static void D3D11_WaitForFences(
     D3D11_INTERNAL_PerformPendingDestroys(renderer);
 
     SDL_UnlockMutex(renderer->contextLock);
+
+    return result;
 }
 
 static bool D3D11_QueryFence(
@@ -5073,7 +5035,7 @@ static bool D3D11_INTERNAL_InitializeSwapchainTexture(
         0,
         &D3D_IID_ID3D11Texture2D,
         (void **)&swapchainTexture);
-    ERROR_LOG_RETURN("Could not get buffer from swapchain!", 0);
+    CHECK_D3D11_ERROR_AND_RETURN("Could not get buffer from swapchain!", false);
 
     // Create the RTV for the swapchain
     rtvDesc.Format = rtvFormat;
@@ -5087,7 +5049,7 @@ static bool D3D11_INTERNAL_InitializeSwapchainTexture(
         &rtv);
     if (FAILED(res)) {
         ID3D11Texture2D_Release(swapchainTexture);
-        D3D11_INTERNAL_LogError(renderer->device, "Swapchain RTV creation failed", res);
+        D3D11_INTERNAL_SetError(renderer, "Swapchain RTV creation failed", res);
         return false;
     }
 
@@ -5173,7 +5135,7 @@ static bool D3D11_INTERNAL_CreateSwapchain(
         (IUnknown *)renderer->device,
         &swapchainDesc,
         &swapchain);
-    ERROR_LOG_RETURN("Could not create swapchain", 0);
+    CHECK_D3D11_ERROR_AND_RETURN("Could not create swapchain", false);
 
     /*
      * The swapchain's parent is a separate factory from the factory that
@@ -5288,7 +5250,7 @@ static bool D3D11_INTERNAL_ResizeSwapchain(
         height,
         DXGI_FORMAT_UNKNOWN, // Keep the old format
         renderer->supportsTearing ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0);
-    ERROR_LOG_RETURN("Could not resize swapchain buffers", 0);
+    CHECK_D3D11_ERROR_AND_RETURN("Could not resize swapchain buffers", false);
 
     // Create the texture object for the swapchain
     return D3D11_INTERNAL_InitializeSwapchainTexture(
@@ -5328,8 +5290,7 @@ static bool D3D11_SupportsSwapchainComposition(
 
     D3D11WindowData *windowData = D3D11_INTERNAL_FetchWindowData(window);
     if (windowData == NULL) {
-        SDL_SetError("Must claim window before querying swapchain composition support!");
-        return false;
+        SET_STRING_ERROR_AND_RETURN("Must claim window before querying swapchain composition support!", false)
     }
 
     // Check the color space support if necessary
@@ -5349,8 +5310,7 @@ static bool D3D11_SupportsSwapchainComposition(
                 return false;
             }
         } else {
-            SDL_SetError("DXGI 1.4 not supported, cannot use composition other than SDL_GPU_SWAPCHAINCOMPOSITION_SDR!");
-            return false;
+            SET_STRING_ERROR_AND_RETURN("DXGI 1.4 not supported, cannot use composition other than SDL_GPU_SWAPCHAINCOMPOSITION_SDR!", false)
         }
     }
 
@@ -5404,9 +5364,8 @@ static bool D3D11_ClaimWindow(
 
             return true;
         } else {
-            SDL_SetError("Could not create swapchain, failed to claim window!");
             SDL_free(windowData);
-            return false;
+            SET_STRING_ERROR_AND_RETURN("Could not create swapchain, failed to claim window!", false)
         }
     } else {
         SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Window already claimed!");
@@ -5475,11 +5434,10 @@ static void D3D11_ReleaseWindow(
     SDL_ClearProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA);
 }
 
-static SDL_GPUTexture *D3D11_AcquireSwapchainTexture(
+static bool D3D11_AcquireSwapchainTexture(
     SDL_GPUCommandBuffer *commandBuffer,
     SDL_Window *window,
-    Uint32 *w,
-    Uint32 *h)
+    SDL_GPUTexture **swapchainTexture)
 {
     D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
     D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer;
@@ -5488,9 +5446,11 @@ static SDL_GPUTexture *D3D11_AcquireSwapchainTexture(
     int windowW, windowH;
     HRESULT res;
 
+    *swapchainTexture = NULL;
+
     windowData = D3D11_INTERNAL_FetchWindowData(window);
     if (windowData == NULL) {
-        return NULL;
+        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.
@@ -5498,31 +5458,34 @@ static SDL_GPUTexture *D3D11_AcquireSwapchainTexture(
     SDL_GetWindowSize(window, &windowW, &windowH);
 
     if ((UINT)windowW != swapchainDesc.BufferDesc.Width || (UINT)windowH != swapchainDesc.BufferDesc.Height) {
-        res = D3D11_INTERNAL_ResizeSwapchain(
+        if (!D3D11_INTERNAL_ResizeSwapchain(
             renderer,
             windowData,
             windowW,
-            windowH);
-        ERROR_SET_RETURN("Could not resize swapchain", NULL);
+            windowH)) {
+            return false;
+        }
     }
 
     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
-            D3D11_WaitForFences(
+            if (!D3D11_WaitForFences(
                 (SDL_GPURenderer *)renderer,
                 true,
                 &windowData->inFlightFences[windowData->frameCounter],
-                1);
+                1)) {
+                return false;
+            }
         } else {
             if (!D3D11_QueryFence(
                     (SDL_GPURenderer *)d3d11CommandBuffer->renderer,
                     windowData->inFlightFences[windowData->frameCounter])) {
                 /*
                  * In MAILBOX or IMMEDIATE mode, if the least recent fence is not signaled,
-                 * return NULL to indicate that rendering should be skipped
+                 * return true to indicate that there is no error but rendering should be skipped
                  */
-                return NULL;
+                return true;
             }
         }
 
@@ -5539,11 +5502,7 @@ static SDL_GPUTexture *D3D11_AcquireSwapchainTexture(
         0,
         &D3D_IID_ID3D11Texture2D,
         (void **)&windowData->texture.handle);
-    ERROR_SET_RETURN("Could not acquire swapchain!", NULL);
-
-    // Send the dimensions to the out parameters.
-    *w = windowW;
-    *h = windowH;
+    CHECK_D3D11_ERROR_AND_RETURN("Could not acquire swapchain!", false);
 
     // Update the texture container dimensions
     windowData->textureContainer.header.info.width = windowW;
@@ -5560,18 +5519,19 @@ static SDL_GPUTexture *D3D11_AcquireSwapchainTexture(
     d3d11CommandBuffer->windowDataCount += 1;
 
     // Return the swapchain texture
-    return (SDL_GPUTexture *)&windowData->textureContainer;
+    *swapchainTexture = (SDL_GPUTexture*) &windowData->textureContainer;
+    return true;
 }
 
 static SDL_GPUTextureFormat D3D11_GetSwapchainTextureFormat(
     SDL_GPURenderer *driverData,
     SDL_Window *window)
 {
+    D3D11Renderer *renderer = (D3D11Renderer *)driverData;
     D3D11WindowData *windowData = D3D11_INTERNAL_FetchWindowData(window);
 
     if (windowData == NULL) {
-        SDL_SetError("Cannot get swapchain format, window has not been claimed!");
-        return SDL_GPU_TEXTUREFORMAT_INVALID;
+        SET_STRING_ERROR_AND_RETURN("Cannot get swapchain format, window has not been claimed!", SDL_GPU_TEXTUREFORMAT_INVALID)
     }
 
     return windowData->textureContainer.header.info.format;
@@ -5587,18 +5547,15 @@ static bool D3D11_SetSwapchainParameters(
     D3D11WindowData *windowData = D3D11_INTERNAL_FetchWindowData(window);
 
     if (windowData == NULL) {
-        SDL_SetError("Cannot set swapchain parameters on unclaimed window!");
-        return false;
+        SET_STRING_ERROR_AND_RETURN("Cannot set swapchain parameters on unclaimed window!", false)
     }
 
     if (!D3D11_SupportsSwapchainComposition(driverData, window, swapchainComposition)) {
-        SDL_SetError("Swapchain composition not supported!");
-        return false;
+        SET_STRING_ERROR_AND_RETURN("Swapchain composition not supported!", false)
     }
 
     if (!D3D11_SupportsPresentMode(driverData, window, presentMode)) {
-        SDL_SetError("Present mode not supported!");
-        return false;
+        SET_STRING_ERROR_AND_RETURN("Present mode not supported!", false)
     }
 
     if (
@@ -5623,7 +5580,7 @@ static bool D3D11_SetSwapchainParameters(
 
 // Submission
 
-static void D3D11_Submit(
+static bool D3D11_Submit(
     SDL_GPUCommandBuffer *commandBuffer)
 {
     D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
@@ -5668,7 +5625,10 @@ static void D3D11_Submit(
         d3d11CommandBuffer->context,
         0,
         &commandList);
-    ERROR_LOG("Could not finish command list recording!");
+    if (FAILED(res)) {
+        SDL_UnlockMutex(renderer->contextLock);
+        CHECK_D3D11_ERROR_AND_RETURN("Could not finish command list recording!", false)
+    }
 
     // Submit the command list to the immediate context
     ID3D11DeviceContext_ExecuteCommandList(
@@ -5689,6 +5649,8 @@ static void D3D11_Submit(
     renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount] = d3d11CommandBuffer;
     renderer->submittedCommandBufferCount += 1;
 
+    bool result = true;
+
     // Present, if applicable
     for (Uint32 i = 0; i < d3d11CommandBuffer->windowDataCount; i += 1) {
         D3D11WindowData *windowData = d3d11CommandBuffer->windowDatas[i];
@@ -5705,11 +5667,15 @@ static void D3D11_Submit(
             presentFlags = DXGI_PRESENT_ALLOW_TEARING;
         }
 
-        IDXGISwapChain_Present(
+        res = IDXGISwapChain_Present(
             windowData->swapchain,
             syncInterval,
             presentFlags);
 
+        if (FAILED(res)) {
+            result = false;
+        }
+
         ID3D11Texture2D_Release(windowData->texture.handle);
 
         windowData->inFlightFences[windowData->frameCounter] = (SDL_GPUFence*)d3d11CommandBuffer->fence;
@@ -5729,7 +5695,7 @@ static void D3D11_Submit(
             sizeof(queryData),
             0);
         if (res == S_OK) {
-            D3D11_INTERNAL_CleanCommandBuffer(
+            result &= D3D11_INTERNAL_CleanCommandBuffer(
                 renderer,
                 renderer->submittedCommandBuffers[i]);
         }
@@ -5738,6 +5704,8 @@ static void D3D11_Submit(
     D3D11_INTERNAL_PerformPendingDestroys(renderer);
 
     SDL_UnlockMutex(renderer->contextLock);
+
+    return result;
 }
 
 static SDL_GPUFence *D3D11_SubmitAndAcquireFence(
@@ -5752,11 +5720,12 @@ static SDL_GPUFence *D3D11_SubmitAndAcquireFence(
     return (SDL_GPUFence *)fence;
 }
 
-static void D3D11_Wait(
+static bool D3D11_Wait(
     SDL_GPURenderer *driverData)
 {
     D3D11Renderer *renderer = (D3D11Renderer *)driverData;
     D3D11CommandBuffer *commandBuffer;
+    bool result = true;
 
     /*
      * Wait for all submitted command buffers to complete.
@@ -5772,12 +5741,14 @@ static void D3D11_Wait(
 
     for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
         commandBuffer = renderer->submittedCommandBuffers[i];
-        D3D11_INTERNAL_CleanCommandBuffer(renderer, commandBuffer);
+        result &= D3D11_INTERNAL_CleanCommandBuffer(renderer, commandBuffer);
     }
 
     D3D11_INTERNAL_PerformPendingDestroys(renderer);
 
     SDL_UnlockMutex(renderer->contextLock);
+
+    return result;
 }
 
 // Format Info
@@ -6209,8 +6180,7 @@ static SDL_GPUDevice *D3D11_CreateDevice(bool debugMode, bool preferLowPower, SD
     // Load the DXGI library
     renderer->dxgi_dll = SDL_LoadObject(DXGI_DLL);
     if (renderer->dxgi_dll == NULL) {
-        SDL_SetError("Could not find " DXGI_DLL);
-        return NULL;
+        SET_STRING_ERROR_AND_RETURN("Could not find " DXGI_DLL, NULL)
     }
 
     // Load the CreateDXGIFactory1 function
@@ -6218,15 +6188,14 @@ static SDL_GPUDevice *D3D11_CreateDevice(bool debugMode, bool preferLowPower, SD
         renderer->dxgi_dll,
         CREATE_DXGI_FACTORY1_FUNC);
     if (CreateDxgiFactoryFunc == NULL) {
-        SDL_SetError("Could not load function: " CREATE_DXGI_FACTORY1_FUNC);
-        return NULL;
+        SET_STRING_ERROR_AND_RETURN("Could not load function: " CREATE_DXGI_FACTORY1_FUNC, NULL)
     }
 
     // Create the DXGI factory
     res = CreateDxgiFactoryFunc(
         &D3D_IID_IDXGIFactory1,
         (void **)&renderer->factory);
-    ERROR_SET_RETURN("Could not create DXGIFactory", NULL);
+    CHECK_D3D11_ERROR_AND_RETURN("Could not create DXGIFactory", NULL);
 
     // Check for flip-model discard support (supported on Windows 10+)
     res = IDXGIFactory1_QueryInterface(
@@ -6286,8 +6255,7 @@ static SDL_GPUDevice *D3D11_CreateDevice(bool debugMode, bool preferLowPower, SD
     // Load the D3D library
     renderer->d3d11_dll = SDL_LoadObject(D3D11_DLL);
     if (renderer->d3d11_dll == NULL) {
-        SDL_SetError("Could not find " D3D11_DLL);
-        return NULL;
+        SET_STRING_ERROR_AND_RETURN("Could not find " D3D11_DLL, NULL)
     }
 
     // Load the CreateDevice function
@@ -6295,8 +6263,7 @@ static SDL_GPUDevice *D3D11_CreateDevice(bool debugMode, bool preferLowPower, SD
         renderer->d3d11_dll,
         D3D11_CREATE_DEVICE_FUNC);
     if (D3D11CreateDeviceFunc == NULL) {
-        SDL_SetError("Could not load function: " D3D11_CREATE_DEVICE_FUNC);
-        return NULL;
+        SET_STRING_ERROR_AND_RETURN("Could not load function: " D3D11_CREATE_DEVICE_FUNC, NULL)
     }
 
     // Set up device flags
@@ -6327,14 +6294,14 @@ tryCreateDevice:
         goto tryCreateDevice;
     }
 
-    ERROR_SET_RETURN("Could not create D3D11 device", NULL);
+    CHECK_D3D11_ERROR_AND_RETURN("Could not create D3D11 device", NULL);
 
     // The actual device we want is the ID3D11Device1 interface...
     res = ID3D11Device_QueryInterface(
         d3d11Device,
         &D3D_IID_ID3D11Device1,
         (void **)&renderer->device);
-    ERROR_SET_RETURN("Could not get ID3D11Device1 interface", NULL);
+    CHECK_D3D11_ERROR_AND_RETURN("Could not get ID3D11Device1 interface", NULL);
 
     // Release the old device interface, we don't need it anymore
     ID3D11Device_Release(d3d11Device);

File diff suppressed because it is too large
+ 161 - 185
src/gpu/d3d12/SDL_gpu_d3d12.c


+ 44 - 42
src/gpu/metal/SDL_gpu_metal.m

@@ -53,13 +53,22 @@
     commandBuffer->count += 1;                                 \
     SDL_AtomicIncRef(&resource->referenceCount);
 
+#define SET_ERROR_AND_RETURN(fmt, msg, ret)           \
+    if (renderer->debugMode) {                        \
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, fmt, msg); \
+    }                                                 \
+    SDL_SetError(fmt, msg);                           \
+    return ret;                                       \
+
+#define SET_STRING_ERROR_AND_RETURN(msg, ret) SET_ERROR_AND_RETURN("%s", msg, ret)
+
 // Blit Shaders
 
 #include "Metal_Blit.h"
 
 // Forward Declarations
 
-static void METAL_Wait(SDL_GPURenderer *driverData);
+static bool METAL_Wait(SDL_GPURenderer *driverData);
 static void METAL_ReleaseWindow(
     SDL_GPURenderer *driverData,
     SDL_Window *window);
@@ -574,7 +583,7 @@ struct MetalRenderer
     id<MTLDevice> device;
     id<MTLCommandQueue> queue;
 
-    bool debug_mode;
+    bool debugMode;
 
     MetalWindowData **claimedWindows;
     Uint32 claimedWindowCount;
@@ -973,9 +982,7 @@ static SDL_GPUComputePipeline *METAL_CreateComputePipeline(
 
         handle = [renderer->device newComputePipelineStateWithFunction:libraryFunction.function error:&error];
         if (error != NULL) {
-            SDL_SetError(
-                "Creating compute pipeline failed: %s", [[error description] UTF8String]);
-            return NULL;
+            SET_ERROR_AND_RETURN("Creating compute pipeline failed: %s", [[error description] UTF8String], NULL);
         }
 
         pipeline = SDL_calloc(1, sizeof(MetalComputePipeline));
@@ -1107,9 +1114,7 @@ static SDL_GPUGraphicsPipeline *METAL_CreateGraphicsPipeline(
 
         pipelineState = [renderer->device newRenderPipelineStateWithDescriptor:pipelineDescriptor error:&error];
         if (error != NULL) {
-            SDL_SetError(
-                "Creating render pipeline failed: %s", [[error description] UTF8String]);
-            return NULL;
+            SET_ERROR_AND_RETURN("Creating render pipeline failed: %s", [[error description] UTF8String], NULL);
         }
 
         Uint32 sampleMask = createinfo->multisample_state.enable_mask ?
@@ -1146,7 +1151,7 @@ static void METAL_SetBufferName(
         MetalBufferContainer *container = (MetalBufferContainer *)buffer;
         size_t textLength = SDL_strlen(text) + 1;
 
-        if (renderer->debug_mode) {
+        if (renderer->debugMode) {
             container->debugName = SDL_realloc(
                 container->debugName,
                 textLength);
@@ -1173,7 +1178,7 @@ static void METAL_SetTextureName(
         MetalTextureContainer *container = (MetalTextureContainer *)texture;
         size_t textLength = SDL_strlen(text) + 1;
 
-        if (renderer->debug_mode) {
+        if (renderer->debugMode) {
             container->debugName = SDL_realloc(
                 container->debugName,
                 textLength);
@@ -1282,8 +1287,7 @@ static SDL_GPUSampler *METAL_CreateSampler(
 
         sampler = [renderer->device newSamplerStateWithDescriptor:samplerDesc];
         if (sampler == NULL) {
-            SDL_SetError("Failed to create sampler");
-            return NULL;
+            SET_STRING_ERROR_AND_RETURN("Failed to create sampler", NULL);
         }
 
         metalSampler = (MetalSampler *)SDL_calloc(1, sizeof(MetalSampler));
@@ -1341,8 +1345,7 @@ static MetalTexture *METAL_INTERNAL_CreateTexture(
                                                                       MTLTextureSwizzleRed,
                                                                       MTLTextureSwizzleAlpha);
         } else {
-            SDL_SetError("SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM is not supported");
-            return NULL;
+            SET_STRING_ERROR_AND_RETURN("SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM is not supported", NULL);
         }
     }
 
@@ -1409,8 +1412,7 @@ static SDL_GPUTexture *METAL_CreateTexture(
             createinfo);
 
         if (texture == NULL) {
-            SDL_SetError("Failed to create texture!");
-            return NULL;
+            SET_STRING_ERROR_AND_RETURN("Failed to create texture", NULL);
         }
 
         container = SDL_calloc(1, sizeof(MetalTextureContainer));
@@ -1459,7 +1461,7 @@ static MetalTexture *METAL_INTERNAL_PrepareTextureForWrite(
 
         container->activeTexture = container->textures[container->textureCount - 1];
 
-        if (renderer->debug_mode && container->debugName != NULL) {
+        if (renderer->debugMode && container->debugName != NULL) {
             container->activeTexture->handle.label = @(container->debugName);
         }
     }
@@ -1623,7 +1625,7 @@ static MetalBuffer *METAL_INTERNAL_PrepareBufferForWrite(
 
         container->activeBuffer = container->buffers[container->bufferCount - 1];
 
-        if (renderer->debug_mode && container->debugName != NULL) {
+        if (renderer->debugMode && container->debugName != NULL) {
             container->activeBuffer->handle.label = @(container->debugName);
         }
     }
@@ -3345,7 +3347,7 @@ static void METAL_INTERNAL_PerformPendingDestroys(
 
 // Fences
 
-static void METAL_WaitForFences(
+static bool METAL_WaitForFences(
     SDL_GPURenderer *driverData,
     bool waitAll,
     SDL_GPUFence *const *fences,
@@ -3374,6 +3376,8 @@ static void METAL_WaitForFences(
         }
 
         METAL_INTERNAL_PerformPendingDestroys(renderer);
+
+        return true;
     }
 }
 
@@ -3524,9 +3528,8 @@ static bool METAL_ClaimWindow(
 
                 return true;
             } else {
-                SDL_SetError("Could not create swapchain, failed to claim window!");
                 SDL_free(windowData);
-                return false;
+                SET_STRING_ERROR_AND_RETURN("Could not create swapchain, failed to claim window", false);
             }
         } else {
             SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Window already claimed!");
@@ -3544,7 +3547,7 @@ static void METAL_ReleaseWindow(
         MetalWindowData *windowData = METAL_INTERNAL_FetchWindowData(window);
 
         if (windowData == NULL) {
-            return;
+            SET_STRING_ERROR_AND_RETURN("Window is not claimed by this SDL_GpuDevice", );
         }
 
         METAL_Wait(driverData);
@@ -3566,20 +3569,20 @@ static void METAL_ReleaseWindow(
     }
 }
 
-static SDL_GPUTexture *METAL_AcquireSwapchainTexture(
+static bool METAL_AcquireSwapchainTexture(
     SDL_GPUCommandBuffer *commandBuffer,
     SDL_Window *window,
-    Uint32 *w,
-    Uint32 *h)
+    SDL_GPUTexture **texture)
 {
     @autoreleasepool {
         MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        MetalRenderer *renderer = metalCommandBuffer->renderer;
         MetalWindowData *windowData;
         CGSize drawableSize;
 
         windowData = METAL_INTERNAL_FetchWindowData(window);
         if (windowData == NULL) {
-            return NULL;
+            SET_STRING_ERROR_AND_RETURN("Window is not claimed by this SDL_GpuDevice", false);
         }
 
         // Get the drawable and its underlying texture
@@ -3591,10 +3594,6 @@ static SDL_GPUTexture *METAL_AcquireSwapchainTexture(
         windowData->textureContainer.header.info.width = (Uint32)drawableSize.width;
         windowData->textureContainer.header.info.height = (Uint32)drawableSize.height;
 
-        // Send the dimensions to the out parameters.
-        *w = (Uint32)drawableSize.width;
-        *h = (Uint32)drawableSize.height;
-
         // Set up presentation
         if (metalCommandBuffer->windowDataCount == metalCommandBuffer->windowDataCapacity) {
             metalCommandBuffer->windowDataCapacity += 1;
@@ -3606,7 +3605,8 @@ static SDL_GPUTexture *METAL_AcquireSwapchainTexture(
         metalCommandBuffer->windowDataCount += 1;
 
         // Return the swapchain texture
-        return (SDL_GPUTexture *)&windowData->textureContainer;
+        *texture = (SDL_GPUTexture *)&windowData->textureContainer;
+        return true;
     }
 }
 
@@ -3614,11 +3614,11 @@ static SDL_GPUTextureFormat METAL_GetSwapchainTextureFormat(
     SDL_GPURenderer *driverData,
     SDL_Window *window)
 {
+    MetalRenderer *renderer = (MetalRenderer *)driverData;
     MetalWindowData *windowData = METAL_INTERNAL_FetchWindowData(window);
 
     if (windowData == NULL) {
-        SDL_SetError("Cannot get swapchain format, window has not been claimed!");
-        return SDL_GPU_TEXTUREFORMAT_INVALID;
+        SET_STRING_ERROR_AND_RETURN("Cannot get swapchain format, window has not been claimed", SDL_GPU_TEXTUREFORMAT_INVALID);
     }
 
     return windowData->textureContainer.header.info.format;
@@ -3631,22 +3631,20 @@ static bool METAL_SetSwapchainParameters(
     SDL_GPUPresentMode presentMode)
 {
     @autoreleasepool {
+        MetalRenderer *renderer = (MetalRenderer *)driverData;
         MetalWindowData *windowData = METAL_INTERNAL_FetchWindowData(window);
         CGColorSpaceRef colorspace;
 
         if (windowData == NULL) {
-            SDL_SetError("Cannot set swapchain parameters, window has not been claimed!");
-            return false;
+            SET_STRING_ERROR_AND_RETURN("Cannot set swapchain parameters, window has not been claimed!", false);
         }
 
         if (!METAL_SupportsSwapchainComposition(driverData, window, swapchainComposition)) {
-            SDL_SetError("Swapchain composition not supported!");
-            return false;
+            SET_STRING_ERROR_AND_RETURN("Swapchain composition not supported", false);
         }
 
         if (!METAL_SupportsPresentMode(driverData, window, presentMode)) {
-            SDL_SetError("Present mode not supported!");
-            return false;
+            SET_STRING_ERROR_AND_RETURN("Present mode not supported", false);
         }
 
         METAL_Wait(driverData);
@@ -3673,7 +3671,7 @@ static bool METAL_SetSwapchainParameters(
 
 // Submission
 
-static void METAL_Submit(
+static bool METAL_Submit(
     SDL_GPUCommandBuffer *commandBuffer)
 {
     @autoreleasepool {
@@ -3720,6 +3718,8 @@ static void METAL_Submit(
         METAL_INTERNAL_PerformPendingDestroys(renderer);
 
         SDL_UnlockMutex(renderer->submitLock);
+
+        return true;
     }
 }
 
@@ -3735,7 +3735,7 @@ static SDL_GPUFence *METAL_SubmitAndAcquireFence(
     return (SDL_GPUFence *)fence;
 }
 
-static void METAL_Wait(
+static bool METAL_Wait(
     SDL_GPURenderer *driverData)
 {
     @autoreleasepool {
@@ -3762,6 +3762,8 @@ static void METAL_Wait(
         METAL_INTERNAL_PerformPendingDestroys(renderer);
 
         SDL_UnlockMutex(renderer->submitLock);
+
+        return true;
     }
 }
 
@@ -4039,7 +4041,7 @@ static SDL_GPUDevice *METAL_CreateDevice(bool debugMode, bool preferLowPower, SD
             [renderer->device.name UTF8String]);
 
         // Remember debug mode
-        renderer->debug_mode = debugMode;
+        renderer->debugMode = debugMode;
 
         // Set up colorspace array
         SwapchainCompositionToColorSpace[0] = kCGColorSpaceSRGB;

File diff suppressed because it is too large
+ 249 - 250
src/gpu/vulkan/SDL_gpu_vulkan.c


+ 12 - 6
src/render/gpu/SDL_render_gpu.c

@@ -956,9 +956,12 @@ static bool GPU_RenderPresent(SDL_Renderer *renderer)
 {
     GPU_RenderData *data = (GPU_RenderData *)renderer->internal;
 
-    Uint32 swapchain_w, swapchain_h;
+    SDL_GPUTexture *swapchain;
+    bool result = SDL_AcquireGPUSwapchainTexture(data->state.command_buffer, renderer->window, &swapchain);
 
-    SDL_GPUTexture *swapchain = SDL_AcquireGPUSwapchainTexture(data->state.command_buffer, renderer->window, &swapchain_w, &swapchain_h);
+    if (!result) {
+        SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Failed to acquire swapchain texture: %s", SDL_GetError());
+    }
 
     if (swapchain == NULL) {
         goto submit;
@@ -966,6 +969,9 @@ static bool GPU_RenderPresent(SDL_Renderer *renderer)
 
     SDL_GPUTextureFormat swapchain_fmt = SDL_GetGPUSwapchainTextureFormat(data->device, renderer->window);
 
+    int window_w, window_h;
+    SDL_GetWindowSizeInPixels(renderer->window, &window_w, &window_h);
+
     SDL_GPUBlitInfo blit_info;
     SDL_zero(blit_info);
 
@@ -973,16 +979,16 @@ static bool GPU_RenderPresent(SDL_Renderer *renderer)
     blit_info.source.w = data->backbuffer.width;
     blit_info.source.h = data->backbuffer.height;
     blit_info.destination.texture = swapchain;
-    blit_info.destination.w = swapchain_w;
-    blit_info.destination.h = swapchain_h;
+    blit_info.destination.w = window_w;
+    blit_info.destination.h = window_h;
     blit_info.load_op = SDL_GPU_LOADOP_DONT_CARE;
     blit_info.filter = SDL_GPU_FILTER_LINEAR;
 
     SDL_BlitGPUTexture(data->state.command_buffer, &blit_info);
 
-    if (swapchain_w != data->backbuffer.width || swapchain_h != data->backbuffer.height || swapchain_fmt != data->backbuffer.format) {
+    if (window_w != data->backbuffer.width || window_h != data->backbuffer.height || swapchain_fmt != data->backbuffer.format) {
         SDL_ReleaseGPUTexture(data->device, data->backbuffer.texture);
-        CreateBackbuffer(data, swapchain_w, swapchain_h, swapchain_fmt);
+        CreateBackbuffer(data, window_w, window_h, swapchain_fmt);
     }
 
 // *** FIXME ***

+ 5 - 2
test/testgpu_simple_clear.c

@@ -74,7 +74,6 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
 
 SDL_AppResult SDL_AppIterate(void *appstate)
 {
-	Uint32 w, h;
 	SDL_GPUCommandBuffer *cmdbuf = SDL_AcquireGPUCommandBuffer(gpu_device);
 
 	if (cmdbuf == NULL) {
@@ -82,7 +81,11 @@ SDL_AppResult SDL_AppIterate(void *appstate)
         return SDL_APP_FAILURE;
 	}
 
-	SDL_GPUTexture *swapchainTexture = SDL_AcquireGPUSwapchainTexture(cmdbuf, state->windows[0], &w, &h);
+    SDL_GPUTexture *swapchainTexture;
+	if (!SDL_AcquireGPUSwapchainTexture(cmdbuf, state->windows[0], &swapchainTexture)) {
+        SDL_Log("SDL_AcquireGPUSwapchainTexture failed: %s", SDL_GetError());
+        return SDL_APP_FAILURE;
+    }
 	if (swapchainTexture != NULL) {
         const double currentTime = (double)SDL_GetPerformanceCounter() / SDL_GetPerformanceFrequency();
         SDL_GPURenderPass *renderPass;

+ 15 - 6
test/testgpu_spinning_cube.c

@@ -325,27 +325,36 @@ static void
 Render(SDL_Window *window, const int windownum)
 {
     WindowState *winstate = &window_states[windownum];
-    SDL_GPUTexture *swapchain;
+    SDL_GPUTexture *swapchainTexture;
     SDL_GPUColorTargetInfo color_target;
     SDL_GPUDepthStencilTargetInfo depth_target;
     float matrix_rotate[16], matrix_modelview[16], matrix_perspective[16], matrix_final[16];
-    Uint32 drawablew, drawableh;
     SDL_GPUCommandBuffer *cmd;
     SDL_GPURenderPass *pass;
     SDL_GPUBufferBinding vertex_binding;
     SDL_GPUBlitInfo blit_info;
+    int drawablew, drawableh;
 
     /* Acquire the swapchain texture */
 
     cmd = SDL_AcquireGPUCommandBuffer(gpu_device);
-    swapchain = SDL_AcquireGPUSwapchainTexture(cmd, state->windows[windownum], &drawablew, &drawableh);
+    if (!cmd) {
+        SDL_Log("Failed to acquire command buffer :%s", SDL_GetError());
+        quit(2);
+    }
+    if (!SDL_AcquireGPUSwapchainTexture(cmd, state->windows[windownum], &swapchainTexture)) {
+        SDL_Log("Failed to acquire swapchain texture: %s", SDL_GetError());
+        quit(2);
+    }
 
-    if (!swapchain) {
+    if (swapchainTexture == NULL) {
         /* No swapchain was acquired, probably too many frames in flight */
         SDL_SubmitGPUCommandBuffer(cmd);
         return;
     }
 
+    SDL_GetWindowSizeInPixels(window, &drawablew, &drawableh);
+
     /*
     * Do some rotation with Euler angles. It is not a fixed axis as
     * quaterions would be, but the effect is cool.
@@ -403,7 +412,7 @@ Render(SDL_Window *window, const int windownum)
     } else {
         color_target.load_op = SDL_GPU_LOADOP_CLEAR;
         color_target.store_op = SDL_GPU_STOREOP_STORE;
-        color_target.texture = swapchain;
+        color_target.texture = swapchainTexture;
     }
 
     SDL_zero(depth_target);
@@ -437,7 +446,7 @@ Render(SDL_Window *window, const int windownum)
         blit_info.source.w = drawablew;
         blit_info.source.h = drawableh;
 
-        blit_info.destination.texture = swapchain;
+        blit_info.destination.texture = swapchainTexture;
         blit_info.destination.w = drawablew;
         blit_info.destination.h = drawableh;
 

Some files were not shown because too many files changed in this diff