GS: Adjust default renderer based on vendor and feature level.

Vulkan default:
Nvidia Maxwell gen2 and higher.

OpenGL default:
From Fermi to Mawell gen1.

Everything else Direct3D11.
This commit is contained in:
lightningterror 2022-05-03 10:39:51 +02:00
parent 4efa845580
commit 8091b6bc1b
3 changed files with 72 additions and 33 deletions

View File

@ -194,16 +194,14 @@ GSRendererType GSUtil::GetPreferredRenderer()
// Mac: Prefer Metal hardware.
return GSRendererType::Metal;
#elif defined(_WIN32)
if (D3D::ShouldPreferRenderer() == D3D::Renderer::Vulkan)
return GSRendererType::VK;
#if defined(ENABLE_OPENGL)
// Windows: Prefer GL if available.
if (D3D::ShouldPreferD3D())
return GSRendererType::DX11;
else
else if (D3D::ShouldPreferRenderer() == D3D::Renderer::OpenGL)
return GSRendererType::OGL;
#else
// DX11 is always available, otherwise.
return GSRendererType::DX11;
#endif
else
return GSRendererType::DX11;
#else
// Linux: Prefer GL/Vulkan, whatever is available.
#if defined(ENABLE_OPENGL)

View File

@ -69,44 +69,68 @@ namespace D3D
return adapter;
}
bool IsNvidia(IDXGIAdapter1* adapter)
u8 Vendor()
{
auto factory = CreateFactory(false);
auto adapter = GetAdapterFromIndex(factory.get(), 0);
ASSERT(adapter);
DXGI_ADAPTER_DESC1 desc = {};
if (FAILED(adapter->GetDesc1(&desc)))
{
fprintf(stderr, "D3D: failed to get the adapter description\n");
return false;
return VendorID::Unknown;
}
// NV magic number
return desc.VendorId == 0x10DE;
switch (desc.VendorId)
{
case 0x10DE:
return VendorID::Nvidia;
case 0x1002:
case 0x1022:
return VendorID::AMD;
case 0x163C:
case 0x8086:
case 0x8087:
return VendorID::Intel;
default:
return VendorID::Unknown;
}
}
bool SupportsFeatureLevel11(IDXGIAdapter1* adapter)
{
ASSERT(adapter);
D3D_FEATURE_LEVEL feature_level;
static const D3D_FEATURE_LEVEL check[] = { D3D_FEATURE_LEVEL_11_0 };
const HRESULT hr = D3D11CreateDevice(
adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, 0,
check, std::size(check), D3D11_SDK_VERSION, nullptr, &feature_level, nullptr
);
if (FAILED(hr))
return false;
return feature_level == D3D_FEATURE_LEVEL_11_0;
}
bool ShouldPreferD3D()
u8 ShouldPreferRenderer()
{
auto factory = CreateFactory(false);
auto adapter = GetAdapterFromIndex(factory.get(), 0);
return !(IsNvidia(adapter.get()) && SupportsFeatureLevel11(adapter.get()));
ASSERT(adapter);
D3D_FEATURE_LEVEL feature_level;
static const D3D_FEATURE_LEVEL check[] = {
D3D_FEATURE_LEVEL_12_1,
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
};
const HRESULT hr = D3D11CreateDevice(
adapter.get(), D3D_DRIVER_TYPE_UNKNOWN, nullptr, 0,
std::data(check), std::size(check), D3D11_SDK_VERSION, nullptr, &feature_level, nullptr
);
if (FAILED(hr))
return Renderer::Default;
if (Vendor() == VendorID::Nvidia)
{
if (feature_level == D3D_FEATURE_LEVEL_12_1)
return Renderer::Vulkan;
else if (feature_level == D3D_FEATURE_LEVEL_11_0)
return Renderer::OpenGL;
}
// Default is D3D11
return Renderer::Default;
}
}

View File

@ -32,6 +32,23 @@ namespace D3D
// this is sort of a legacy thing that doesn't have much to do with d3d (just the easiest way)
// checks to see if the adapter at 0 is NV and thus we should prefer OpenGL
bool IsNvidia(IDXGIAdapter1* adapter);
bool ShouldPreferD3D();
enum VendorID
{
Unknown,
Nvidia,
AMD,
Intel
};
enum Renderer
{
Default,
OpenGL,
Vulkan,
Direct3D11,
Direct3D12
};
u8 Vendor();
u8 ShouldPreferRenderer();
};