Mesa (master): d3d12: Refactor screen to abstract DXGI details

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Dec 16 16:42:47 UTC 2020


Module: Mesa
Branch: master
Commit: 50fab5da93ad05817f8bc33abba759cc0cb3d0ef
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=50fab5da93ad05817f8bc33abba759cc0cb3d0ef

Author: Jesse Natalie <jenatali at microsoft.com>
Date:   Tue Dec  8 12:14:40 2020 -0800

d3d12: Refactor screen to abstract DXGI details

The next commit will add an alternative that can be dropped in instead.

Reviewed-by: Erik Faye-Lund <erik.faye-lund at collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7937>

---

 src/gallium/drivers/d3d12/d3d12_dxgi_screen.cpp    | 148 +++++++++++++++++++++
 src/gallium/drivers/d3d12/d3d12_public.h           |   2 +-
 src/gallium/drivers/d3d12/d3d12_screen.cpp         | 120 ++---------------
 src/gallium/drivers/d3d12/d3d12_screen.h           |  23 +++-
 src/gallium/drivers/d3d12/meson.build              |   1 +
 .../winsys/d3d12/wgl/d3d12_wgl_framebuffer.cpp     |   4 +-
 src/gallium/winsys/d3d12/wgl/d3d12_wgl_winsys.c    |   2 +-
 7 files changed, 181 insertions(+), 119 deletions(-)

diff --git a/src/gallium/drivers/d3d12/d3d12_dxgi_screen.cpp b/src/gallium/drivers/d3d12/d3d12_dxgi_screen.cpp
new file mode 100644
index 00000000000..f0abd401aef
--- /dev/null
+++ b/src/gallium/drivers/d3d12/d3d12_dxgi_screen.cpp
@@ -0,0 +1,148 @@
+/*
+ * Copyright © Microsoft Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "d3d12_screen.h"
+#include "d3d12_public.h"
+
+#include "util/debug.h"
+#include "util/u_memory.h"
+
+#include <dxgi1_4.h>
+
+static IDXGIFactory4 *
+get_dxgi_factory()
+{
+   static const GUID IID_IDXGIFactory4 = {
+      0x1bc6ea02, 0xef36, 0x464f,
+      { 0xbf, 0x0c, 0x21, 0xca, 0x39, 0xe5, 0x16, 0x8a }
+   };
+
+   typedef HRESULT(WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory);
+   PFN_CREATE_DXGI_FACTORY CreateDXGIFactory;
+
+   HMODULE hDXGIMod = LoadLibrary("DXGI.DLL");
+   if (!hDXGIMod) {
+      debug_printf("D3D12: failed to load DXGI.DLL\n");
+      return NULL;
+   }
+
+   CreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY)GetProcAddress(hDXGIMod, "CreateDXGIFactory");
+   if (!CreateDXGIFactory) {
+      debug_printf("D3D12: failed to load CreateDXGIFactory from DXGI.DLL\n");
+      return NULL;
+   }
+
+   IDXGIFactory4 *factory = NULL;
+   HRESULT hr = CreateDXGIFactory(IID_IDXGIFactory4, (void **)&factory);
+   if (FAILED(hr)) {
+      debug_printf("D3D12: CreateDXGIFactory failed: %08x\n", hr);
+      return NULL;
+   }
+
+   return factory;
+}
+
+static IDXGIAdapter1 *
+choose_dxgi_adapter(IDXGIFactory4 *factory, LUID *adapter)
+{
+   IDXGIAdapter1 *ret;
+   if (adapter) {
+      if (SUCCEEDED(factory->EnumAdapterByLuid(*adapter,
+                                               __uuidof(IDXGIAdapter1),
+                                               (void**)&ret)))
+         return ret;
+      debug_printf("D3D12: requested adapter missing, falling back to auto-detection...\n");
+   }
+
+   bool want_warp = env_var_as_boolean("LIBGL_ALWAYS_SOFTWARE", false);
+   if (want_warp) {
+      if (SUCCEEDED(factory->EnumWarpAdapter(__uuidof(IDXGIAdapter1),
+                                             (void**)&ret)))
+         return ret;
+      debug_printf("D3D12: failed to enum warp adapter\n");
+      return NULL;
+   }
+
+   // The first adapter is the default
+   if (SUCCEEDED(factory->EnumAdapters1(0, &ret)))
+      return ret;
+
+   return NULL;
+}
+
+static const char *
+dxgi_get_name(struct pipe_screen *screen)
+{
+   struct d3d12_dxgi_screen *dxgi_screen = d3d12_dxgi_screen(d3d12_screen(screen));
+   static char buf[1000];
+   if (dxgi_screen->description[0] == L'\0')
+      return "D3D12 (Unknown)";
+
+   snprintf(buf, sizeof(buf), "D3D12 (%S)", dxgi_screen->description);
+   return buf;
+}
+
+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;
+
+   screen->factory = get_dxgi_factory();
+   if (!screen->factory) {
+      FREE(screen);
+      return nullptr;
+   }
+
+   screen->adapter = choose_dxgi_adapter(screen->factory, adapter_luid);
+   if (!screen->adapter) {
+      debug_printf("D3D12: no suitable adapter\n");
+      FREE(screen);
+      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);
+      return nullptr;
+   }
+
+   screen->base.vendor_id = adapter_desc.VendorId;
+   // Note: memory sizes in bytes, but stored in size_t, so may be capped at 4GB.
+   // In that case, adding before conversion to MB can easily overflow.
+   screen->base.memory_size_megabytes = (adapter_desc.DedicatedVideoMemory >> 20) +
+                                        (adapter_desc.DedicatedSystemMemory >> 20) +
+                                        (adapter_desc.SharedSystemMemory >> 20);
+   wcsncpy(screen->description, adapter_desc.Description, ARRAY_SIZE(screen->description));
+   screen->base.base.get_name = dxgi_get_name;
+
+   if (!d3d12_init_screen(&screen->base, winsys, screen->adapter)) {
+      debug_printf("D3D12: failed to initialize DXGI screen\n");
+      FREE(screen);
+      return nullptr;
+   }
+
+   return &screen->base.base;
+}
diff --git a/src/gallium/drivers/d3d12/d3d12_public.h b/src/gallium/drivers/d3d12/d3d12_public.h
index bd485b3a6c4..8f3f3dbf130 100644
--- a/src/gallium/drivers/d3d12/d3d12_public.h
+++ b/src/gallium/drivers/d3d12/d3d12_public.h
@@ -32,7 +32,7 @@ extern "C" {
 #endif
 
 struct pipe_screen *
-d3d12_create_screen(struct sw_winsys *winsys, LUID *adapter_luid);
+d3d12_create_dxgi_screen(struct sw_winsys *winsys, LUID *adapter_luid);
 
 #ifdef __cplusplus
 }
diff --git a/src/gallium/drivers/d3d12/d3d12_screen.cpp b/src/gallium/drivers/d3d12/d3d12_screen.cpp
index e85fc7c8acc..f8dcb80a830 100644
--- a/src/gallium/drivers/d3d12/d3d12_screen.cpp
+++ b/src/gallium/drivers/d3d12/d3d12_screen.cpp
@@ -29,7 +29,6 @@
 #include "d3d12_debug.h"
 #include "d3d12_fence.h"
 #include "d3d12_format.h"
-#include "d3d12_public.h"
 #include "d3d12_resource.h"
 #include "d3d12_nir_passes.h"
 
@@ -42,7 +41,6 @@
 #include "nir.h"
 #include "frontend/sw_winsys.h"
 
-#include <dxgi1_4.h>
 #include <directx/d3d12sdklayers.h>
 
 static const struct debug_named_value
@@ -81,7 +79,7 @@ d3d12_get_device_vendor(struct pipe_screen *pscreen)
 {
    struct d3d12_screen* screen = d3d12_screen(pscreen);
 
-   switch (screen->adapter_desc.VendorId) {
+   switch (screen->vendor_id) {
    case HW_VENDOR_MICROSOFT:
       return "Microsoft";
    case HW_VENDOR_AMD:
@@ -95,29 +93,12 @@ d3d12_get_device_vendor(struct pipe_screen *pscreen)
    }
 }
 
-static const char *
-d3d12_get_name(struct pipe_screen *pscreen)
-{
-   struct d3d12_screen* screen = d3d12_screen(pscreen);
-
-   if (screen->adapter_desc.Description[0] == '\0')
-      return "D3D12 (Unknown)";
-
-   static char buf[1000];
-   snprintf(buf, sizeof(buf), "D3D12 (%S)", screen->adapter_desc.Description);
-   return buf;
-}
-
 static int
 d3d12_get_video_mem(struct pipe_screen *pscreen)
 {
    struct d3d12_screen* screen = d3d12_screen(pscreen);
 
-   // Note: memory sizes in bytes, but stored in size_t, so may be capped at 4GB.
-   // In that case, adding before conversion to MB can easily overflow.
-   return (screen->adapter_desc.DedicatedVideoMemory >> 20) +
-          (screen->adapter_desc.DedicatedSystemMemory >> 20) +
-          (screen->adapter_desc.SharedSystemMemory >> 20);
+   return screen->memory_size_megabytes;
 }
 
 static int
@@ -702,69 +683,8 @@ enable_gpu_validation()
       debug3->SetEnableGPUBasedValidation(true);
 }
 
-static IDXGIFactory4 *
-get_dxgi_factory()
-{
-   static const GUID IID_IDXGIFactory4 = {
-      0x1bc6ea02, 0xef36, 0x464f,
-      { 0xbf, 0x0c, 0x21, 0xca, 0x39, 0xe5, 0x16, 0x8a }
-   };
-
-   typedef HRESULT(WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory);
-   PFN_CREATE_DXGI_FACTORY CreateDXGIFactory;
-
-   HMODULE hDXGIMod = LoadLibrary("DXGI.DLL");
-   if (!hDXGIMod) {
-      debug_printf("D3D12: failed to load DXGI.DLL\n");
-      return NULL;
-   }
-
-   CreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY)GetProcAddress(hDXGIMod, "CreateDXGIFactory");
-   if (!CreateDXGIFactory) {
-      debug_printf("D3D12: failed to load CreateDXGIFactory from DXGI.DLL\n");
-      return NULL;
-   }
-
-   IDXGIFactory4 *factory = NULL;
-   HRESULT hr = CreateDXGIFactory(IID_IDXGIFactory4, (void **)&factory);
-   if (FAILED(hr)) {
-      debug_printf("D3D12: CreateDXGIFactory failed: %08x\n", hr);
-      return NULL;
-   }
-
-   return factory;
-}
-
-static IDXGIAdapter1 *
-choose_adapter(IDXGIFactory4 *factory, LUID *adapter)
-{
-   IDXGIAdapter1 *ret;
-   if (adapter) {
-      if (SUCCEEDED(factory->EnumAdapterByLuid(*adapter,
-                                               __uuidof(IDXGIAdapter1),
-                                               (void**)&ret)))
-         return ret;
-      debug_printf("D3D12: requested adapter missing, falling back to auto-detection...\n");
-   }
-
-   bool want_warp = env_var_as_boolean("LIBGL_ALWAYS_SOFTWARE", false);
-   if (want_warp) {
-      if (SUCCEEDED(factory->EnumWarpAdapter(__uuidof(IDXGIAdapter1),
-                                             (void**)&ret)))
-         return ret;
-      debug_printf("D3D12: failed to enum warp adapter\n");
-      return NULL;
-   }
-
-   // The first adapter is the default
-   if (SUCCEEDED(factory->EnumAdapters1(0, &ret)))
-      return ret;
-
-   return NULL;
-}
-
 static ID3D12Device *
-create_device(IDXGIAdapter1 *adapter)
+create_device(IUnknown *adapter)
 {
    typedef HRESULT(WINAPI *PFN_D3D12CREATEDEVICE)(IUnknown*, D3D_FEATURE_LEVEL, REFIID, void**);
    typedef HRESULT(WINAPI *PFN_D3D12ENABLEEXPERIMENTALFEATURES)(UINT, const IID*, void*, UINT*);
@@ -800,7 +720,7 @@ create_device(IDXGIAdapter1 *adapter)
 static bool
 can_attribute_at_vertex(struct d3d12_screen *screen)
 {
-   switch (screen->adapter_desc.VendorId)  {
+   switch (screen->vendor_id)  {
    case HW_VENDOR_MICROSOFT:
       return true;
    default:
@@ -808,18 +728,13 @@ can_attribute_at_vertex(struct d3d12_screen *screen)
    }
 }
 
-struct pipe_screen *
-d3d12_create_screen(struct sw_winsys *winsys, LUID *adapter_luid)
+bool
+d3d12_init_screen(struct d3d12_screen *screen, struct sw_winsys *winsys, IUnknown *adapter)
 {
-   struct d3d12_screen *screen = CALLOC_STRUCT(d3d12_screen);
-   if (!screen)
-      return NULL;
-
    d3d12_debug = debug_get_option_d3d12_debug();
 
    screen->winsys = winsys;
 
-   screen->base.get_name = d3d12_get_name;
    screen->base.get_vendor = d3d12_get_vendor;
    screen->base.get_device_vendor = d3d12_get_device_vendor;
    screen->base.get_param = d3d12_get_param;
@@ -839,24 +754,8 @@ d3d12_create_screen(struct sw_winsys *winsys, LUID *adapter_luid)
    if (d3d12_debug & D3D12_DEBUG_GPU_VALIDATOR)
       enable_gpu_validation();
 
-   screen->factory = get_dxgi_factory();
-   if (!screen->factory) {
-      debug_printf("D3D12: failed to create DXGI factory\n");
-      goto failed;
-   }
-
-   screen->adapter = choose_adapter(screen->factory, adapter_luid);
-   if (!screen->adapter) {
-      debug_printf("D3D12: no suitable adapter\n");
-      return NULL;
-   }
+   screen->dev = create_device(adapter);
 
-   if (FAILED(screen->adapter->GetDesc1(&screen->adapter_desc))) {
-      debug_printf("D3D12: failed to retrieve adapter description\n");
-      return NULL;
-   }
-
-   screen->dev = create_device(screen->adapter);
    if (!screen->dev) {
       debug_printf("D3D12: failed to create device\n");
       goto failed;
@@ -963,9 +862,8 @@ d3d12_create_screen(struct sw_winsys *winsys, LUID *adapter_luid)
                                                       &desc);
 
    screen->have_load_at_vertex = can_attribute_at_vertex(screen);
-   return &screen->base;
+   return true;
 
 failed:
-   FREE(screen);
-   return NULL;
+   return false;
 }
diff --git a/src/gallium/drivers/d3d12/d3d12_screen.h b/src/gallium/drivers/d3d12/d3d12_screen.h
index 76e43d4f199..5910b538ae2 100644
--- a/src/gallium/drivers/d3d12/d3d12_screen.h
+++ b/src/gallium/drivers/d3d12/d3d12_screen.h
@@ -30,7 +30,6 @@
 
 #define D3D12_IGNORE_SDK_LAYERS
 #include <directx/d3d12.h>
-#include <dxgi1_4.h>
 
 struct pb_manager;
 
@@ -38,8 +37,6 @@ struct d3d12_screen {
    struct pipe_screen base;
    struct sw_winsys *winsys;
 
-   IDXGIFactory4 *factory;
-   IDXGIAdapter1 *adapter;
    ID3D12Device *dev;
    ID3D12CommandQueue *cmdqueue;
 
@@ -57,7 +54,8 @@ struct d3d12_screen {
    D3D12_FEATURE_DATA_D3D12_OPTIONS4 opts4;
 
    /* description */
-   DXGI_ADAPTER_DESC1 adapter_desc;
+   uint32_t vendor_id;
+   uint64_t memory_size_megabytes;
    double timestamp_multiplier;
    bool have_load_at_vertex;
 };
@@ -68,4 +66,21 @@ d3d12_screen(struct pipe_screen *pipe)
    return (struct d3d12_screen *)pipe;
 }
 
+struct d3d12_dxgi_screen {
+   struct d3d12_screen base;
+
+   struct IDXGIFactory4 *factory;
+   struct IDXGIAdapter1 *adapter;
+   wchar_t description[128];
+};
+
+static inline struct d3d12_dxgi_screen *
+d3d12_dxgi_screen(struct d3d12_screen *screen)
+{
+   return (struct d3d12_dxgi_screen *)screen;
+}
+
+bool
+d3d12_init_screen(struct d3d12_screen *screen, struct sw_winsys *winsys, IUnknown *adapter);
+
 #endif
diff --git a/src/gallium/drivers/d3d12/meson.build b/src/gallium/drivers/d3d12/meson.build
index 44a968121f3..56cb4741df1 100644
--- a/src/gallium/drivers/d3d12/meson.build
+++ b/src/gallium/drivers/d3d12/meson.build
@@ -27,6 +27,7 @@ files_libd3d12 = files(
   'd3d12_context.cpp',
   'd3d12_descriptor_pool.cpp',
   'd3d12_draw.cpp',
+  'd3d12_dxgi_screen.cpp',
   'd3d12_fence.cpp',
   'd3d12_format.c',
   'd3d12_gs_variant.cpp',
diff --git a/src/gallium/winsys/d3d12/wgl/d3d12_wgl_framebuffer.cpp b/src/gallium/winsys/d3d12/wgl/d3d12_wgl_framebuffer.cpp
index 9ac8b80b2e6..9409beb9ee6 100644
--- a/src/gallium/winsys/d3d12/wgl/d3d12_wgl_framebuffer.cpp
+++ b/src/gallium/winsys/d3d12/wgl/d3d12_wgl_framebuffer.cpp
@@ -71,7 +71,7 @@ d3d12_wgl_framebuffer_resize(stw_winsys_framebuffer *fb,
                              pipe_resource *templ)
 {
    struct d3d12_wgl_framebuffer *framebuffer = d3d12_wgl_framebuffer(fb);
-   struct d3d12_screen *screen = framebuffer->screen;
+   struct d3d12_dxgi_screen *screen = d3d12_dxgi_screen(framebuffer->screen);
 
    DXGI_SWAP_CHAIN_DESC1 desc = {};
    desc.BufferCount = 2;
@@ -88,7 +88,7 @@ d3d12_wgl_framebuffer_resize(stw_winsys_framebuffer *fb,
    if (!framebuffer->swapchain) {
       ComPtr<IDXGISwapChain1> swapchain1;
       if (FAILED(screen->factory->CreateSwapChainForHwnd(
-         screen->cmdqueue,
+         screen->base.cmdqueue,
          framebuffer->window,
          &desc,
          nullptr,
diff --git a/src/gallium/winsys/d3d12/wgl/d3d12_wgl_winsys.c b/src/gallium/winsys/d3d12/wgl/d3d12_wgl_winsys.c
index 7a193cdef68..65a7be01bbb 100644
--- a/src/gallium/winsys/d3d12/wgl/d3d12_wgl_winsys.c
+++ b/src/gallium/winsys/d3d12/wgl/d3d12_wgl_winsys.c
@@ -38,7 +38,7 @@ d3d12_wgl_create_screen(struct sw_winsys *winsys, HDC hDC)
       stw_dev->callbacks.pfnGetAdapterLuid(hDC, &local_luid);
       adapter_luid = &local_luid;
    }
-   return d3d12_create_screen(winsys, adapter_luid);
+   return d3d12_create_dxgi_screen(winsys, adapter_luid);
 }
 
 void



More information about the mesa-commit mailing list