Mesa (main): d3d12: Plug screen leaks

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


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

Author: Jesse Natalie <jenatali at microsoft.com>
Date:   Fri Feb 11 09:17:48 2022 -0800

d3d12: Plug screen leaks

This also breaks screen init/deinit into two parts. The first part of
creation cannot fail, and is not repeatable. The second part of creation
can fail, and is repeatable, to be used for reset recovery.

Reviewed-by: Bill Kristiansen <billkris at microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15002>

---

 src/gallium/drivers/d3d12/d3d12_dxcore_screen.cpp |  36 ++++++-
 src/gallium/drivers/d3d12/d3d12_dxgi_screen.cpp   |  34 +++++-
 src/gallium/drivers/d3d12/d3d12_residency.cpp     |   9 ++
 src/gallium/drivers/d3d12/d3d12_residency.h       |   3 +
 src/gallium/drivers/d3d12/d3d12_screen.cpp        | 124 ++++++++++++++++------
 src/gallium/drivers/d3d12/d3d12_screen.h          |  11 +-
 6 files changed, 175 insertions(+), 42 deletions(-)

diff --git a/src/gallium/drivers/d3d12/d3d12_dxcore_screen.cpp b/src/gallium/drivers/d3d12/d3d12_dxcore_screen.cpp
index 8f10e5273f7..d0e1c7b9435 100644
--- a/src/gallium/drivers/d3d12/d3d12_dxcore_screen.cpp
+++ b/src/gallium/drivers/d3d12/d3d12_dxcore_screen.cpp
@@ -143,6 +143,29 @@ dxcore_get_memory_info(struct d3d12_screen *screen, struct d3d12_memory_info *ou
    output->usage = local_info.currentUsage + nonlocal_info.currentUsage;
 }
 
+static void
+d3d12_deinit_dxcore_screen(struct d3d12_screen *dscreen)
+{
+   d3d12_deinit_screen(dscreen);
+   struct d3d12_dxcore_screen *screen = d3d12_dxcore_screen(dscreen);
+   if (screen->adapter) {
+      screen->adapter->Release();
+      screen->adapter = nullptr;
+   }
+   if (screen->factory) {
+      screen->factory->Release();
+      screen->factory = nullptr;
+   }
+}
+
+static void
+d3d12_destroy_dxcore_screen(struct pipe_screen *pscreen)
+{
+   struct d3d12_screen *screen = d3d12_screen(pscreen);
+   d3d12_deinit_dxcore_screen(screen);
+   d3d12_destroy_screen(screen);
+}
+
 struct pipe_screen *
 d3d12_create_dxcore_screen(struct sw_winsys *winsys, LUID *adapter_luid)
 {
@@ -150,16 +173,19 @@ d3d12_create_dxcore_screen(struct sw_winsys *winsys, LUID *adapter_luid)
    if (!screen)
       return nullptr;
 
+   d3d12_init_screen_base(&screen->base, winsys);
+   screen->base.base.destroy = d3d12_destroy_dxcore_screen;
+
    screen->factory = get_dxcore_factory();
    if (!screen->factory) {
-      FREE(screen);
+      d3d12_destroy_dxcore_screen(&screen->base.base);
       return nullptr;
    }
 
    screen->adapter = choose_dxcore_adapter(screen->factory, adapter_luid);
    if (!screen->adapter) {
       debug_printf("D3D12: no suitable adapter\n");
-      FREE(screen);
+      d3d12_destroy_dxcore_screen(&screen->base.base);
       return nullptr;
    }
 
@@ -174,7 +200,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");
-      FREE(screen);
+      d3d12_destroy_dxcore_screen(&screen->base.base);
       return nullptr;
    }
 
@@ -183,9 +209,9 @@ d3d12_create_dxcore_screen(struct sw_winsys *winsys, LUID *adapter_luid)
    screen->base.base.get_name = dxcore_get_name;
    screen->base.get_memory_info = dxcore_get_memory_info;
 
-   if (!d3d12_init_screen(&screen->base, winsys, screen->adapter)) {
+   if (!d3d12_init_screen(&screen->base, screen->adapter)) {
       debug_printf("D3D12: failed to initialize DXCore screen\n");
-      FREE(screen);
+      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 344adb638bd..ff9987c2b5e 100644
--- a/src/gallium/drivers/d3d12/d3d12_dxgi_screen.cpp
+++ b/src/gallium/drivers/d3d12/d3d12_dxgi_screen.cpp
@@ -124,6 +124,29 @@ dxgi_get_memory_info(struct d3d12_screen *screen, struct d3d12_memory_info *outp
    output->usage = local_info.CurrentUsage + nonlocal_info.CurrentUsage;
 }
 
+static void
+d3d12_deinit_dxgi_screen(struct d3d12_screen *dscreen)
+{
+   d3d12_deinit_screen(dscreen);
+   struct d3d12_dxgi_screen *screen = d3d12_dxgi_screen(dscreen);
+   if (screen->adapter) {
+      screen->adapter->Release();
+      screen->adapter = nullptr;
+   }
+   if (screen->factory) {
+      screen->factory->Release();
+      screen->factory = nullptr;
+   }
+}
+
+static void
+d3d12_destroy_dxgi_screen(struct pipe_screen *pscreen)
+{
+   struct d3d12_screen *screen = d3d12_screen(pscreen);
+   d3d12_deinit_dxgi_screen(screen);
+   d3d12_destroy_screen(screen);
+}
+
 struct pipe_screen *
 d3d12_create_dxgi_screen(struct sw_winsys *winsys, LUID *adapter_luid)
 {
@@ -131,6 +154,9 @@ d3d12_create_dxgi_screen(struct sw_winsys *winsys, LUID *adapter_luid)
    if (!screen)
       return nullptr;
 
+   d3d12_init_screen_base(&screen->base, winsys);
+   screen->base.base.destroy = d3d12_destroy_dxgi_screen;
+
    screen->factory = get_dxgi_factory();
    if (!screen->factory) {
       FREE(screen);
@@ -140,14 +166,14 @@ d3d12_create_dxgi_screen(struct sw_winsys *winsys, LUID *adapter_luid)
    screen->adapter = choose_dxgi_adapter(screen->factory, adapter_luid);
    if (!screen->adapter) {
       debug_printf("D3D12: no suitable adapter\n");
-      FREE(screen);
+      d3d12_destroy_dxgi_screen(&screen->base.base);
       return nullptr;
    }
 
    DXGI_ADAPTER_DESC1 adapter_desc = {};
    if (FAILED(screen->adapter->GetDesc1(&adapter_desc))) {
       debug_printf("D3D12: failed to retrieve adapter description\n");
-      FREE(screen);
+      d3d12_destroy_dxgi_screen(&screen->base.base);
       return nullptr;
    }
 
@@ -165,9 +191,9 @@ d3d12_create_dxgi_screen(struct sw_winsys *winsys, LUID *adapter_luid)
    screen->base.base.get_name = dxgi_get_name;
    screen->base.get_memory_info = dxgi_get_memory_info;
 
-   if (!d3d12_init_screen(&screen->base, winsys, screen->adapter)) {
+   if (!d3d12_init_screen(&screen->base, screen->adapter)) {
       debug_printf("D3D12: failed to initialize DXGI screen\n");
-      FREE(screen);
+      d3d12_destroy_dxgi_screen(&screen->base.base);
       return nullptr;
    }
 
diff --git a/src/gallium/drivers/d3d12/d3d12_residency.cpp b/src/gallium/drivers/d3d12/d3d12_residency.cpp
index 75654c5b610..b3b0934e7ee 100644
--- a/src/gallium/drivers/d3d12/d3d12_residency.cpp
+++ b/src/gallium/drivers/d3d12/d3d12_residency.cpp
@@ -249,3 +249,12 @@ d3d12_init_residency(struct d3d12_screen *screen)
 
    return true;
 }
+
+void
+d3d12_deinit_residency(struct d3d12_screen *screen)
+{
+   if (screen->residency_fence) {
+      screen->residency_fence->Release();
+      screen->residency_fence = nullptr;
+   }
+}
diff --git a/src/gallium/drivers/d3d12/d3d12_residency.h b/src/gallium/drivers/d3d12/d3d12_residency.h
index af84e65e682..2413aaedaca 100644
--- a/src/gallium/drivers/d3d12/d3d12_residency.h
+++ b/src/gallium/drivers/d3d12/d3d12_residency.h
@@ -31,3 +31,6 @@ d3d12_process_batch_residency(struct d3d12_screen *screen, struct d3d12_batch *b
 
 bool
 d3d12_init_residency(struct d3d12_screen *screen);
+
+void
+d3d12_deinit_residency(struct d3d12_screen *screen);
diff --git a/src/gallium/drivers/d3d12/d3d12_screen.cpp b/src/gallium/drivers/d3d12/d3d12_screen.cpp
index 8b6896d7d97..60f4681eb2d 100644
--- a/src/gallium/drivers/d3d12/d3d12_screen.cpp
+++ b/src/gallium/drivers/d3d12/d3d12_screen.cpp
@@ -694,18 +694,56 @@ d3d12_is_format_supported(struct pipe_screen *pscreen,
    return true;
 }
 
-static void
-d3d12_destroy_screen(struct pipe_screen *pscreen)
+void
+d3d12_deinit_screen(struct d3d12_screen *screen)
+{
+   if (screen->rtv_pool) {
+      d3d12_descriptor_pool_free(screen->rtv_pool);
+      screen->rtv_pool = nullptr;
+   }
+   if (screen->dsv_pool) {
+      d3d12_descriptor_pool_free(screen->dsv_pool);
+      screen->dsv_pool = nullptr;
+   }
+   if (screen->view_pool) {
+      d3d12_descriptor_pool_free(screen->view_pool);
+      screen->view_pool = nullptr;
+   }
+   if (screen->readback_slab_bufmgr) {
+      screen->readback_slab_bufmgr->destroy(screen->readback_slab_bufmgr);
+      screen->readback_slab_bufmgr = nullptr;
+   }
+   if (screen->slab_bufmgr) {
+      screen->slab_bufmgr->destroy(screen->slab_bufmgr);
+      screen->slab_bufmgr = nullptr;
+   }
+   if (screen->cache_bufmgr) {
+      screen->cache_bufmgr->destroy(screen->cache_bufmgr);
+      screen->cache_bufmgr = nullptr;
+   }
+   if (screen->bufmgr) {
+      screen->bufmgr->destroy(screen->bufmgr);
+      screen->bufmgr = nullptr;
+   }
+   d3d12_deinit_residency(screen);
+   if (screen->fence) {
+      screen->fence->Release();
+      screen->fence = nullptr;
+   }
+   if (screen->cmdqueue) {
+      screen->cmdqueue->Release();
+      screen->cmdqueue = nullptr;
+   }
+   if (screen->dev) {
+      screen->dev->Release();
+      screen->dev = nullptr;
+   }
+}
+
+void
+d3d12_destroy_screen(struct d3d12_screen *screen)
 {
-   struct d3d12_screen *screen = d3d12_screen(pscreen);
    slab_destroy_parent(&screen->transfer_pool);
-   d3d12_descriptor_pool_free(screen->rtv_pool);
-   d3d12_descriptor_pool_free(screen->dsv_pool);
-   d3d12_descriptor_pool_free(screen->view_pool);
-   screen->readback_slab_bufmgr->destroy(screen->readback_slab_bufmgr);
-   screen->slab_bufmgr->destroy(screen->slab_bufmgr);
-   screen->cache_bufmgr->destroy(screen->cache_bufmgr);
-   screen->bufmgr->destroy(screen->bufmgr);
    mtx_destroy(&screen->submit_mutex);
    mtx_destroy(&screen->descriptor_pool_mutex);
    FREE(screen);
@@ -788,8 +826,10 @@ static void
 enable_d3d12_debug_layer()
 {
    ID3D12Debug *debug = get_debug_interface();
-   if (debug)
+   if (debug) {
       debug->EnableDebugLayer();
+      debug->Release();
+   }
 }
 
 static void
@@ -797,9 +837,13 @@ enable_gpu_validation()
 {
    ID3D12Debug *debug = get_debug_interface();
    ID3D12Debug3 *debug3;
-   if (debug &&
-       SUCCEEDED(debug->QueryInterface(IID_PPV_ARGS(&debug3))))
-      debug3->SetEnableGPUBasedValidation(true);
+   if (debug) {
+      if (SUCCEEDED(debug->QueryInterface(IID_PPV_ARGS(&debug3)))) {
+         debug3->SetEnableGPUBasedValidation(true);
+         debug3->Release();
+      }
+      debug->Release();
+   }
 }
 
 static ID3D12Device3 *
@@ -1053,8 +1097,8 @@ d3d12_init_null_rtv(struct d3d12_screen *screen)
    screen->dev->CreateRenderTargetView(NULL, &rtv, screen->null_rtv.cpu_handle);
 }
 
-bool
-d3d12_init_screen(struct d3d12_screen *screen, struct sw_winsys *winsys, IUnknown *adapter)
+void
+d3d12_init_screen_base(struct d3d12_screen *screen, struct sw_winsys *winsys)
 {
    d3d12_debug = debug_get_option_d3d12_debug();
 
@@ -1072,7 +1116,12 @@ d3d12_init_screen(struct d3d12_screen *screen, struct sw_winsys *winsys, IUnknow
    screen->base.get_compiler_options = d3d12_get_compiler_options;
    screen->base.context_create = d3d12_context_create;
    screen->base.flush_frontbuffer = d3d12_flush_frontbuffer;
-   screen->base.destroy = d3d12_destroy_screen;
+}
+
+bool
+d3d12_init_screen(struct d3d12_screen *screen, IUnknown *adapter)
+{
+   assert(screen->base.destroy != nullptr);
 
 #ifndef DEBUG
    if (d3d12_debug & D3D12_DEBUG_DEBUG_LAYER)
@@ -1086,7 +1135,7 @@ d3d12_init_screen(struct d3d12_screen *screen, struct sw_winsys *winsys, IUnknow
 
    if (!screen->dev) {
       debug_printf("D3D12: failed to create device\n");
-      goto failed;
+      return false;
    }
 
    ID3D12InfoQueue *info_queue;
@@ -1107,37 +1156,38 @@ d3d12_init_screen(struct d3d12_screen *screen, struct sw_winsys *winsys, IUnknow
       NewFilter.DenyList.pIDList = msg_ids;
 
       info_queue->PushStorageFilter(&NewFilter);
+      info_queue->Release();
    }
 
    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS,
                                                &screen->opts,
                                                sizeof(screen->opts)))) {
       debug_printf("D3D12: failed to get device options\n");
-      goto failed;
+      return false;
    }
    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS1,
                                                &screen->opts1,
                                                sizeof(screen->opts1)))) {
       debug_printf("D3D12: failed to get device options\n");
-      goto failed;
+      return false;
    }
    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS2,
                                                &screen->opts2,
                                                sizeof(screen->opts2)))) {
       debug_printf("D3D12: failed to get device options\n");
-      goto failed;
+      return false;
    }
    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS3,
                                                &screen->opts3,
                                                sizeof(screen->opts3)))) {
       debug_printf("D3D12: failed to get device options\n");
-      goto failed;
+      return false;
    }
    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS4,
                                                &screen->opts4,
                                                sizeof(screen->opts4)))) {
       debug_printf("D3D12: failed to get device options\n");
-      goto failed;
+      return false;
    }
 
    screen->architecture.NodeIndex = 0;
@@ -1145,7 +1195,7 @@ d3d12_init_screen(struct d3d12_screen *screen, struct sw_winsys *winsys, IUnknow
                                                &screen->architecture,
                                                sizeof(screen->architecture)))) {
       debug_printf("D3D12: failed to get device architecture\n");
-      goto failed;
+      return false;
    }
 
    D3D12_FEATURE_DATA_FEATURE_LEVELS feature_levels;
@@ -1161,7 +1211,7 @@ d3d12_init_screen(struct d3d12_screen *screen, struct sw_winsys *winsys, IUnknow
                                                &feature_levels,
                                                sizeof(feature_levels)))) {
       debug_printf("D3D12: failed to get device feature levels\n");
-      goto failed;
+      return false;
    }
    screen->max_feature_level = feature_levels.MaxSupportedFeatureLevel;
 
@@ -1175,19 +1225,19 @@ d3d12_init_screen(struct d3d12_screen *screen, struct sw_winsys *winsys, IUnknow
    if (SUCCEEDED(screen->dev->QueryInterface(&device9))) {
       if (FAILED(device9->CreateCommandQueue1(&queue_desc, OpenGLOn12CreatorID,
                                               IID_PPV_ARGS(&screen->cmdqueue))))
-         goto failed;
+         return false;
       device9->Release();
    } else {
       if (FAILED(screen->dev->CreateCommandQueue(&queue_desc,
                                                  IID_PPV_ARGS(&screen->cmdqueue))))
-         goto failed;
+         return false;
    }
 
    if (FAILED(screen->dev->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&screen->fence))))
-      goto failed;
+      return false;
 
    if (!d3d12_init_residency(screen))
-      goto failed;
+      return false;
 
    UINT64 timestamp_freq;
    if (FAILED(screen->cmdqueue->GetTimestampFrequency(&timestamp_freq)))
@@ -1203,16 +1253,27 @@ d3d12_init_screen(struct d3d12_screen *screen, struct sw_winsys *winsys, IUnknow
    desc.usage = (pb_usage_flags)(PB_USAGE_CPU_WRITE | PB_USAGE_GPU_READ);
 
    screen->bufmgr = d3d12_bufmgr_create(screen);
+   if (!screen->bufmgr)
+      return false;
+
    screen->cache_bufmgr = pb_cache_manager_create(screen->bufmgr, 0xfffff, 2, 0, 512 * 1024 * 1024);
+   if (!screen->cache_bufmgr)
+      return false;
+
    screen->slab_bufmgr = pb_slab_range_manager_create(screen->cache_bufmgr, 16,
                                                       D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
                                                       D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
                                                       &desc);
+   if (!screen->slab_bufmgr)
+      return false;
+
    desc.usage = (pb_usage_flags)(PB_USAGE_CPU_READ_WRITE | PB_USAGE_GPU_WRITE);
    screen->readback_slab_bufmgr = pb_slab_range_manager_create(screen->cache_bufmgr, 16,
                                                                D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
                                                                D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
                                                                &desc);
+   if (!screen->readback_slab_bufmgr)
+      return false;
 
    screen->rtv_pool = d3d12_descriptor_pool_new(screen,
                                                 D3D12_DESCRIPTOR_HEAP_TYPE_RTV,
@@ -1223,6 +1284,8 @@ d3d12_init_screen(struct d3d12_screen *screen, struct sw_winsys *winsys, IUnknow
    screen->view_pool = d3d12_descriptor_pool_new(screen,
                                                  D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
                                                  1024);
+   if (!screen->rtv_pool || !screen->dsv_pool || !screen->view_pool)
+      return false;
 
    d3d12_init_null_srvs(screen);
    d3d12_init_null_uavs(screen);
@@ -1252,7 +1315,4 @@ d3d12_init_screen(struct d3d12_screen *screen, struct sw_winsys *winsys, IUnknow
       screen->nir_options.lower_doubles_options = (nir_lower_doubles_options)~0;
 
    return true;
-
-failed:
-   return false;
 }
diff --git a/src/gallium/drivers/d3d12/d3d12_screen.h b/src/gallium/drivers/d3d12/d3d12_screen.h
index a97e7360b33..9cf012fd861 100644
--- a/src/gallium/drivers/d3d12/d3d12_screen.h
+++ b/src/gallium/drivers/d3d12/d3d12_screen.h
@@ -149,7 +149,16 @@ d3d12_dxcore_screen(struct d3d12_screen *screen)
    return (struct d3d12_dxcore_screen *)screen;
 }
 
+void
+d3d12_init_screen_base(struct d3d12_screen *screen, struct sw_winsys *winsys);
+
 bool
-d3d12_init_screen(struct d3d12_screen *screen, struct sw_winsys *winsys, IUnknown *adapter);
+d3d12_init_screen(struct d3d12_screen *screen, IUnknown *adapter);
+
+void
+d3d12_deinit_screen(struct d3d12_screen *screen);
+
+void
+d3d12_destroy_screen(struct d3d12_screen *screen);
 
 #endif



More information about the mesa-commit mailing list