Mesa (main): d3d12: Attempt screen reset during context create

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Apr 28 20:01:21 UTC 2022


Module: Mesa
Branch: main
Commit: 869a1a606689fe0b51d15d9caebc7da3aba2b408
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=869a1a606689fe0b51d15d9caebc7da3aba2b408

Author: Jesse Natalie <jenatali at microsoft.com>
Date:   Fri Feb 11 11:22:23 2022 -0800

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 <billkris at microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15002>

---

 src/gallium/drivers/d3d12/d3d12_context.cpp       |  8 ++++
 src/gallium/drivers/d3d12/d3d12_dxcore_screen.cpp | 46 ++++++++++++++--------
 src/gallium/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);



More information about the mesa-commit mailing list