From 869a1a606689fe0b51d15d9caebc7da3aba2b408 Mon Sep 17 00:00:00 2001 From: Jesse Natalie Date: Fri, 11 Feb 2022 11:22:23 -0800 Subject: [PATCH] d3d12: Attempt screen reset during context create This will only work if all contexts have been destroyed. If the app attempts to re-create one context, while another outstanding context exists and is still in the removed state, then the screen is not recovered and the new context will fail to create. Reviewed-by: Bill Kristiansen Part-of: --- src/gallium/drivers/d3d12/d3d12_context.cpp | 8 ++++ .../drivers/d3d12/d3d12_dxcore_screen.cpp | 46 +++++++++++------- .../drivers/d3d12/d3d12_dxgi_screen.cpp | 47 ++++++++++++------- src/gallium/drivers/d3d12/d3d12_screen.cpp | 4 +- src/gallium/drivers/d3d12/d3d12_screen.h | 5 +- 5 files changed, 75 insertions(+), 35 deletions(-) diff --git a/src/gallium/drivers/d3d12/d3d12_context.cpp b/src/gallium/drivers/d3d12/d3d12_context.cpp index 26191519f67..8a11d9d51ca 100644 --- a/src/gallium/drivers/d3d12/d3d12_context.cpp +++ b/src/gallium/drivers/d3d12/d3d12_context.cpp @@ -2379,6 +2379,14 @@ struct pipe_context * d3d12_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) { struct d3d12_screen *screen = d3d12_screen(pscreen); + if (FAILED(screen->dev->GetDeviceRemovedReason())) { + /* Attempt recovery, but this may fail */ + screen->deinit(screen); + if (!screen->init(screen)) { + debug_printf("D3D12: failed to reset screen\n"); + return nullptr; + } + } struct d3d12_context *ctx = CALLOC_STRUCT(d3d12_context); if (!ctx) diff --git a/src/gallium/drivers/d3d12/d3d12_dxcore_screen.cpp b/src/gallium/drivers/d3d12/d3d12_dxcore_screen.cpp index d0e1c7b9435..b12f2f4b3b1 100644 --- a/src/gallium/drivers/d3d12/d3d12_dxcore_screen.cpp +++ b/src/gallium/drivers/d3d12/d3d12_dxcore_screen.cpp @@ -166,27 +166,23 @@ d3d12_destroy_dxcore_screen(struct pipe_screen *pscreen) d3d12_destroy_screen(screen); } -struct pipe_screen * -d3d12_create_dxcore_screen(struct sw_winsys *winsys, LUID *adapter_luid) +static bool +d3d12_init_dxcore_screen(struct d3d12_screen *dscreen) { - struct d3d12_dxcore_screen *screen = CALLOC_STRUCT(d3d12_dxcore_screen); - if (!screen) - return nullptr; - - d3d12_init_screen_base(&screen->base, winsys); - screen->base.base.destroy = d3d12_destroy_dxcore_screen; + struct d3d12_dxcore_screen *screen = d3d12_dxcore_screen(dscreen); screen->factory = get_dxcore_factory(); - if (!screen->factory) { - d3d12_destroy_dxcore_screen(&screen->base.base); - return nullptr; - } + if (!screen->factory) + return false; + + LUID *adapter_luid = &dscreen->adapter_luid; + if (adapter_luid->HighPart == 0 && adapter_luid->LowPart == 0) + adapter_luid = nullptr; screen->adapter = choose_dxcore_adapter(screen->factory, adapter_luid); if (!screen->adapter) { debug_printf("D3D12: no suitable adapter\n"); - d3d12_destroy_dxcore_screen(&screen->base.base); - return nullptr; + return false; } DXCoreHardwareID hardware_ids = {}; @@ -200,8 +196,7 @@ d3d12_create_dxcore_screen(struct sw_winsys *winsys, LUID *adapter_luid) sizeof(screen->description), screen->description))) { debug_printf("D3D12: failed to retrieve adapter description\n"); - d3d12_destroy_dxcore_screen(&screen->base.base); - return nullptr; + return false; } screen->base.vendor_id = hardware_ids.vendorID; @@ -211,6 +206,25 @@ d3d12_create_dxcore_screen(struct sw_winsys *winsys, LUID *adapter_luid) if (!d3d12_init_screen(&screen->base, screen->adapter)) { debug_printf("D3D12: failed to initialize DXCore screen\n"); + return false; + } + + return true; +} + +struct pipe_screen * +d3d12_create_dxcore_screen(struct sw_winsys *winsys, LUID *adapter_luid) +{ + struct d3d12_dxcore_screen *screen = CALLOC_STRUCT(d3d12_dxcore_screen); + if (!screen) + return nullptr; + + d3d12_init_screen_base(&screen->base, winsys, adapter_luid); + screen->base.base.destroy = d3d12_destroy_dxcore_screen; + screen->base.init = d3d12_init_dxcore_screen; + screen->base.deinit = d3d12_deinit_dxcore_screen; + + if (!d3d12_init_dxcore_screen(&screen->base)) { d3d12_destroy_dxcore_screen(&screen->base.base); return nullptr; } diff --git a/src/gallium/drivers/d3d12/d3d12_dxgi_screen.cpp b/src/gallium/drivers/d3d12/d3d12_dxgi_screen.cpp index ff9987c2b5e..ef6a8fe2f99 100644 --- a/src/gallium/drivers/d3d12/d3d12_dxgi_screen.cpp +++ b/src/gallium/drivers/d3d12/d3d12_dxgi_screen.cpp @@ -147,34 +147,28 @@ d3d12_destroy_dxgi_screen(struct pipe_screen *pscreen) d3d12_destroy_screen(screen); } -struct pipe_screen * -d3d12_create_dxgi_screen(struct sw_winsys *winsys, LUID *adapter_luid) +static bool +d3d12_init_dxgi_screen(struct d3d12_screen *dscreen) { - struct d3d12_dxgi_screen *screen = CALLOC_STRUCT(d3d12_dxgi_screen); - if (!screen) - return nullptr; - - d3d12_init_screen_base(&screen->base, winsys); - screen->base.base.destroy = d3d12_destroy_dxgi_screen; - + struct d3d12_dxgi_screen *screen = d3d12_dxgi_screen(dscreen); screen->factory = get_dxgi_factory(); - if (!screen->factory) { - FREE(screen); - return nullptr; - } + if (!screen->factory) + return false; + + LUID *adapter_luid = &dscreen->adapter_luid; + if (adapter_luid->HighPart == 0 && adapter_luid->LowPart == 0) + adapter_luid = nullptr; screen->adapter = choose_dxgi_adapter(screen->factory, adapter_luid); if (!screen->adapter) { debug_printf("D3D12: no suitable adapter\n"); - d3d12_destroy_dxgi_screen(&screen->base.base); - return nullptr; + return false; } DXGI_ADAPTER_DESC1 adapter_desc = {}; if (FAILED(screen->adapter->GetDesc1(&adapter_desc))) { debug_printf("D3D12: failed to retrieve adapter description\n"); - d3d12_destroy_dxgi_screen(&screen->base.base); - return nullptr; + return false; } LARGE_INTEGER driver_version; @@ -193,6 +187,25 @@ d3d12_create_dxgi_screen(struct sw_winsys *winsys, LUID *adapter_luid) if (!d3d12_init_screen(&screen->base, screen->adapter)) { debug_printf("D3D12: failed to initialize DXGI screen\n"); + return false; + } + + return true; +} + +struct pipe_screen * +d3d12_create_dxgi_screen(struct sw_winsys *winsys, LUID *adapter_luid) +{ + struct d3d12_dxgi_screen *screen = CALLOC_STRUCT(d3d12_dxgi_screen); + if (!screen) + return nullptr; + + d3d12_init_screen_base(&screen->base, winsys, adapter_luid); + screen->base.base.destroy = d3d12_destroy_dxgi_screen; + screen->base.init = d3d12_init_dxgi_screen; + screen->base.deinit = d3d12_deinit_dxgi_screen; + + if (!d3d12_init_dxgi_screen(&screen->base)) { d3d12_destroy_dxgi_screen(&screen->base.base); return nullptr; } diff --git a/src/gallium/drivers/d3d12/d3d12_screen.cpp b/src/gallium/drivers/d3d12/d3d12_screen.cpp index 60f4681eb2d..a20a48f2704 100644 --- a/src/gallium/drivers/d3d12/d3d12_screen.cpp +++ b/src/gallium/drivers/d3d12/d3d12_screen.cpp @@ -1098,11 +1098,13 @@ d3d12_init_null_rtv(struct d3d12_screen *screen) } void -d3d12_init_screen_base(struct d3d12_screen *screen, struct sw_winsys *winsys) +d3d12_init_screen_base(struct d3d12_screen *screen, struct sw_winsys *winsys, LUID *adapter_luid) { d3d12_debug = debug_get_option_d3d12_debug(); screen->winsys = winsys; + if (adapter_luid) + screen->adapter_luid = *adapter_luid; mtx_init(&screen->descriptor_pool_mutex, mtx_plain); mtx_init(&screen->submit_mutex, mtx_plain); diff --git a/src/gallium/drivers/d3d12/d3d12_screen.h b/src/gallium/drivers/d3d12/d3d12_screen.h index 9cf012fd861..cb4575986e0 100644 --- a/src/gallium/drivers/d3d12/d3d12_screen.h +++ b/src/gallium/drivers/d3d12/d3d12_screen.h @@ -64,9 +64,12 @@ struct d3d12_memory_info { struct d3d12_screen { struct pipe_screen base; struct sw_winsys *winsys; + LUID adapter_luid; ID3D12Device3 *dev; ID3D12CommandQueue *cmdqueue; + bool (*init)(struct d3d12_screen *screen); + void (*deinit)(struct d3d12_screen *screen); void (*get_memory_info)(struct d3d12_screen *screen, struct d3d12_memory_info *output); mtx_t submit_mutex; @@ -150,7 +153,7 @@ d3d12_dxcore_screen(struct d3d12_screen *screen) } void -d3d12_init_screen_base(struct d3d12_screen *screen, struct sw_winsys *winsys); +d3d12_init_screen_base(struct d3d12_screen *screen, struct sw_winsys *winsys, LUID *adapter_luid); bool d3d12_init_screen(struct d3d12_screen *screen, IUnknown *adapter);