Files
fastfetch/src/detection/gpu/gpu_windows.c
T

175 lines
7.8 KiB
C
Raw Normal View History

2023-03-25 13:04:44 +08:00
#include "gpu.h"
#include "detection/gpu/gpu_driver_specific.h"
2023-03-25 13:04:44 +08:00
#include "util/windows/unicode.h"
#include "util/windows/registry.h"
#include <inttypes.h>
2023-07-01 20:27:04 +08:00
static int isGpuNameEqual(const FFGPUResult* gpu, const FFstrbuf* name)
{
return ffStrbufEqual(&gpu->name, name);
}
2023-12-21 14:53:35 +08:00
static inline bool getDriverSpecificDetectionFn(const char* vendor, __typeof__(&ffDetectNvidiaGpuInfo)* pDetectFn, const char** pDllName)
{
if (vendor == FF_GPU_VENDOR_NAME_NVIDIA)
{
*pDetectFn = ffDetectNvidiaGpuInfo;
*pDllName = "nvml.dll";
}
else if (vendor == FF_GPU_VENDOR_NAME_INTEL)
{
*pDetectFn = ffDetectIntelGpuInfo;
#ifdef _WIN64
*pDllName = "ControlLib.dll";
#else
*pDllName = "ControlLib32.dll";
#endif
}
else if (vendor == FF_GPU_VENDOR_NAME_AMD)
{
*pDetectFn = ffDetectAmdGpuInfo;
#ifdef _WIN64
*pDllName = "amd_ags_x64.dll";
#else
*pDllName = "amd_ags_x86.dll";
#endif
}
else
{
*pDetectFn = NULL;
*pDllName = NULL;
return false;
}
return true;
}
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus)
2023-03-25 13:04:44 +08:00
{
2023-07-01 14:47:14 +08:00
DISPLAY_DEVICEW displayDevice = { .cb = sizeof(displayDevice) };
wchar_t regDirectxKey[MAX_PATH] = L"SOFTWARE\\Microsoft\\DirectX\\{";
const uint32_t regDirectxKeyPrefixLength = (uint32_t) wcslen(regDirectxKey);
wchar_t regControlVideoKey[MAX_PATH] = L"SYSTEM\\CurrentControlSet\\Control\\Video\\{";
const uint32_t regControlVideoKeyPrefixLength = (uint32_t) wcslen(regControlVideoKey);
const uint32_t deviceKeyPrefixLength = strlen("\\Registry\\Machine\\") + regControlVideoKeyPrefixLength;
2023-03-25 14:19:58 +08:00
2023-03-25 13:04:44 +08:00
for (DWORD i = 0; EnumDisplayDevicesW(NULL, i, &displayDevice, 0); ++i)
{
if (displayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) continue;
2023-03-25 14:19:58 +08:00
const uint32_t deviceKeyLength = (uint32_t) wcslen(displayDevice.DeviceKey);
2023-07-01 20:27:04 +08:00
if (__builtin_expect(deviceKeyLength == 100, true))
{
if (wmemcmp(&displayDevice.DeviceKey[deviceKeyLength - 4], L"0000", 4) != 0) continue;
}
else
{
// DeviceKey can be empty. See #484
FF_STRBUF_AUTO_DESTROY gpuName = ffStrbufCreateWS(displayDevice.DeviceString);
if (ffListContains(gpus, &gpuName, (void*) isGpuNameEqual)) continue;
}
2023-03-25 13:04:44 +08:00
2023-12-29 23:00:50 +08:00
// See: https://download.nvidia.com/XFree86/Linux-x86_64/545.23.06/README/supportedchips.html
// displayDevice.DeviceID = MatchingDeviceId "PCI\\VEN_10DE&DEV_2782&SUBSYS_513417AA&REV_A1"
uint32_t vendorId = 0, deviceId = 0, subSystemId = 0, revId = 0;
swscanf(displayDevice.DeviceID, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId);
2023-03-25 13:04:44 +08:00
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
2023-12-29 23:00:50 +08:00
ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString(vendorId));
2023-05-27 22:30:38 +08:00
ffStrbufInitWS(&gpu->name, displayDevice.DeviceString);
2023-03-25 13:04:44 +08:00
ffStrbufInit(&gpu->driver);
ffStrbufInitStatic(&gpu->platformApi, "Direct3D");
2023-03-25 13:04:44 +08:00
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->type = FF_GPU_TYPE_UNKNOWN;
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = 0;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
2023-03-25 13:04:44 +08:00
2023-07-01 20:27:04 +08:00
if (deviceKeyLength == 100 && displayDevice.DeviceKey[deviceKeyPrefixLength - 1] == '{')
2023-03-25 13:04:44 +08:00
{
wmemcpy(regControlVideoKey + regControlVideoKeyPrefixLength, displayDevice.DeviceKey + deviceKeyPrefixLength, strlen("00000000-0000-0000-0000-000000000000}\\0000"));
2023-03-25 14:19:58 +08:00
FF_HKEY_AUTO_DESTROY hKey = NULL;
if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regControlVideoKey, &hKey, NULL)) continue;
2023-03-25 14:19:58 +08:00
ffRegReadStrbuf(hKey, L"DriverVersion", &gpu->driver, NULL);
wmemcpy(regDirectxKey + regDirectxKeyPrefixLength, displayDevice.DeviceKey + deviceKeyPrefixLength, strlen("00000000-0000-0000-0000-000000000000}"));
FF_HKEY_AUTO_DESTROY hDirectxKey = NULL;
if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDirectxKey, &hDirectxKey, NULL))
{
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);
}
else if (!ffRegReadUint64(hKey, L"HardwareInformation.qwMemorySize", &gpu->dedicated.total, NULL))
2023-03-25 14:19:58 +08:00
{
uint32_t vmem = 0;
if (ffRegReadUint(hKey, 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;
2023-03-25 14:19:58 +08:00
}
2023-12-29 23:00:50 +08:00
if (gpu->vendor.length == 0)
{
ffRegReadStrbuf(hKey, 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);
}
2023-03-25 13:04:44 +08:00
}
2023-10-27 21:05:03 +08:00
2023-12-21 14:53:35 +08:00
__typeof__(&ffDetectNvidiaGpuInfo) detectFn;
const char* dllName;
if (getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &dllName) && (options->temp || options->driverSpecific))
{
2023-12-29 23:00:50 +08:00
if (vendorId && deviceId && subSystemId && revId)
{
2023-12-21 14:53:35 +08:00
detectFn(
&(FFGpuDriverCondition) {
.type = FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID | FF_GPU_DRIVER_CONDITION_TYPE_LUID,
.pciDeviceId = {
.deviceId = deviceId,
.vendorId = vendorId,
.subSystemId = subSystemId,
.revId = revId,
},
.luid = gpu->deviceId,
2023-12-21 14:53:35 +08:00
},
(FFGpuDriverResult) {
.temp = options->temp ? &gpu->temperature : NULL,
2023-12-20 14:59:27 +08:00
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
.type = &gpu->type,
.frequency = &gpu->frequency,
2023-12-21 14:53:35 +08:00
},
dllName
);
}
}
2023-03-25 13:04:44 +08:00
}
return NULL;
}