Add DriverVersion to GPUAdapter for checking on old GPU drivers
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Core/Types/Version.h"
|
||||
#include "Engine/Scripting/ScriptingObject.h"
|
||||
|
||||
// GPU vendors IDs
|
||||
@@ -56,6 +57,11 @@ public:
|
||||
/// </summary>
|
||||
API_PROPERTY() virtual String GetDescription() const = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the GPU driver version.
|
||||
/// </summary>
|
||||
API_PROPERTY() virtual Version GetDriverVersion() const = 0;
|
||||
|
||||
public:
|
||||
// Returns true if adapter's vendor is AMD.
|
||||
API_PROPERTY() FORCE_INLINE bool IsAMD() const
|
||||
|
||||
@@ -182,12 +182,12 @@ bool GraphicsService::Init()
|
||||
return true;
|
||||
}
|
||||
GPUDevice::Instance = device;
|
||||
LOG(Info,
|
||||
"Graphics Device created! Adapter: \'{0}\', Renderer: {1}, Shader Profile: {2}, Feature Level: {3}",
|
||||
device->GetAdapter()->GetDescription(),
|
||||
LOG(Info, "GPU Device created: {}", device->GetAdapter()->GetDescription());
|
||||
LOG(Info, "Renderer: {}, Shader Profile: {}, Feature Level: {}, Driver: {}",
|
||||
::ToString(device->GetRendererType()),
|
||||
::ToString(device->GetShaderProfile()),
|
||||
::ToString(device->GetFeatureLevel())
|
||||
::ToString(device->GetFeatureLevel()),
|
||||
device->GetAdapter()->GetDriverVersion().ToString()
|
||||
);
|
||||
|
||||
// Initialize
|
||||
|
||||
@@ -296,8 +296,6 @@ GPUDevice* GPUDeviceDX11::Create()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validate adapter
|
||||
if (!selectedAdapter.IsValid())
|
||||
{
|
||||
LOG(Error, "Failed to choose valid DirectX adapter!");
|
||||
@@ -427,7 +425,7 @@ bool GPUDeviceDX11::Init()
|
||||
|
||||
// Create DirectX device
|
||||
D3D_FEATURE_LEVEL createdFeatureLevel = static_cast<D3D_FEATURE_LEVEL>(0);
|
||||
auto targetFeatureLevel = GetD3DFeatureLevel();
|
||||
D3D_FEATURE_LEVEL targetFeatureLevel = _adapter->MaxFeatureLevel;
|
||||
VALIDATE_DIRECTX_CALL(D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, flags, &targetFeatureLevel, 1, D3D11_SDK_VERSION, &_device, &createdFeatureLevel, &_imContext));
|
||||
ASSERT(_device);
|
||||
ASSERT(_imContext);
|
||||
|
||||
@@ -198,17 +198,14 @@ GPUDevice* GPUDeviceDX12::Create()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validate adapter
|
||||
if (!selectedAdapter.IsValid())
|
||||
{
|
||||
LOG(Error, "Failed to choose valid DirectX adapter!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Check if selected adapter does not support DirectX 12
|
||||
if (!selectedAdapter.IsSupportingDX12())
|
||||
if (selectedAdapter.MaxFeatureLevel < D3D_FEATURE_LEVEL_12_0)
|
||||
{
|
||||
LOG(Error, "Failed to choose valid DirectX adapter!");
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -14,25 +14,18 @@
|
||||
class GPUAdapterDX : public GPUAdapter
|
||||
{
|
||||
public:
|
||||
|
||||
int32 Index = INVALID_INDEX;
|
||||
D3D_FEATURE_LEVEL MaxFeatureLevel;
|
||||
DXGI_ADAPTER_DESC Description;
|
||||
Version DriverVersion = Version(0, 0);
|
||||
|
||||
public:
|
||||
void GetDriverVersion();
|
||||
|
||||
// Returns true if adapter is supporting DirectX 12.
|
||||
FORCE_INLINE bool IsSupportingDX12() const
|
||||
{
|
||||
#if GRAPHICS_API_DIRECTX12
|
||||
return MaxFeatureLevel >= D3D_FEATURE_LEVEL_12_0;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
private:
|
||||
void SetDriverVersion(Version& ver);
|
||||
|
||||
public:
|
||||
|
||||
// [GPUAdapter]
|
||||
bool IsValid() const override
|
||||
{
|
||||
@@ -50,6 +43,10 @@ public:
|
||||
{
|
||||
return Description.Description;
|
||||
}
|
||||
Version GetDriverVersion() const override
|
||||
{
|
||||
return DriverVersion;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -36,17 +36,10 @@ protected:
|
||||
: GPUDevice(type, profile)
|
||||
, _adapter(adapter)
|
||||
{
|
||||
adapter->GetDriverVersion();
|
||||
}
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Gets DirectX device feature level.
|
||||
/// </summary>
|
||||
FORCE_INLINE D3D_FEATURE_LEVEL GetD3DFeatureLevel() const
|
||||
{
|
||||
return _adapter->MaxFeatureLevel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The video outputs.
|
||||
/// </summary>
|
||||
|
||||
@@ -3,11 +3,24 @@
|
||||
#if GRAPHICS_API_DIRECTX11 || GRAPHICS_API_DIRECTX12
|
||||
|
||||
#include "RenderToolsDX.h"
|
||||
#include "GPUAdapterDX.h"
|
||||
#include "GPUDeviceDX.h"
|
||||
#include "Engine/Core/Types/DateTime.h"
|
||||
#include "Engine/Core/Types/StringBuilder.h"
|
||||
#include "Engine/Graphics/GPUDevice.h"
|
||||
#include "IncludeDirectXHeaders.h"
|
||||
#include <winerror.h>
|
||||
|
||||
#define GPU_DRIVER_DETECTION_WIN32_REGISTRY (PLATFORM_WINDOWS)
|
||||
#define GPU_DRIVER_DETECTION_WIN32_SETUPAPI (PLATFORM_WINDOWS)
|
||||
|
||||
#if GPU_DRIVER_DETECTION_WIN32_SETUPAPI
|
||||
#define _SETUPAPI_VER WINVER
|
||||
typedef void* LPCDLGTEMPLATE;
|
||||
#include <SetupAPI.h>
|
||||
#pragma comment(lib, "SetupAPI.lib")
|
||||
#endif
|
||||
|
||||
namespace Windows
|
||||
{
|
||||
typedef struct _devicemodeW
|
||||
@@ -304,7 +317,7 @@ void FormatD3DErrorString(HRESULT errorCode, StringBuilder& sb, HRESULT& removed
|
||||
|
||||
default:
|
||||
sb.AppendFormat(TEXT("0x{0:x}"), static_cast<unsigned int>(errorCode));
|
||||
break;
|
||||
break;
|
||||
}
|
||||
#undef D3DERR
|
||||
|
||||
@@ -439,6 +452,140 @@ LPCSTR RenderToolsDX::GetVertexInputSemantic(VertexElement::Types type, UINT& se
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
void GPUAdapterDX::GetDriverVersion()
|
||||
{
|
||||
#if GPU_DRIVER_DETECTION_WIN32_REGISTRY
|
||||
{
|
||||
// Reference: https://github.com/GameTechDev/gpudetect/blob/master/GPUDetect.cpp
|
||||
|
||||
// Fetch registry data
|
||||
HKEY dxKeyHandle = nullptr;
|
||||
DWORD numOfAdapters = 0;
|
||||
LSTATUS returnCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\DirectX"), 0, KEY_READ, &dxKeyHandle);
|
||||
if (returnCode == S_OK)
|
||||
{
|
||||
// Find all sub keys
|
||||
DWORD subKeyMaxLength = 0;
|
||||
returnCode = RegQueryInfoKeyW(dxKeyHandle, 0, 0, 0, &numOfAdapters, &subKeyMaxLength, 0, 0, 0, 0, 0, 0);
|
||||
if (returnCode == S_OK && subKeyMaxLength < 100)
|
||||
{
|
||||
subKeyMaxLength += 1;
|
||||
uint64_t driverVersionRaw = 0;
|
||||
TCHAR subKeyName[100];
|
||||
for (DWORD i = 0; i < numOfAdapters; i++)
|
||||
{
|
||||
DWORD subKeyLength = subKeyMaxLength;
|
||||
returnCode = RegEnumKeyExW(dxKeyHandle, i, subKeyName, &subKeyLength, 0, 0, 0, 0);
|
||||
if (returnCode == S_OK)
|
||||
{
|
||||
LUID adapterLUID = {};
|
||||
DWORD qwordSize = sizeof(uint64_t);
|
||||
returnCode = RegGetValueW(dxKeyHandle, subKeyName, TEXT("AdapterLuid"), RRF_RT_QWORD, 0, &adapterLUID, &qwordSize);
|
||||
if (returnCode == S_OK && adapterLUID.HighPart == Description.AdapterLuid.HighPart && adapterLUID.LowPart == Description.AdapterLuid.LowPart)
|
||||
{
|
||||
// Get driver version
|
||||
returnCode = RegGetValueW(dxKeyHandle, subKeyName, TEXT("DriverVersion"), RRF_RT_QWORD, 0, &driverVersionRaw, &qwordSize);
|
||||
if (returnCode == S_OK)
|
||||
{
|
||||
Version driverVersion(
|
||||
(int32)((driverVersionRaw & 0xFFFF000000000000) >> 16 * 3),
|
||||
(int32)((driverVersionRaw & 0x0000FFFF00000000) >> 16 * 2),
|
||||
(int32)((driverVersionRaw & 0x00000000FFFF0000) >> 16 * 1),
|
||||
(int32)((driverVersionRaw & 0x000000000000FFFF)));
|
||||
SetDriverVersion(driverVersion);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
RegCloseKey(dxKeyHandle);
|
||||
}
|
||||
|
||||
if (DriverVersion != Version(0, 0))
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if GPU_DRIVER_DETECTION_WIN32_SETUPAPI
|
||||
{
|
||||
// Reference: https://gist.github.com/LxLasso/eccee4d71c2e49492f2cbf01a966fa73
|
||||
|
||||
// Copied from devguid.h and devpkey.h
|
||||
#define MAKE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
|
||||
#define MAKE_DEVPROPKEY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8, pid) const DEVPROPKEY name = { { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }, pid }
|
||||
MAKE_GUID(GUID_DEVCLASS_DISPLAY, 0x4d36e968L, 0xe325, 0x11ce, 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18);
|
||||
MAKE_DEVPROPKEY(DEVPKEY_Device_DriverDate, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 2);
|
||||
MAKE_DEVPROPKEY(DEVPKEY_Device_DriverVersion, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 3);
|
||||
#undef MAKE_DEVPROPKEY
|
||||
#undef MAKE_GUID
|
||||
|
||||
HDEVINFO deviceInfoList = SetupDiGetClassDevs(&GUID_DEVCLASS_DISPLAY, NULL, NULL, DIGCF_PRESENT);
|
||||
if (deviceInfoList != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
SP_DEVINFO_DATA deviceInfo;
|
||||
ZeroMemory(&deviceInfo, sizeof(deviceInfo));
|
||||
deviceInfo.cbSize = sizeof(SP_DEVINFO_DATA);
|
||||
|
||||
wchar_t searchBuffer[128];
|
||||
swprintf(searchBuffer, sizeof(searchBuffer) / 2, L"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%04X", Description.VendorId, Description.DeviceId, Description.SubSysId);
|
||||
size_t searchBufferLen = wcslen(searchBuffer);
|
||||
|
||||
DWORD deviceIndex = 0;
|
||||
DEVPROPTYPE propertyType;
|
||||
wchar_t buffer[300];
|
||||
while (SetupDiEnumDeviceInfo(deviceInfoList, deviceIndex, &deviceInfo))
|
||||
{
|
||||
DWORD deviceIdSize;
|
||||
if (SetupDiGetDeviceInstanceId(deviceInfoList, &deviceInfo, buffer, sizeof(buffer), &deviceIdSize) &&
|
||||
wcsncmp(buffer, searchBuffer, searchBufferLen) == 0)
|
||||
{
|
||||
// Get driver version
|
||||
if (SetupDiGetDeviceProperty(deviceInfoList, &deviceInfo, &DEVPKEY_Device_DriverVersion, &propertyType, (PBYTE)buffer, sizeof(buffer), NULL, 0) &&
|
||||
propertyType == DEVPROP_TYPE_STRING)
|
||||
{
|
||||
//ParseDriverVersionBuffer(buffer);
|
||||
Version driverVersion;
|
||||
String bufferStr(buffer);
|
||||
if (!Version::Parse(bufferStr, &driverVersion))
|
||||
SetDriverVersion(driverVersion);
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Get driver date
|
||||
DEVPROPTYPE propertyType;
|
||||
if (SetupDiGetDeviceProperty(deviceInfoList, &deviceInfo, &DEVPKEY_Device_DriverDate, &propertyType, (PBYTE)buffer, sizeof(FILETIME), NULL, 0) &&
|
||||
propertyType == DEVPROP_TYPE_FILETIME)
|
||||
{
|
||||
SYSTEMTIME deviceDriverSystemTime;
|
||||
FileTimeToSystemTime((FILETIME*)buffer, &deviceDriverSystemTime);
|
||||
DriverDate = DateTime(deviceDriverSystemTime.wYear, deviceDriverSystemTime.wMonth, deviceDriverSystemTime.wDay, deviceDriverSystemTime.wHour, deviceDriverSystemTime.wMinute, deviceDriverSystemTime.wSecond, deviceDriverSystemTime.wMilliseconds);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
deviceIndex++;
|
||||
}
|
||||
|
||||
SetupDiDestroyDeviceInfoList(deviceInfoList);
|
||||
}
|
||||
|
||||
if (DriverVersion != Version(0, 0))
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void GPUAdapterDX::SetDriverVersion(Version& ver)
|
||||
{
|
||||
if (IsNVIDIA() && ver.Build() > 0 && ver.Revision() > 99)
|
||||
{
|
||||
// Convert NVIDIA version from 32.0.15.7247 into 572.47
|
||||
ver = Version((ver.Build() % 10) * 100 + ver.Revision() / 100, ver.Revision() % 100);
|
||||
}
|
||||
DriverVersion = ver;
|
||||
}
|
||||
|
||||
void GPUDeviceDX::UpdateOutputs(IDXGIAdapter* adapter)
|
||||
{
|
||||
#if PLATFORM_WINDOWS
|
||||
|
||||
@@ -29,6 +29,10 @@ public:
|
||||
{
|
||||
return TEXT("Null");
|
||||
}
|
||||
Version GetDriverVersion() const override
|
||||
{
|
||||
return Version(0, 0);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -70,6 +70,27 @@ public:
|
||||
{
|
||||
return Description;
|
||||
}
|
||||
Version GetDriverVersion() const override
|
||||
{
|
||||
Version version(VK_VERSION_MAJOR(GpuProps.driverVersion), VK_VERSION_MINOR(GpuProps.driverVersion), VK_VERSION_PATCH(GpuProps.driverVersion));
|
||||
if (IsNVIDIA())
|
||||
{
|
||||
union NvidiaDriverVersion
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 Tertiary : 6;
|
||||
uint32 Secondary : 8;
|
||||
uint32 Minor : 8;
|
||||
uint32 Major : 10;
|
||||
};
|
||||
uint32 Packed;
|
||||
} NvidiaVersion;
|
||||
NvidiaVersion.Packed = GpuProps.driverVersion;
|
||||
version = Version(NvidiaVersion.Major, NvidiaVersion.Minor);
|
||||
}
|
||||
return version;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user