Skip to content

Commit fe7e684

Browse files
committed
GPU (Windows): fix missing GPUs sometimes
1 parent 2281caa commit fe7e684

File tree

1 file changed

+71
-58
lines changed

1 file changed

+71
-58
lines changed

src/detection/gpu/gpu_windows.c

Lines changed: 71 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ static inline void wrapSetupDiDestroyDeviceInfoList(HDEVINFO* hdev)
1717
#define FF_EMPTY_GUID_STR L"{00000000-0000-0000-0000-000000000000}"
1818
enum { FF_GUID_STRLEN = sizeof(FF_EMPTY_GUID_STR) / sizeof(wchar_t) - 1 };
1919

20+
wchar_t regDirectxKey[] = L"SOFTWARE\\Microsoft\\DirectX\\" FF_EMPTY_GUID_STR;
21+
const uint32_t regDirectxKeyPrefixLength = (uint32_t) __builtin_strlen("SOFTWARE\\Microsoft\\DirectX\\");
22+
wchar_t regDriverKey[] = L"SYSTEM\\CurrentControlSet\\Control\\Class\\" FF_EMPTY_GUID_STR L"\\0000";
23+
const uint32_t regDriverKeyPrefixLength = (uint32_t) __builtin_strlen("SYSTEM\\CurrentControlSet\\Control\\Class\\");
24+
2025
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus)
2126
{
2227
HDEVINFO hdev __attribute__((__cleanup__(wrapSetupDiDestroyDeviceInfoList))) =
@@ -25,11 +30,6 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
2530
if(hdev == INVALID_HANDLE_VALUE)
2631
return "SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY) failed";
2732

28-
wchar_t regDirectxKey[] = L"SOFTWARE\\Microsoft\\DirectX\\" FF_EMPTY_GUID_STR;
29-
const uint32_t regDirectxKeyPrefixLength = (uint32_t) strlen("SOFTWARE\\Microsoft\\DirectX\\");
30-
wchar_t regControlVideoKey[] = L"SYSTEM\\CurrentControlSet\\Control\\Video\\" FF_EMPTY_GUID_STR L"\\0000";
31-
const uint32_t regControlVideoKeyPrefixLength = (uint32_t) strlen("SYSTEM\\CurrentControlSet\\Control\\Video\\");
32-
3333
SP_DEVINFO_DATA did = { .cbSize = sizeof(did) };
3434
for (DWORD idev = 0; SetupDiEnumDeviceInfo(hdev, idev, &did); ++idev)
3535
{
@@ -50,74 +50,87 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
5050
if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_DEVICEDESC, NULL, (PBYTE) buffer, sizeof(buffer), NULL))
5151
ffStrbufSetWS(&gpu->name, buffer);
5252

53-
if (!SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_HARDWAREID, NULL, (PBYTE) buffer, sizeof(buffer), NULL))
54-
continue;
55-
56-
unsigned vendorId = 0, deviceId = 0, subSystemId = 0, revId = 0;
57-
swscanf(buffer, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId);
58-
ffStrbufSetStatic(&gpu->vendor, ffGetGPUVendorString(vendorId));
59-
6053
FF_HKEY_AUTO_DESTROY hVideoIdKey = SetupDiOpenDevRegKey(hdev, &did, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE);
6154
if (!hVideoIdKey) continue;
62-
DWORD videoIdLength = sizeof(buffer);
63-
if (RegGetValueW(hVideoIdKey, NULL, L"VideoID", RRF_RT_REG_SZ, NULL, buffer, &videoIdLength) != ERROR_SUCCESS)
64-
continue;
65-
66-
if (videoIdLength != (FF_GUID_STRLEN + 1) * sizeof(wchar_t))
67-
continue; // Should not happen
68-
69-
wmemcpy(regControlVideoKey + regControlVideoKeyPrefixLength, buffer, FF_GUID_STRLEN);
70-
FF_HKEY_AUTO_DESTROY hRegControlVideoKey = NULL;
71-
if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regControlVideoKey, &hRegControlVideoKey, NULL)) continue;
72-
73-
wmemcpy(regDirectxKey + regDirectxKeyPrefixLength, buffer, FF_GUID_STRLEN);
74-
FF_HKEY_AUTO_DESTROY hDirectxKey = NULL;
75-
if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDirectxKey, &hDirectxKey, NULL))
55+
DWORD bufferLen = sizeof(buffer);
56+
if (RegGetValueW(hVideoIdKey, NULL, L"VideoID", RRF_RT_REG_SZ, NULL, buffer, &bufferLen) == ERROR_SUCCESS &&
57+
bufferLen == (FF_GUID_STRLEN + 1) * sizeof(wchar_t))
7658
{
77-
uint64_t dedicatedVideoMemory = 0;
78-
if(ffRegReadUint64(hDirectxKey, L"DedicatedVideoMemory", &dedicatedVideoMemory, NULL))
79-
gpu->type = dedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
80-
81-
uint64_t dedicatedSystemMemory, sharedSystemMemory;
82-
if(ffRegReadUint64(hDirectxKey, L"DedicatedSystemMemory", &dedicatedSystemMemory, NULL) &&
83-
ffRegReadUint64(hDirectxKey, L"SharedSystemMemory", &sharedSystemMemory, NULL))
59+
wmemcpy(regDirectxKey + regDirectxKeyPrefixLength, buffer, FF_GUID_STRLEN);
60+
FF_HKEY_AUTO_DESTROY hDirectxKey = NULL;
61+
if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDirectxKey, &hDirectxKey, NULL))
8462
{
85-
gpu->dedicated.total = dedicatedVideoMemory + dedicatedSystemMemory;
86-
gpu->shared.total = sharedSystemMemory;
63+
uint64_t dedicatedVideoMemory = 0;
64+
if(ffRegReadUint64(hDirectxKey, L"DedicatedVideoMemory", &dedicatedVideoMemory, NULL))
65+
gpu->type = dedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
66+
67+
uint64_t dedicatedSystemMemory, sharedSystemMemory;
68+
if(ffRegReadUint64(hDirectxKey, L"DedicatedSystemMemory", &dedicatedSystemMemory, NULL) &&
69+
ffRegReadUint64(hDirectxKey, L"SharedSystemMemory", &sharedSystemMemory, NULL))
70+
{
71+
gpu->dedicated.total = dedicatedVideoMemory + dedicatedSystemMemory;
72+
gpu->shared.total = sharedSystemMemory;
73+
}
74+
75+
ffRegReadUint64(hDirectxKey, L"AdapterLuid", &gpu->deviceId, NULL);
76+
77+
uint32_t featureLevel = 0;
78+
if(ffRegReadUint(hDirectxKey, L"MaxD3D12FeatureLevel", &featureLevel, NULL) && featureLevel)
79+
ffStrbufSetF(&gpu->platformApi, "Direct3D 12.%u", (featureLevel & 0x0F00) >> 8);
80+
else if(ffRegReadUint(hDirectxKey, L"MaxD3D11FeatureLevel", &featureLevel, NULL) && featureLevel)
81+
ffStrbufSetF(&gpu->platformApi, "Direct3D 11.%u", (featureLevel & 0x0F00) >> 8);
82+
83+
uint64_t driverVersion = 0;
84+
if(ffRegReadUint64(hDirectxKey, L"DriverVersion", &driverVersion, NULL) && driverVersion)
85+
{
86+
ffStrbufSetF(&gpu->driver, "%u.%u.%u.%u",
87+
(unsigned) (driverVersion >> 48) & 0xFFFF,
88+
(unsigned) (driverVersion >> 32) & 0xFFFF,
89+
(unsigned) (driverVersion >> 16) & 0xFFFF,
90+
(unsigned) (driverVersion >> 0) & 0xFFFF
91+
);
92+
}
93+
94+
uint32_t vendorId = 0;
95+
if(ffRegReadUint(hDirectxKey, L"VendorId", &vendorId, NULL) && vendorId)
96+
ffStrbufSetStatic(&gpu->vendor, ffGetGPUVendorString(vendorId));
8797
}
88-
89-
ffRegReadUint64(hDirectxKey, L"AdapterLuid", &gpu->deviceId, NULL);
90-
91-
uint32_t featureLevel = 0;
92-
if(ffRegReadUint(hDirectxKey, L"MaxD3D12FeatureLevel", &featureLevel, NULL) && featureLevel)
93-
ffStrbufSetF(&gpu->platformApi, "Direct3D 12.%u", (featureLevel & 0x0F00) >> 8);
94-
else if(ffRegReadUint(hDirectxKey, L"MaxD3D11FeatureLevel", &featureLevel, NULL) && featureLevel)
95-
ffStrbufSetF(&gpu->platformApi, "Direct3D 11.%u", (featureLevel & 0x0F00) >> 8);
96-
}
97-
else if (!ffRegReadUint64(hRegControlVideoKey, L"HardwareInformation.qwMemorySize", &gpu->dedicated.total, NULL))
98-
{
99-
uint32_t vmem = 0;
100-
if (ffRegReadUint(hRegControlVideoKey, L"HardwareInformation.MemorySize", &vmem, NULL))
101-
gpu->dedicated.total = vmem;
102-
gpu->type = gpu->dedicated.total > 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
10398
}
10499

105100
if (gpu->vendor.length == 0)
106101
{
107-
ffRegReadStrbuf(hRegControlVideoKey, L"ProviderName", &gpu->vendor, NULL);
108-
if (ffStrbufContainS(&gpu->vendor, "Intel"))
109-
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
110-
else if (ffStrbufContainS(&gpu->vendor, "NVIDIA"))
111-
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
112-
else if (ffStrbufContainS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI"))
113-
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
102+
bufferLen = sizeof(buffer);
103+
if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_DRIVER, NULL, (PBYTE) buffer, sizeof(buffer), &bufferLen) && bufferLen == (FF_GUID_STRLEN + strlen("\\0000") + 1) * 2)
104+
{
105+
wmemcpy(regDriverKey + regDriverKeyPrefixLength, buffer, FF_GUID_STRLEN + strlen("\\0000"));
106+
FF_HKEY_AUTO_DESTROY hRegDriverKey = NULL;
107+
if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDriverKey, &hRegDriverKey, NULL))
108+
{
109+
if (ffRegReadStrbuf(hRegDriverKey, L"ProviderName", &gpu->vendor, NULL))
110+
{
111+
if (ffStrbufContainS(&gpu->vendor, "Intel"))
112+
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
113+
else if (ffStrbufContainS(&gpu->vendor, "NVIDIA"))
114+
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
115+
else if (ffStrbufContainS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI"))
116+
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
117+
}
118+
}
119+
}
114120
}
115121

116122
__typeof__(&ffDetectNvidiaGpuInfo) detectFn;
117123
const char* dllName;
118124

119125
if (getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &dllName) && (options->temp || options->driverSpecific))
120126
{
127+
unsigned vendorId = 0, deviceId = 0, subSystemId = 0, revId = 0;
128+
if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_HARDWAREID, NULL, (PBYTE) buffer, sizeof(buffer), NULL))
129+
{
130+
swscanf(buffer, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId);
131+
ffStrbufSetStatic(&gpu->vendor, ffGetGPUVendorString(vendorId));
132+
}
133+
121134
uint32_t pciBus, pciAddr;
122135
if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_BUSNUMBER, NULL, (PBYTE) &pciBus, sizeof(pciBus), NULL) &&
123136
SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_ADDRESS, NULL, (PBYTE) &pciAddr, sizeof(pciAddr), NULL))
@@ -129,7 +142,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
129142
&(FFGpuDriverCondition) {
130143
.type = FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID
131144
| (gpu->deviceId > 0 ? FF_GPU_DRIVER_CONDITION_TYPE_LUID : 0)
132-
| FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
145+
| (vendorId > 0 ? FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID : 0),
133146
.pciDeviceId = {
134147
.deviceId = deviceId,
135148
.vendorId = vendorId,

0 commit comments

Comments
 (0)