Add DriverVersion to GPUAdapter for checking on old GPU drivers
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Engine/Core/Types/Version.h"
|
||||||
#include "Engine/Scripting/ScriptingObject.h"
|
#include "Engine/Scripting/ScriptingObject.h"
|
||||||
|
|
||||||
// GPU vendors IDs
|
// GPU vendors IDs
|
||||||
@@ -56,6 +57,11 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
API_PROPERTY() virtual String GetDescription() const = 0;
|
API_PROPERTY() virtual String GetDescription() const = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the GPU driver version.
|
||||||
|
/// </summary>
|
||||||
|
API_PROPERTY() virtual Version GetDriverVersion() const = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Returns true if adapter's vendor is AMD.
|
// Returns true if adapter's vendor is AMD.
|
||||||
API_PROPERTY() FORCE_INLINE bool IsAMD() const
|
API_PROPERTY() FORCE_INLINE bool IsAMD() const
|
||||||
|
|||||||
@@ -182,12 +182,12 @@ bool GraphicsService::Init()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
GPUDevice::Instance = device;
|
GPUDevice::Instance = device;
|
||||||
LOG(Info,
|
LOG(Info, "GPU Device created: {}", device->GetAdapter()->GetDescription());
|
||||||
"Graphics Device created! Adapter: \'{0}\', Renderer: {1}, Shader Profile: {2}, Feature Level: {3}",
|
LOG(Info, "Renderer: {}, Shader Profile: {}, Feature Level: {}, Driver: {}",
|
||||||
device->GetAdapter()->GetDescription(),
|
|
||||||
::ToString(device->GetRendererType()),
|
::ToString(device->GetRendererType()),
|
||||||
::ToString(device->GetShaderProfile()),
|
::ToString(device->GetShaderProfile()),
|
||||||
::ToString(device->GetFeatureLevel())
|
::ToString(device->GetFeatureLevel()),
|
||||||
|
device->GetAdapter()->GetDriverVersion().ToString()
|
||||||
);
|
);
|
||||||
|
|
||||||
// Initialize
|
// Initialize
|
||||||
|
|||||||
@@ -296,8 +296,6 @@ GPUDevice* GPUDeviceDX11::Create()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate adapter
|
|
||||||
if (!selectedAdapter.IsValid())
|
if (!selectedAdapter.IsValid())
|
||||||
{
|
{
|
||||||
LOG(Error, "Failed to choose valid DirectX adapter!");
|
LOG(Error, "Failed to choose valid DirectX adapter!");
|
||||||
@@ -427,7 +425,7 @@ bool GPUDeviceDX11::Init()
|
|||||||
|
|
||||||
// Create DirectX device
|
// Create DirectX device
|
||||||
D3D_FEATURE_LEVEL createdFeatureLevel = static_cast<D3D_FEATURE_LEVEL>(0);
|
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));
|
VALIDATE_DIRECTX_CALL(D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, flags, &targetFeatureLevel, 1, D3D11_SDK_VERSION, &_device, &createdFeatureLevel, &_imContext));
|
||||||
ASSERT(_device);
|
ASSERT(_device);
|
||||||
ASSERT(_imContext);
|
ASSERT(_imContext);
|
||||||
|
|||||||
@@ -198,17 +198,14 @@ GPUDevice* GPUDeviceDX12::Create()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate adapter
|
|
||||||
if (!selectedAdapter.IsValid())
|
if (!selectedAdapter.IsValid())
|
||||||
{
|
{
|
||||||
LOG(Error, "Failed to choose valid DirectX adapter!");
|
LOG(Error, "Failed to choose valid DirectX adapter!");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
if (selectedAdapter.MaxFeatureLevel < D3D_FEATURE_LEVEL_12_0)
|
||||||
// Check if selected adapter does not support DirectX 12
|
|
||||||
if (!selectedAdapter.IsSupportingDX12())
|
|
||||||
{
|
{
|
||||||
|
LOG(Error, "Failed to choose valid DirectX adapter!");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -14,25 +14,18 @@
|
|||||||
class GPUAdapterDX : public GPUAdapter
|
class GPUAdapterDX : public GPUAdapter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
int32 Index = INVALID_INDEX;
|
int32 Index = INVALID_INDEX;
|
||||||
D3D_FEATURE_LEVEL MaxFeatureLevel;
|
D3D_FEATURE_LEVEL MaxFeatureLevel;
|
||||||
DXGI_ADAPTER_DESC Description;
|
DXGI_ADAPTER_DESC Description;
|
||||||
|
Version DriverVersion = Version(0, 0);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
void GetDriverVersion();
|
||||||
|
|
||||||
// Returns true if adapter is supporting DirectX 12.
|
private:
|
||||||
FORCE_INLINE bool IsSupportingDX12() const
|
void SetDriverVersion(Version& ver);
|
||||||
{
|
|
||||||
#if GRAPHICS_API_DIRECTX12
|
|
||||||
return MaxFeatureLevel >= D3D_FEATURE_LEVEL_12_0;
|
|
||||||
#else
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// [GPUAdapter]
|
// [GPUAdapter]
|
||||||
bool IsValid() const override
|
bool IsValid() const override
|
||||||
{
|
{
|
||||||
@@ -50,6 +43,10 @@ public:
|
|||||||
{
|
{
|
||||||
return Description.Description;
|
return Description.Description;
|
||||||
}
|
}
|
||||||
|
Version GetDriverVersion() const override
|
||||||
|
{
|
||||||
|
return DriverVersion;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -36,17 +36,10 @@ protected:
|
|||||||
: GPUDevice(type, profile)
|
: GPUDevice(type, profile)
|
||||||
, _adapter(adapter)
|
, _adapter(adapter)
|
||||||
{
|
{
|
||||||
|
adapter->GetDriverVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// <summary>
|
|
||||||
/// Gets DirectX device feature level.
|
|
||||||
/// </summary>
|
|
||||||
FORCE_INLINE D3D_FEATURE_LEVEL GetD3DFeatureLevel() const
|
|
||||||
{
|
|
||||||
return _adapter->MaxFeatureLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The video outputs.
|
/// The video outputs.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -3,11 +3,24 @@
|
|||||||
#if GRAPHICS_API_DIRECTX11 || GRAPHICS_API_DIRECTX12
|
#if GRAPHICS_API_DIRECTX11 || GRAPHICS_API_DIRECTX12
|
||||||
|
|
||||||
#include "RenderToolsDX.h"
|
#include "RenderToolsDX.h"
|
||||||
|
#include "GPUAdapterDX.h"
|
||||||
#include "GPUDeviceDX.h"
|
#include "GPUDeviceDX.h"
|
||||||
|
#include "Engine/Core/Types/DateTime.h"
|
||||||
#include "Engine/Core/Types/StringBuilder.h"
|
#include "Engine/Core/Types/StringBuilder.h"
|
||||||
#include "Engine/Graphics/GPUDevice.h"
|
#include "Engine/Graphics/GPUDevice.h"
|
||||||
|
#include "IncludeDirectXHeaders.h"
|
||||||
#include <winerror.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
|
namespace Windows
|
||||||
{
|
{
|
||||||
typedef struct _devicemodeW
|
typedef struct _devicemodeW
|
||||||
@@ -304,7 +317,7 @@ void FormatD3DErrorString(HRESULT errorCode, StringBuilder& sb, HRESULT& removed
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
sb.AppendFormat(TEXT("0x{0:x}"), static_cast<unsigned int>(errorCode));
|
sb.AppendFormat(TEXT("0x{0:x}"), static_cast<unsigned int>(errorCode));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#undef D3DERR
|
#undef D3DERR
|
||||||
|
|
||||||
@@ -439,6 +452,140 @@ LPCSTR RenderToolsDX::GetVertexInputSemantic(VertexElement::Types type, UINT& se
|
|||||||
return "";
|
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)
|
void GPUDeviceDX::UpdateOutputs(IDXGIAdapter* adapter)
|
||||||
{
|
{
|
||||||
#if PLATFORM_WINDOWS
|
#if PLATFORM_WINDOWS
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ public:
|
|||||||
{
|
{
|
||||||
return TEXT("Null");
|
return TEXT("Null");
|
||||||
}
|
}
|
||||||
|
Version GetDriverVersion() const override
|
||||||
|
{
|
||||||
|
return Version(0, 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -70,6 +70,27 @@ public:
|
|||||||
{
|
{
|
||||||
return Description;
|
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
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user