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}"
1813enum { 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
2520const 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