Skip to content

Commit

Permalink
Fixed crashes handling D3D11/12 device lost in testsprite
Browse files Browse the repository at this point in the history
You can test this using "dxcap -forcetdr"
  • Loading branch information
slouken committed Oct 21, 2024
1 parent 86bd694 commit c761ec1
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 4 deletions.
19 changes: 17 additions & 2 deletions src/render/direct3d11/SDL_render_d3d11.c
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ static void D3D11_ReleaseAll(SDL_Renderer *renderer)
SAFE_RELEASE(data->blendModes[i].blendState);
}
SDL_free(data->blendModes);

data->blendModes = NULL;
data->blendModesCount = 0;
}
for (i = 0; i < SDL_arraysize(data->pixelShaders); ++i) {
Expand Down Expand Up @@ -993,12 +993,14 @@ static HRESULT D3D11_HandleDeviceLost(SDL_Renderer *renderer)
result = D3D11_CreateDeviceResources(renderer);
if (FAILED(result)) {
// D3D11_CreateDeviceResources will set the SDL error
D3D11_ReleaseAll(renderer);
return result;
}

result = D3D11_UpdateForWindowSizeChange(renderer);
if (FAILED(result)) {
// D3D11_UpdateForWindowSizeChange will set the SDL error
D3D11_ReleaseAll(renderer);
return result;
}

Expand Down Expand Up @@ -2395,6 +2397,10 @@ static bool D3D11_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd
D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->internal;
const int viewportRotation = D3D11_GetRotationForCurrentRenderTarget(renderer);

if (!rendererData->d3dDevice) {
return SDL_SetError("Device lost and couldn't be recovered");
}

if (rendererData->pixelSizeChanged) {
D3D11_UpdateForWindowSizeChange(renderer);
rendererData->pixelSizeChanged = false;
Expand Down Expand Up @@ -2613,6 +2619,10 @@ static bool D3D11_RenderPresent(SDL_Renderer *renderer)
HRESULT result;
DXGI_PRESENT_PARAMETERS parameters;

if (!data->d3dDevice) {
return SDL_SetError("Device lost and couldn't be recovered");
}

SDL_zero(parameters);

/* The application may optionally specify "dirty" or "scroll"
Expand All @@ -2634,10 +2644,15 @@ static bool D3D11_RenderPresent(SDL_Renderer *renderer)
* must recreate all device resources.
*/
if (result == DXGI_ERROR_DEVICE_REMOVED) {
D3D11_HandleDeviceLost(renderer);
if (SUCCEEDED(D3D11_HandleDeviceLost(renderer))) {
SDL_SetError("Present failed, device lost");
} else {
// Recovering from device lost failed, error is already set
}
} else if (result == DXGI_ERROR_INVALID_CALL) {
// We probably went through a fullscreen <-> windowed transition
D3D11_CreateWindowSizeDependentResources(renderer);
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain::Present"), result);
} else {
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain::Present"), result);
}
Expand Down
12 changes: 11 additions & 1 deletion src/render/direct3d12/SDL_render_d3d12.c
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,7 @@ static void D3D12_ReleaseAll(SDL_Renderer *renderer)
D3D_SAFE_RELEASE(data->pipelineStates[i].pipelineState);
}
SDL_free(data->pipelineStates);
data->pipelineStates = NULL;
data->pipelineStateCount = 0;
}

Expand Down Expand Up @@ -2738,6 +2739,10 @@ static bool D3D12_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *
D3D12_CPU_DESCRIPTOR_HANDLE *textureSampler;
D3D12_PixelShaderConstants constants;

if (!textureData) {
return SDL_SetError("Texture is not currently available");
}

D3D12_SetupShaderConstants(renderer, cmd, texture, &constants);

switch (textureData->scaleMode) {
Expand Down Expand Up @@ -3132,10 +3137,15 @@ static bool D3D12_RenderPresent(SDL_Renderer *renderer)
* must recreate all device resources.
*/
if (result == DXGI_ERROR_DEVICE_REMOVED) {
D3D12_HandleDeviceLost(renderer);
if (SUCCEEDED(D3D12_HandleDeviceLost(renderer))) {
SDL_SetError("Present failed, device lost");
} else {
// Recovering from device lost failed, error is already set
}
} else if (result == DXGI_ERROR_INVALID_CALL) {
// We probably went through a fullscreen <-> windowed transition
D3D12_CreateWindowSizeDependentResources(renderer);
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain::Present"), result);
} else {
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain::Present"), result);
}
Expand Down
8 changes: 7 additions & 1 deletion test/testsprite.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#define MAX_SPEED 1

static SDLTest_CommonState *state;
static const char *icon = "icon.bmp";
static int num_sprites;
static SDL_Texture **sprites;
static bool cycle_color;
Expand Down Expand Up @@ -56,6 +57,9 @@ static int LoadSprite(const char *file)

for (i = 0; i < state->num_windows; ++i) {
/* This does the SDL_LoadBMP step repeatedly, but that's OK for test code. */
if (sprites[i]) {
SDL_DestroyTexture(sprites[i]);
}
sprites[i] = LoadTexture(state->renderers[i], file, true, &w, &h);
sprite_w = (float)w;
sprite_h = (float)h;
Expand Down Expand Up @@ -390,7 +394,6 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
SDL_Rect safe_area;
int i;
Uint64 seed;
const char *icon = "icon.bmp";

/* Initialize parameters */
num_sprites = NUM_SPRITES;
Expand Down Expand Up @@ -553,6 +556,9 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])

SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_RENDER_DEVICE_RESET) {
LoadSprite(icon);
}
return SDLTest_CommonEventMainCallbacks(state, event);
}

Expand Down

0 comments on commit c761ec1

Please sign in to comment.