mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-04 15:40:11 +01:00
d3d12: Support device factories in addition to global device creation
As explained in a comment, a device factory allows modification of state like debug layer enablement without touching global state / triggering device removal on a singleton device, and can even create devices that are not singletons if the driver supports that. Reviewed-by: Sil Vilerino <sivileri@microsoft.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18305>
This commit is contained in:
parent
cb9a58c103
commit
d21f0cb5b9
1 changed files with 70 additions and 29 deletions
|
|
@ -780,8 +780,14 @@ d3d12_flush_frontbuffer(struct pipe_screen * pscreen,
|
|||
}
|
||||
|
||||
static ID3D12Debug *
|
||||
get_debug_interface(util_dl_library *d3d12_mod)
|
||||
get_debug_interface(util_dl_library *d3d12_mod, ID3D12DeviceFactory *factory)
|
||||
{
|
||||
ID3D12Debug *debug = nullptr;
|
||||
if (factory) {
|
||||
factory->GetConfigurationInterface(CLSID_D3D12Debug, IID_PPV_ARGS(&debug));
|
||||
return debug;
|
||||
}
|
||||
|
||||
typedef HRESULT(WINAPI *PFN_D3D12_GET_DEBUG_INTERFACE)(REFIID riid, void **ppFactory);
|
||||
PFN_D3D12_GET_DEBUG_INTERFACE D3D12GetDebugInterface;
|
||||
|
||||
|
|
@ -791,7 +797,6 @@ get_debug_interface(util_dl_library *d3d12_mod)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ID3D12Debug *debug;
|
||||
if (FAILED(D3D12GetDebugInterface(IID_PPV_ARGS(&debug)))) {
|
||||
debug_printf("D3D12: D3D12GetDebugInterface failed\n");
|
||||
return NULL;
|
||||
|
|
@ -801,9 +806,9 @@ get_debug_interface(util_dl_library *d3d12_mod)
|
|||
}
|
||||
|
||||
static void
|
||||
enable_d3d12_debug_layer(util_dl_library *d3d12_mod)
|
||||
enable_d3d12_debug_layer(util_dl_library *d3d12_mod, ID3D12DeviceFactory *factory)
|
||||
{
|
||||
ID3D12Debug *debug = get_debug_interface(d3d12_mod);
|
||||
ID3D12Debug *debug = get_debug_interface(d3d12_mod, factory);
|
||||
if (debug) {
|
||||
debug->EnableDebugLayer();
|
||||
debug->Release();
|
||||
|
|
@ -811,9 +816,9 @@ enable_d3d12_debug_layer(util_dl_library *d3d12_mod)
|
|||
}
|
||||
|
||||
static void
|
||||
enable_gpu_validation(util_dl_library *d3d12_mod)
|
||||
enable_gpu_validation(util_dl_library *d3d12_mod, ID3D12DeviceFactory *factory)
|
||||
{
|
||||
ID3D12Debug *debug = get_debug_interface(d3d12_mod);
|
||||
ID3D12Debug *debug = get_debug_interface(d3d12_mod, factory);
|
||||
ID3D12Debug3 *debug3;
|
||||
if (debug) {
|
||||
if (SUCCEEDED(debug->QueryInterface(IID_PPV_ARGS(&debug3)))) {
|
||||
|
|
@ -825,37 +830,49 @@ enable_gpu_validation(util_dl_library *d3d12_mod)
|
|||
}
|
||||
|
||||
static ID3D12Device3 *
|
||||
create_device(util_dl_library *d3d12_mod, IUnknown *adapter)
|
||||
create_device(util_dl_library *d3d12_mod, IUnknown *adapter, ID3D12DeviceFactory *factory)
|
||||
{
|
||||
typedef HRESULT(WINAPI *PFN_D3D12CREATEDEVICE)(IUnknown*, D3D_FEATURE_LEVEL, REFIID, void**);
|
||||
typedef HRESULT(WINAPI *PFN_D3D12ENABLEEXPERIMENTALFEATURES)(UINT, const IID*, void*, UINT*);
|
||||
PFN_D3D12CREATEDEVICE D3D12CreateDevice;
|
||||
PFN_D3D12ENABLEEXPERIMENTALFEATURES D3D12EnableExperimentalFeatures;
|
||||
|
||||
#ifdef _WIN32
|
||||
if (d3d12_debug & D3D12_DEBUG_EXPERIMENTAL)
|
||||
#endif
|
||||
{
|
||||
D3D12EnableExperimentalFeatures = (PFN_D3D12ENABLEEXPERIMENTALFEATURES)util_dl_get_proc_address(d3d12_mod, "D3D12EnableExperimentalFeatures");
|
||||
if (FAILED(D3D12EnableExperimentalFeatures(1, &D3D12ExperimentalShaderModels, NULL, NULL))) {
|
||||
debug_printf("D3D12: failed to enable experimental shader models\n");
|
||||
return nullptr;
|
||||
if (factory) {
|
||||
if (FAILED(factory->EnableExperimentalFeatures(1, &D3D12ExperimentalShaderModels, nullptr, nullptr))) {
|
||||
debug_printf("D3D12: failed to enable experimental shader models\n");
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
typedef HRESULT(WINAPI *PFN_D3D12ENABLEEXPERIMENTALFEATURES)(UINT, const IID*, void*, UINT*);
|
||||
PFN_D3D12ENABLEEXPERIMENTALFEATURES D3D12EnableExperimentalFeatures =
|
||||
(PFN_D3D12ENABLEEXPERIMENTALFEATURES)util_dl_get_proc_address(d3d12_mod, "D3D12EnableExperimentalFeatures");
|
||||
|
||||
if (!D3D12EnableExperimentalFeatures ||
|
||||
FAILED(D3D12EnableExperimentalFeatures(1, &D3D12ExperimentalShaderModels, NULL, NULL))) {
|
||||
debug_printf("D3D12: failed to enable experimental shader models\n");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
D3D12CreateDevice = (PFN_D3D12CREATEDEVICE)util_dl_get_proc_address(d3d12_mod, "D3D12CreateDevice");
|
||||
if (!D3D12CreateDevice) {
|
||||
debug_printf("D3D12: failed to load D3D12CreateDevice from D3D12.DLL\n");
|
||||
return NULL;
|
||||
ID3D12Device3 *dev = nullptr;
|
||||
if (factory) {
|
||||
factory->SetFlags(D3D12_DEVICE_FACTORY_FLAG_ALLOW_RETURNING_EXISTING_DEVICE |
|
||||
D3D12_DEVICE_FACTORY_FLAG_ALLOW_RETURNING_INCOMPATIBLE_EXISTING_DEVICE);
|
||||
if (FAILED(factory->CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&dev))))
|
||||
debug_printf("D3D12: D3D12CreateDevice failed\n");
|
||||
} else {
|
||||
typedef HRESULT(WINAPI *PFN_D3D12CREATEDEVICE)(IUnknown*, D3D_FEATURE_LEVEL, REFIID, void**);
|
||||
PFN_D3D12CREATEDEVICE D3D12CreateDevice = (PFN_D3D12CREATEDEVICE)util_dl_get_proc_address(d3d12_mod, "D3D12CreateDevice");
|
||||
if (!D3D12CreateDevice) {
|
||||
debug_printf("D3D12: failed to load D3D12CreateDevice from D3D12.DLL\n");
|
||||
return NULL;
|
||||
}
|
||||
if (FAILED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&dev))))
|
||||
debug_printf("D3D12: D3D12CreateDevice failed\n");
|
||||
}
|
||||
|
||||
ID3D12Device3 *dev;
|
||||
if (SUCCEEDED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0,
|
||||
IID_PPV_ARGS(&dev))))
|
||||
return dev;
|
||||
|
||||
debug_printf("D3D12: D3D12CreateDevice failed\n");
|
||||
return NULL;
|
||||
return dev;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -1152,21 +1169,45 @@ d3d12_init_screen_base(struct d3d12_screen *screen, struct sw_winsys *winsys, LU
|
|||
return true;
|
||||
}
|
||||
|
||||
static ID3D12DeviceFactory *
|
||||
try_create_device_factory(util_dl_library *d3d12_mod)
|
||||
{
|
||||
/* A device factory allows us to isolate things like debug layer enablement from other callers,
|
||||
* and can potentially even refer to a different D3D12 redist implementation from others.
|
||||
*/
|
||||
ID3D12DeviceFactory *factory = nullptr;
|
||||
|
||||
typedef HRESULT(WINAPI *PFN_D3D12_GET_INTERFACE)(REFCLSID clsid, REFIID riid, void **ppFactory);
|
||||
PFN_D3D12_GET_INTERFACE D3D12GetInterface = (PFN_D3D12_GET_INTERFACE)util_dl_get_proc_address(d3d12_mod, "D3D12GetInterface");
|
||||
if (!D3D12GetInterface) {
|
||||
debug_printf("D3D12: Failed to retrieve D3D12GetInterface");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
(void)D3D12GetInterface(CLSID_D3D12DeviceFactory, IID_PPV_ARGS(&factory));
|
||||
return factory;
|
||||
}
|
||||
|
||||
bool
|
||||
d3d12_init_screen(struct d3d12_screen *screen, IUnknown *adapter)
|
||||
{
|
||||
assert(screen->base.destroy != nullptr);
|
||||
|
||||
ID3D12DeviceFactory *factory = try_create_device_factory(screen->d3d12_mod);
|
||||
|
||||
#ifndef DEBUG
|
||||
if (d3d12_debug & D3D12_DEBUG_DEBUG_LAYER)
|
||||
#endif
|
||||
enable_d3d12_debug_layer(screen->d3d12_mod);
|
||||
enable_d3d12_debug_layer(screen->d3d12_mod, factory);
|
||||
|
||||
if (d3d12_debug & D3D12_DEBUG_GPU_VALIDATOR)
|
||||
enable_gpu_validation(screen->d3d12_mod);
|
||||
enable_gpu_validation(screen->d3d12_mod, factory);
|
||||
|
||||
screen->dev = create_device(screen->d3d12_mod, adapter);
|
||||
screen->dev = create_device(screen->d3d12_mod, adapter, factory);
|
||||
|
||||
if (factory)
|
||||
factory->Release();
|
||||
|
||||
if (!screen->dev) {
|
||||
debug_printf("D3D12: failed to create device\n");
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue