diff --git a/src/detection/gpu/gpu_windows.c b/src/detection/gpu/gpu_windows.c index d4d616c1e..6ad1cd2e8 100644 --- a/src/detection/gpu/gpu_windows.c +++ b/src/detection/gpu/gpu_windows.c @@ -17,6 +17,11 @@ static inline void wrapSetupDiDestroyDeviceInfoList(HDEVINFO* hdev) #define FF_EMPTY_GUID_STR L"{00000000-0000-0000-0000-000000000000}" enum { FF_GUID_STRLEN = sizeof(FF_EMPTY_GUID_STR) / sizeof(wchar_t) - 1 }; +wchar_t regDirectxKey[] = L"SOFTWARE\\Microsoft\\DirectX\\" FF_EMPTY_GUID_STR; +const uint32_t regDirectxKeyPrefixLength = (uint32_t) __builtin_strlen("SOFTWARE\\Microsoft\\DirectX\\"); +wchar_t regDriverKey[] = L"SYSTEM\\CurrentControlSet\\Control\\Class\\" FF_EMPTY_GUID_STR L"\\0000"; +const uint32_t regDriverKeyPrefixLength = (uint32_t) __builtin_strlen("SYSTEM\\CurrentControlSet\\Control\\Class\\"); + const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus) { HDEVINFO hdev __attribute__((__cleanup__(wrapSetupDiDestroyDeviceInfoList))) = @@ -25,11 +30,6 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* if(hdev == INVALID_HANDLE_VALUE) return "SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY) failed"; - wchar_t regDirectxKey[] = L"SOFTWARE\\Microsoft\\DirectX\\" FF_EMPTY_GUID_STR; - const uint32_t regDirectxKeyPrefixLength = (uint32_t) strlen("SOFTWARE\\Microsoft\\DirectX\\"); - wchar_t regControlVideoKey[] = L"SYSTEM\\CurrentControlSet\\Control\\Video\\" FF_EMPTY_GUID_STR L"\\0000"; - const uint32_t regControlVideoKeyPrefixLength = (uint32_t) strlen("SYSTEM\\CurrentControlSet\\Control\\Video\\"); - SP_DEVINFO_DATA did = { .cbSize = sizeof(did) }; for (DWORD idev = 0; SetupDiEnumDeviceInfo(hdev, idev, &did); ++idev) { @@ -50,67 +50,73 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_DEVICEDESC, NULL, (PBYTE) buffer, sizeof(buffer), NULL)) ffStrbufSetWS(&gpu->name, buffer); - if (!SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_HARDWAREID, NULL, (PBYTE) buffer, sizeof(buffer), NULL)) - continue; - - unsigned vendorId = 0, deviceId = 0, subSystemId = 0, revId = 0; - swscanf(buffer, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId); - ffStrbufSetStatic(&gpu->vendor, ffGetGPUVendorString(vendorId)); - FF_HKEY_AUTO_DESTROY hVideoIdKey = SetupDiOpenDevRegKey(hdev, &did, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE); if (!hVideoIdKey) continue; - DWORD videoIdLength = sizeof(buffer); - if (RegGetValueW(hVideoIdKey, NULL, L"VideoID", RRF_RT_REG_SZ, NULL, buffer, &videoIdLength) != ERROR_SUCCESS) - continue; - - if (videoIdLength != (FF_GUID_STRLEN + 1) * sizeof(wchar_t)) - continue; // Should not happen - - wmemcpy(regControlVideoKey + regControlVideoKeyPrefixLength, buffer, FF_GUID_STRLEN); - FF_HKEY_AUTO_DESTROY hRegControlVideoKey = NULL; - if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regControlVideoKey, &hRegControlVideoKey, NULL)) continue; - - wmemcpy(regDirectxKey + regDirectxKeyPrefixLength, buffer, FF_GUID_STRLEN); - FF_HKEY_AUTO_DESTROY hDirectxKey = NULL; - if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDirectxKey, &hDirectxKey, NULL)) + DWORD bufferLen = sizeof(buffer); + if (RegGetValueW(hVideoIdKey, NULL, L"VideoID", RRF_RT_REG_SZ, NULL, buffer, &bufferLen) == ERROR_SUCCESS && + bufferLen == (FF_GUID_STRLEN + 1) * sizeof(wchar_t)) { - uint64_t dedicatedVideoMemory = 0; - if(ffRegReadUint64(hDirectxKey, L"DedicatedVideoMemory", &dedicatedVideoMemory, NULL)) - gpu->type = dedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; - - uint64_t dedicatedSystemMemory, sharedSystemMemory; - if(ffRegReadUint64(hDirectxKey, L"DedicatedSystemMemory", &dedicatedSystemMemory, NULL) && - ffRegReadUint64(hDirectxKey, L"SharedSystemMemory", &sharedSystemMemory, NULL)) + wmemcpy(regDirectxKey + regDirectxKeyPrefixLength, buffer, FF_GUID_STRLEN); + FF_HKEY_AUTO_DESTROY hDirectxKey = NULL; + if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDirectxKey, &hDirectxKey, NULL)) { - gpu->dedicated.total = dedicatedVideoMemory + dedicatedSystemMemory; - gpu->shared.total = sharedSystemMemory; + uint64_t dedicatedVideoMemory = 0; + if(ffRegReadUint64(hDirectxKey, L"DedicatedVideoMemory", &dedicatedVideoMemory, NULL)) + gpu->type = dedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; + + uint64_t dedicatedSystemMemory, sharedSystemMemory; + if(ffRegReadUint64(hDirectxKey, L"DedicatedSystemMemory", &dedicatedSystemMemory, NULL) && + ffRegReadUint64(hDirectxKey, L"SharedSystemMemory", &sharedSystemMemory, NULL)) + { + gpu->dedicated.total = dedicatedVideoMemory + dedicatedSystemMemory; + gpu->shared.total = sharedSystemMemory; + } + + ffRegReadUint64(hDirectxKey, L"AdapterLuid", &gpu->deviceId, NULL); + + uint32_t featureLevel = 0; + if(ffRegReadUint(hDirectxKey, L"MaxD3D12FeatureLevel", &featureLevel, NULL) && featureLevel) + ffStrbufSetF(&gpu->platformApi, "Direct3D 12.%u", (featureLevel & 0x0F00) >> 8); + else if(ffRegReadUint(hDirectxKey, L"MaxD3D11FeatureLevel", &featureLevel, NULL) && featureLevel) + ffStrbufSetF(&gpu->platformApi, "Direct3D 11.%u", (featureLevel & 0x0F00) >> 8); + + uint64_t driverVersion = 0; + if(ffRegReadUint64(hDirectxKey, L"DriverVersion", &driverVersion, NULL) && driverVersion) + { + ffStrbufSetF(&gpu->driver, "%u.%u.%u.%u", + (unsigned) (driverVersion >> 48) & 0xFFFF, + (unsigned) (driverVersion >> 32) & 0xFFFF, + (unsigned) (driverVersion >> 16) & 0xFFFF, + (unsigned) (driverVersion >> 0) & 0xFFFF + ); + } + + uint32_t vendorId = 0; + if(ffRegReadUint(hDirectxKey, L"VendorId", &vendorId, NULL) && vendorId) + ffStrbufSetStatic(&gpu->vendor, ffGetGPUVendorString(vendorId)); } - - ffRegReadUint64(hDirectxKey, L"AdapterLuid", &gpu->deviceId, NULL); - - uint32_t featureLevel = 0; - if(ffRegReadUint(hDirectxKey, L"MaxD3D12FeatureLevel", &featureLevel, NULL) && featureLevel) - ffStrbufSetF(&gpu->platformApi, "Direct3D 12.%u", (featureLevel & 0x0F00) >> 8); - else if(ffRegReadUint(hDirectxKey, L"MaxD3D11FeatureLevel", &featureLevel, NULL) && featureLevel) - ffStrbufSetF(&gpu->platformApi, "Direct3D 11.%u", (featureLevel & 0x0F00) >> 8); - } - else if (!ffRegReadUint64(hRegControlVideoKey, L"HardwareInformation.qwMemorySize", &gpu->dedicated.total, NULL)) - { - uint32_t vmem = 0; - if (ffRegReadUint(hRegControlVideoKey, L"HardwareInformation.MemorySize", &vmem, NULL)) - gpu->dedicated.total = vmem; - gpu->type = gpu->dedicated.total > 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; } if (gpu->vendor.length == 0) { - ffRegReadStrbuf(hRegControlVideoKey, L"ProviderName", &gpu->vendor, NULL); - if (ffStrbufContainS(&gpu->vendor, "Intel")) - ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL); - else if (ffStrbufContainS(&gpu->vendor, "NVIDIA")) - ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA); - else if (ffStrbufContainS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI")) - ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD); + bufferLen = sizeof(buffer); + if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_DRIVER, NULL, (PBYTE) buffer, sizeof(buffer), &bufferLen) && bufferLen == (FF_GUID_STRLEN + strlen("\\0000") + 1) * 2) + { + wmemcpy(regDriverKey + regDriverKeyPrefixLength, buffer, FF_GUID_STRLEN + strlen("\\0000")); + FF_HKEY_AUTO_DESTROY hRegDriverKey = NULL; + if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDriverKey, &hRegDriverKey, NULL)) + { + if (ffRegReadStrbuf(hRegDriverKey, L"ProviderName", &gpu->vendor, NULL)) + { + if (ffStrbufContainS(&gpu->vendor, "Intel")) + ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL); + else if (ffStrbufContainS(&gpu->vendor, "NVIDIA")) + ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA); + else if (ffStrbufContainS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI")) + ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD); + } + } + } } __typeof__(&ffDetectNvidiaGpuInfo) detectFn; @@ -118,6 +124,13 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* if (getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &dllName) && (options->temp || options->driverSpecific)) { + unsigned vendorId = 0, deviceId = 0, subSystemId = 0, revId = 0; + if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_HARDWAREID, NULL, (PBYTE) buffer, sizeof(buffer), NULL)) + { + swscanf(buffer, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId); + ffStrbufSetStatic(&gpu->vendor, ffGetGPUVendorString(vendorId)); + } + uint32_t pciBus, pciAddr; if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_BUSNUMBER, NULL, (PBYTE) &pciBus, sizeof(pciBus), NULL) && 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* &(FFGpuDriverCondition) { .type = FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID | (gpu->deviceId > 0 ? FF_GPU_DRIVER_CONDITION_TYPE_LUID : 0) - | FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID, + | (vendorId > 0 ? FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID : 0), .pciDeviceId = { .deviceId = deviceId, .vendorId = vendorId,