Skip to content

Commit 2029679

Browse files
committed
GPU (Windows): use CMAPI instead of SetupAPI
Improve performance
1 parent 817f70c commit 2029679

1 file changed

Lines changed: 91 additions & 71 deletions

File tree

src/detection/gpu/gpu_windows.c

Lines changed: 91 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,12 @@
22
#include "detection/gpu/gpu_driver_specific.h"
33
#include "util/windows/unicode.h"
44
#include "util/windows/registry.h"
5+
#include "util/mallocHelper.h"
56

67
#define INITGUID
7-
#include <windows.h>
8-
#include <setupapi.h>
9-
#include <devguid.h>
10-
11-
static inline void wrapSetupDiDestroyDeviceInfoList(HDEVINFO* hdev)
12-
{
13-
if(*hdev)
14-
SetupDiDestroyDeviceInfoList(*hdev);
15-
}
8+
#include <cfgmgr32.h>
9+
#include <ntddvdeo.h>
10+
#include <devpkey.h>
1611

1712
#define FF_EMPTY_GUID_STR L"{00000000-0000-0000-0000-000000000000}"
1813
enum { FF_GUID_STRLEN = sizeof(FF_EMPTY_GUID_STR) / sizeof(wchar_t) - 1 };
@@ -24,21 +19,38 @@ const uint32_t regDriverKeyPrefixLength = (uint32_t) __builtin_strlen("SYSTEM\\C
2419

2520
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus)
2621
{
27-
HDEVINFO hdev __attribute__((__cleanup__(wrapSetupDiDestroyDeviceInfoList))) =
28-
SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY, NULL, NULL, DIGCF_PRESENT);
22+
ULONG devInfListSize = 0;
23+
if (CM_Get_Device_Interface_List_SizeW(&devInfListSize, (LPGUID)&GUID_DEVINTERFACE_DISPLAY_ADAPTER, NULL, CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS || devInfListSize <= 1)
24+
return "No display devices found";
2925

30-
if(hdev == INVALID_HANDLE_VALUE)
31-
return "SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY) failed";
26+
FF_AUTO_FREE DEVINSTID_W devInfList = malloc(devInfListSize * sizeof(*devInfList));
3227

33-
SP_DEVINFO_DATA did = { .cbSize = sizeof(did) };
34-
for (DWORD idev = 0; SetupDiEnumDeviceInfo(hdev, idev, &did); ++idev)
28+
if (CM_Get_Device_Interface_ListW((LPGUID)&GUID_DEVINTERFACE_DISPLAY_ADAPTER, NULL, devInfList, devInfListSize, CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS)
29+
return "CM_Get_Device_Interface_ListW failed";
30+
31+
for (wchar_t* devInf = devInfList; *devInf; devInf += wcslen(devInf) + 1)
3532
{
33+
if (wcsncmp(devInf, L"\\\\?\\ROOT#BasicDisplay#", 22) == 0)
34+
continue; // Skip Microsoft Basic Display Adapter
35+
36+
DEVINST devInst = 0;
37+
wchar_t buffer[256];
38+
ULONG bufferLen = 0;
39+
40+
{
41+
DEVPROPTYPE propertyType;
42+
bufferLen = sizeof(buffer);
43+
if (CM_Get_Device_Interface_PropertyW(devInf, &DEVPKEY_Device_InstanceId, &propertyType, (PBYTE) buffer, &bufferLen, 0) != CR_SUCCESS ||
44+
CM_Locate_DevNodeW(&devInst, buffer, CM_LOCATE_DEVNODE_NORMAL) != CR_SUCCESS)
45+
continue;
46+
}
47+
3648
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
3749
ffStrbufInit(&gpu->vendor);
3850
ffStrbufInit(&gpu->name);
3951
ffStrbufInit(&gpu->driver);
4052
ffStrbufInit(&gpu->memoryType);
41-
ffStrbufInitStatic(&gpu->platformApi, "SetupAPI");
53+
ffStrbufInitStatic(&gpu->platformApi, "CM API");
4254
gpu->index = FF_GPU_INDEX_UNSET;
4355
gpu->temperature = FF_GPU_TEMP_UNSET;
4456
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
@@ -49,79 +61,85 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
4961
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
5062

5163
uint32_t pciBus = 0, pciAddr = 0, pciDev = 0, pciFunc = 0;
52-
if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_BUSNUMBER, NULL, (PBYTE) &pciBus, sizeof(pciBus), NULL) &&
53-
SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_ADDRESS, NULL, (PBYTE) &pciAddr, sizeof(pciAddr), NULL))
64+
65+
ULONG pciBufLen = sizeof(pciBus);
66+
if (CM_Get_DevNode_Registry_PropertyW(devInst, CM_DRP_BUSNUMBER, NULL, &pciBus, &pciBufLen, 0) == CR_SUCCESS)
5467
{
55-
pciDev = (pciAddr >> 16) & 0xFFFF;
56-
pciFunc = pciAddr & 0xFFFF;
57-
gpu->deviceId = (pciBus * 1000ull) + (pciDev * 10ull) + pciFunc;
58-
pciAddr = 1; // Set to 1 to indicate that the device is a PCI device
68+
pciBufLen = sizeof(pciAddr);
69+
if (CM_Get_DevNode_Registry_PropertyW(devInst, CM_DRP_ADDRESS, NULL, &pciAddr, &pciBufLen, 0) == CR_SUCCESS)
70+
{
71+
pciDev = (pciAddr >> 16) & 0xFFFF;
72+
pciFunc = pciAddr & 0xFFFF;
73+
gpu->deviceId = (pciBus * 1000ull) + (pciDev * 10ull) + pciFunc;
74+
pciAddr = 1; // Set to 1 to indicate that the device is a PCI device
75+
}
5976
}
6077

61-
wchar_t buffer[256];
62-
6378
uint64_t adapterLuid = 0;
6479

65-
FF_HKEY_AUTO_DESTROY hVideoIdKey = SetupDiOpenDevRegKey(hdev, &did, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE);
66-
if (!hVideoIdKey) continue;
67-
DWORD bufferLen = sizeof(buffer);
68-
if (RegGetValueW(hVideoIdKey, NULL, L"VideoID", RRF_RT_REG_SZ, NULL, buffer, &bufferLen) == ERROR_SUCCESS &&
69-
bufferLen == (FF_GUID_STRLEN + 1) * sizeof(wchar_t))
80+
FF_HKEY_AUTO_DESTROY hVideoIdKey = NULL;
81+
if (CM_Open_DevNode_Key(devInst, KEY_QUERY_VALUE, 0, RegDisposition_OpenExisting, &hVideoIdKey, CM_REGISTRY_HARDWARE) == CR_SUCCESS)
7082
{
71-
wmemcpy(regDirectxKey + regDirectxKeyPrefixLength, buffer, FF_GUID_STRLEN);
72-
FF_HKEY_AUTO_DESTROY hDirectxKey = NULL;
73-
if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDirectxKey, &hDirectxKey, NULL))
83+
bufferLen = sizeof(buffer);
84+
if (RegGetValueW(hVideoIdKey, NULL, L"VideoID", RRF_RT_REG_SZ, NULL, buffer, &bufferLen) == ERROR_SUCCESS &&
85+
bufferLen == (FF_GUID_STRLEN + 1) * sizeof(wchar_t))
7486
{
75-
uint32_t vendorId = 0;
76-
if(ffRegReadUint(hDirectxKey, L"VendorId", &vendorId, NULL) && vendorId)
77-
ffStrbufSetStatic(&gpu->vendor, ffGPUGetVendorString(vendorId));
87+
wmemcpy(regDirectxKey + regDirectxKeyPrefixLength, buffer, FF_GUID_STRLEN);
88+
FF_HKEY_AUTO_DESTROY hDirectxKey = NULL;
89+
if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDirectxKey, &hDirectxKey, NULL))
90+
{
91+
uint32_t vendorId = 0;
92+
if(ffRegReadUint(hDirectxKey, L"VendorId", &vendorId, NULL) && vendorId)
93+
ffStrbufSetStatic(&gpu->vendor, ffGPUGetVendorString(vendorId));
7894

79-
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
80-
gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
95+
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
96+
gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
8197

82-
uint64_t dedicatedVideoMemory = 0;
83-
if(ffRegReadUint64(hDirectxKey, L"DedicatedVideoMemory", &dedicatedVideoMemory, NULL))
84-
{
85-
if (gpu->type == FF_GPU_TYPE_UNKNOWN)
86-
gpu->type = dedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
87-
}
98+
uint64_t dedicatedVideoMemory = 0;
99+
if(ffRegReadUint64(hDirectxKey, L"DedicatedVideoMemory", &dedicatedVideoMemory, NULL))
100+
{
101+
if (gpu->type == FF_GPU_TYPE_UNKNOWN)
102+
gpu->type = dedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
103+
}
88104

89-
uint64_t dedicatedSystemMemory, sharedSystemMemory;
90-
if(ffRegReadUint64(hDirectxKey, L"DedicatedSystemMemory", &dedicatedSystemMemory, NULL) &&
91-
ffRegReadUint64(hDirectxKey, L"SharedSystemMemory", &sharedSystemMemory, NULL))
92-
{
93-
gpu->dedicated.total = dedicatedVideoMemory + dedicatedSystemMemory;
94-
gpu->shared.total = sharedSystemMemory;
95-
}
105+
uint64_t dedicatedSystemMemory, sharedSystemMemory;
106+
if(ffRegReadUint64(hDirectxKey, L"DedicatedSystemMemory", &dedicatedSystemMemory, NULL) &&
107+
ffRegReadUint64(hDirectxKey, L"SharedSystemMemory", &sharedSystemMemory, NULL))
108+
{
109+
gpu->dedicated.total = dedicatedVideoMemory + dedicatedSystemMemory;
110+
gpu->shared.total = sharedSystemMemory;
111+
}
96112

97-
if (ffRegReadUint64(hDirectxKey, L"AdapterLuid", &adapterLuid, NULL))
98-
{
99-
if (!gpu->deviceId) gpu->deviceId = adapterLuid;
100-
}
113+
if (ffRegReadUint64(hDirectxKey, L"AdapterLuid", &adapterLuid, NULL))
114+
{
115+
if (!gpu->deviceId) gpu->deviceId = adapterLuid;
116+
}
101117

102-
uint32_t featureLevel = 0;
103-
if(ffRegReadUint(hDirectxKey, L"MaxD3D12FeatureLevel", &featureLevel, NULL) && featureLevel)
104-
ffStrbufSetF(&gpu->platformApi, "Direct3D 12.%u", (featureLevel & 0x0F00) >> 8);
105-
else if(ffRegReadUint(hDirectxKey, L"MaxD3D11FeatureLevel", &featureLevel, NULL) && featureLevel)
106-
ffStrbufSetF(&gpu->platformApi, "Direct3D 11.%u", (featureLevel & 0x0F00) >> 8);
118+
uint32_t featureLevel = 0;
119+
if(ffRegReadUint(hDirectxKey, L"MaxD3D12FeatureLevel", &featureLevel, NULL) && featureLevel)
120+
ffStrbufSetF(&gpu->platformApi, "Direct3D 12.%u", (featureLevel & 0x0F00) >> 8);
121+
else if(ffRegReadUint(hDirectxKey, L"MaxD3D11FeatureLevel", &featureLevel, NULL) && featureLevel)
122+
ffStrbufSetF(&gpu->platformApi, "Direct3D 11.%u", (featureLevel & 0x0F00) >> 8);
107123

108-
uint64_t driverVersion = 0;
109-
if(ffRegReadUint64(hDirectxKey, L"DriverVersion", &driverVersion, NULL) && driverVersion)
110-
{
111-
ffStrbufSetF(&gpu->driver, "%u.%u.%u.%u",
112-
(unsigned) (driverVersion >> 48) & 0xFFFF,
113-
(unsigned) (driverVersion >> 32) & 0xFFFF,
114-
(unsigned) (driverVersion >> 16) & 0xFFFF,
115-
(unsigned) (driverVersion >> 0) & 0xFFFF
116-
);
124+
uint64_t driverVersion = 0;
125+
if(ffRegReadUint64(hDirectxKey, L"DriverVersion", &driverVersion, NULL) && driverVersion)
126+
{
127+
ffStrbufSetF(&gpu->driver, "%u.%u.%u.%u",
128+
(unsigned) (driverVersion >> 48) & 0xFFFF,
129+
(unsigned) (driverVersion >> 32) & 0xFFFF,
130+
(unsigned) (driverVersion >> 16) & 0xFFFF,
131+
(unsigned) (driverVersion >> 0) & 0xFFFF
132+
);
133+
}
117134
}
118135
}
119136
}
120137

121138
if (gpu->vendor.length == 0)
122139
{
123140
bufferLen = sizeof(buffer);
124-
if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_DRIVER, NULL, (PBYTE) buffer, sizeof(buffer), &bufferLen) && bufferLen == (FF_GUID_STRLEN + strlen("\\0000") + 1) * 2)
141+
if (CM_Get_DevNode_Registry_PropertyW(devInst, CM_DRP_DRIVER, NULL, buffer, &bufferLen, 0) == CR_SUCCESS &&
142+
bufferLen == (FF_GUID_STRLEN + strlen("\\0000") + 1) * 2)
125143
{
126144
wmemcpy(regDriverKey + regDriverKeyPrefixLength, buffer, FF_GUID_STRLEN + strlen("\\0000"));
127145
FF_HKEY_AUTO_DESTROY hRegDriverKey = NULL;
@@ -146,7 +164,8 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
146164
if (getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &dllName) && (options->temp || options->driverSpecific))
147165
{
148166
unsigned vendorId = 0, deviceId = 0, subSystemId = 0, revId = 0;
149-
if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_HARDWAREID, NULL, (PBYTE) buffer, sizeof(buffer), NULL))
167+
bufferLen = sizeof(buffer);
168+
if (CM_Get_DevNode_Registry_PropertyW(devInst, CM_DRP_HARDWAREID, NULL, buffer, &bufferLen, 0) == CR_SUCCESS)
150169
{
151170
swscanf(buffer, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId);
152171
ffStrbufSetStatic(&gpu->vendor, ffGPUGetVendorString(vendorId));
@@ -189,7 +208,8 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
189208

190209
if (!gpu->name.length)
191210
{
192-
if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_DEVICEDESC, NULL, (PBYTE) buffer, sizeof(buffer), NULL))
211+
bufferLen = sizeof(buffer);
212+
if (CM_Get_DevNode_Registry_PropertyW(devInst, CM_DRP_DEVICEDESC, NULL, buffer, &bufferLen, 0) == CR_SUCCESS)
193213
ffStrbufSetWS(&gpu->name, buffer);
194214
}
195215
}

0 commit comments

Comments
 (0)