mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-05-20 12:34:50 +08:00
GPU: More robust error reporting (#10958)
--------- Co-authored-by: Ethan Lee <flibitijibibo@gmail.com> Co-authored-by: Caleb Cornett <caleb.cornett@outlook.com>
This commit is contained in:
+33
-30
@@ -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,
|
||||
|
||||
@@ -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
@@ -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;
|
||||
return false;
|
||||
}
|
||||
if (w == NULL) {
|
||||
SDL_InvalidParamError("w");
|
||||
return NULL;
|
||||
}
|
||||
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,
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+180
-196
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
|
||||
+335
-347
File diff suppressed because it is too large
Load Diff
@@ -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 ***
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user