mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-01 01:00:10 +01:00
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@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7937>
This commit is contained in:
parent
bc5f69faee
commit
50fab5da93
7 changed files with 181 additions and 119 deletions
148
src/gallium/drivers/d3d12/d3d12_dxgi_screen.cpp
Normal file
148
src/gallium/drivers/d3d12/d3d12_dxgi_screen.cpp
Normal file
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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->dev = create_device(adapter);
|
||||
|
||||
screen->adapter = choose_adapter(screen->factory, adapter_luid);
|
||||
if (!screen->adapter) {
|
||||
debug_printf("D3D12: no suitable adapter\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue