d3d12: Add mechanism for D3D12 Adapter Selection

This add a simple mechanism to select which GPU adapter the d3d12
driver should be using. A new environment variable is introduced.

MESA_D3D12_DEFAULT_ADAPTER_NAME

This represent a substring to search for in the GPU descrition,
for example "NVIDIA" or "INTEL", or "NVIDIA GeForce RTX 3090",
etc...

GPU are searched in order and the first one to include the substring
becomes a match. If no match is found, we default to the first
enumerated GPU.

Reviewed-by: Jesse Natalie <jenatali@microsoft.com>
Reviewed-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10710>
This commit is contained in:
Steve Pronovost 2021-04-25 11:20:46 -07:00 committed by Marge Bot
parent 108f34a165
commit 29e3a11d78
2 changed files with 59 additions and 8 deletions

View File

@ -47,3 +47,15 @@ environment variables:
.. _debug layer: https://docs.microsoft.com/en-us/windows/win32/direct3d12/understanding-the-d3d12-debug-layer
.. _GPU validator: https://docs.microsoft.com/en-us/windows/win32/direct3d12/using-d3d12-debug-layer-gpu-based-validation
Utilities
---------
Environment variables that control the behavior of the D3D12 driver.
.. envvar:: MESA_D3D12_DEFAULT_ADAPTER_NAME <string> ("")
Specifies a substring to search for when chosing a default adapter to run on.
The first adapter matching the substring is chosen. The substring is not
case sensitive.

View File

@ -60,20 +60,59 @@ get_dxcore_factory()
}
static IDXCoreAdapter *
choose_dxcore_adapter(IDXCoreAdapterFactory *factory, LUID *adapter)
choose_dxcore_adapter(IDXCoreAdapterFactory *factory, LUID *adapter_luid)
{
IDXCoreAdapter *ret;
if (adapter) {
if (SUCCEEDED(factory->GetAdapterByLuid(*adapter, &ret)))
return ret;
IDXCoreAdapter *adapter = nullptr;
if (adapter_luid) {
if (SUCCEEDED(factory->GetAdapterByLuid(*adapter_luid, &adapter)))
return adapter;
debug_printf("D3D12: requested adapter missing, falling back to auto-detection...\n");
}
// The first adapter is the default
IDXCoreAdapterList *list = nullptr;
if (SUCCEEDED(factory->CreateAdapterList(1, &DXCORE_ADAPTER_ATTRIBUTE_D3D12_GRAPHICS, &list))) {
if (list->GetAdapterCount() > 0 && SUCCEEDED(list->GetAdapter(0, &ret)))
return ret;
#ifndef _WIN32
// Pick the user selected adapter if any
char *adapter_name = getenv("MESA_D3D12_DEFAULT_ADAPTER_NAME");
if (adapter_name) {
for (unsigned i=0; i<list->GetAdapterCount(); i++) {
if (SUCCEEDED(list->GetAdapter(i, &adapter))) {
size_t desc_size;
if (!SUCCEEDED(adapter->GetPropertySize(DXCoreAdapterProperty::DriverDescription, &desc_size))) {
adapter->Release();
continue;
}
char *desc = (char*)malloc(desc_size);
if (!desc) {
adapter->Release();
continue;
}
if (!SUCCEEDED(adapter->GetProperty(DXCoreAdapterProperty::DriverDescription, desc_size, desc))) {
free(desc);
adapter->Release();
continue;
}
if (strcasestr(desc, adapter_name)) {
free(desc);
return adapter;
} else {
free(desc);
adapter->Release();
}
}
}
debug_printf("D3D12: Couldn't find an adapter containing the substring (%s)\n", adapter_name);
}
#endif
// No adapter specified or not found, pick 0 as the default
if (list->GetAdapterCount() > 0 && SUCCEEDED(list->GetAdapter(0, &adapter)))
return adapter;
}
return NULL;