gdk: Render/GPU can call SuspendX, document when to call SuspendComplete

This commit is contained in:
Ethan Lee
2026-02-25 09:20:25 -05:00
parent 49a8b4229b
commit 5770e013c2
4 changed files with 76 additions and 4 deletions

View File

@@ -291,9 +291,8 @@ static void DrawSprites(SDL_Renderer * renderer, SDL_Texture * sprite)
SDL_RenderPresent(renderer);
}
static void loop()
static void update()
{
int i;
SDL_Event event;
/* Check for events */
@@ -310,13 +309,31 @@ static void loop()
SDLTest_CommonEvent(state, &event, &done);
#endif
}
fillerup();
}
static void draw()
{
int i;
for (i = 0; i < state->num_windows; ++i) {
if (state->windows[i] == NULL) {
continue;
}
DrawSprites(state->renderers[i], sprites[i]);
}
fillerup();
}
static bool SDLCALL GDKEventWatch(void* userdata, SDL_Event* event)
{
bool *suppressdraw = (bool *)userdata;
SDL_assert(suppressdraw != NULL);
if (event->type == SDL_EVENT_DID_ENTER_BACKGROUND) {
*suppressdraw = true;
SDL_GDKSuspendComplete();
} else if (event->type == SDL_EVENT_WILL_ENTER_FOREGROUND) {
*suppressdraw = false;
}
return true;
}
int main(int argc, char *argv[])
@@ -324,6 +341,7 @@ int main(int argc, char *argv[])
int i;
const char *icon = "icon.bmp";
char *soundname = NULL;
bool suppressdraw = false;
/* Initialize parameters */
num_sprites = NUM_SPRITES;
@@ -390,6 +408,9 @@ int main(int argc, char *argv[])
quit(2);
}
/* By this point the renderers are made, so we can now add this watcher */
SDL_AddEventWatch(GDKEventWatch, &suppressdraw);
/* Create the windows, initialize the renderers, and load the textures */
sprites =
(SDL_Texture **) SDL_malloc(state->num_windows * sizeof(*sprites));
@@ -441,7 +462,10 @@ int main(int argc, char *argv[])
AddUserSilent();
while (!done) {
loop();
update();
if (!suppressdraw) {
draw();
}
}
quit(0);

View File

@@ -664,6 +664,13 @@ extern SDL_DECLSPEC void SDLCALL SDL_UnregisterApp(void);
/**
* Callback from the application to let the suspend continue.
*
* When using SDL_Render or SDL_GPU, this function should be called _after_
* creating the `SDL_Renderer` or `SDL_GPUDevice`; this allows the timing of the
* D3D12 command queue suspension to execute in the correct order.
*
* If you're writing your own D3D12 renderer, this should be called after
* calling `ID3D12CommandQueue::SuspendX`.
*
* This function is only needed for Xbox GDK support; all other platforms will
* do nothing and set an "unsupported" error message.
*

View File

@@ -562,10 +562,26 @@ static HRESULT D3D12_IssueBatch(D3D12_RenderData *data)
return result;
}
#ifdef SDL_PLATFORM_GDK
static bool SDLCALL D3D12_GDKEventFilter(void* userdata, SDL_Event* event)
{
D3D12_RenderData *data = (D3D12_RenderData *)userdata;
if (event->type == SDL_EVENT_DID_ENTER_BACKGROUND) {
data->commandQueue->SuspendX(0);
} else if (event->type == SDL_EVENT_WILL_ENTER_FOREGROUND) {
data->commandQueue->ResumeX();
}
return true;
}
#endif
static void D3D12_DestroyRenderer(SDL_Renderer *renderer)
{
D3D12_RenderData *data = (D3D12_RenderData *)renderer->internal;
if (data) {
#ifdef SDL_PLATFORM_GDK
SDL_RemoveEventWatch(D3D12_GDKEventFilter, data);
#endif
D3D12_WaitForGPU(data);
D3D12_ReleaseAll(renderer);
SDL_free(data);
@@ -1112,6 +1128,10 @@ static HRESULT D3D12_CreateDeviceResources(SDL_Renderer *renderer)
SDL_SetPointerProperty(props, SDL_PROP_RENDERER_D3D12_DEVICE_POINTER, data->d3dDevice);
SDL_SetPointerProperty(props, SDL_PROP_RENDERER_D3D12_COMMAND_QUEUE_POINTER, data->commandQueue);
#ifdef SDL_PLATFORM_GDK
SDL_AddEventWatch(D3D12_GDKEventFilter, data);
#endif
done:
D3D_SAFE_RELEASE(d3dDevice);
return result;

View File

@@ -1562,6 +1562,20 @@ static void GPU_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
texture->internal = NULL;
}
#ifdef SDL_PLATFORM_GDK
static bool SDLCALL GPU_GDKEventFilter(void *userdata, SDL_Event *event)
{
GPU_RenderData *data = (GPU_RenderData *)userdata;
SDL_assert(!data->external_device);
if (event->type == SDL_EVENT_DID_ENTER_BACKGROUND) {
SDL_GDKSuspendGPU(data->device);
} else if (event->type == SDL_EVENT_WILL_ENTER_FOREGROUND) {
SDL_GDKResumeGPU(data->device);
}
return true;
}
#endif
static void GPU_DestroyRenderer(SDL_Renderer *renderer)
{
GPU_RenderData *data = (GPU_RenderData *)renderer->internal;
@@ -1595,6 +1609,9 @@ static void GPU_DestroyRenderer(SDL_Renderer *renderer)
if (data->device) {
GPU_ReleaseShaders(&data->shaders, data->device);
if (!data->external_device) {
#ifdef SDL_PLATFORM_GDK
SDL_RemoveEventWatch(GPU_GDKEventFilter, data);
#endif
SDL_DestroyGPUDevice(data->device);
}
}
@@ -1758,6 +1775,10 @@ static bool GPU_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_P
if (!data->device) {
return false;
}
#ifdef SDL_PLATFORM_GDK
SDL_AddEventWatch(GPU_GDKEventFilter, data);
#endif
}
if (!GPU_InitShaders(&data->shaders, data->device)) {