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