From b90d543afcf4615e12f5baf7fa2e516bad007327 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 11 Feb 2023 02:29:26 +0800 Subject: [PATCH] GPU (Windows): support vmem total / usage detection #416 vmem usage detection is guarded behind `--allow-slow-operations` because it's really slow sometimes --- src/detection/gpu/gpu.h | 9 ++++- src/detection/gpu/gpu_apple.c | 2 + src/detection/gpu/gpu_linux.c | 3 ++ src/detection/gpu/gpu_windows.cpp | 67 +++++++++++++++++++------------ src/detection/vulkan.c | 6 ++- src/modules/gpu.c | 24 +++++++++-- 6 files changed, 78 insertions(+), 33 deletions(-) diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h index 5d38ca1ac..15b2de74b 100644 --- a/src/detection/gpu/gpu.h +++ b/src/detection/gpu/gpu.h @@ -7,6 +7,7 @@ #define FF_GPU_TEMP_UNSET (0/0.0) #define FF_GPU_CORE_COUNT_UNSET -1 +#define FF_GPU_VMEM_SIZE_UNSET ((uint64_t)-1) extern const char* FF_GPU_VENDOR_NAME_APPLE; extern const char* FF_GPU_VENDOR_NAME_AMD; @@ -15,20 +16,24 @@ extern const char* FF_GPU_VENDOR_NAME_NVIDIA; typedef enum FFGpuType { + FF_GPU_TYPE_UNKNOWN, FF_GPU_TYPE_INTEGRATED, FF_GPU_TYPE_DISCRETE, - FF_GPU_TYPE_UNKNOWN } FFGpuType; typedef struct FFGPUResult { + uint64_t id; FFGpuType type; FFstrbuf vendor; FFstrbuf name; FFstrbuf driver; double temperature; - uint64_t memory; int coreCount; + uint64_t dedicatedTotal; + uint64_t dedicatedUsed; + uint64_t sharedTotal; + uint64_t sharedUsed; } FFGPUResult; const FFlist* ffDetectGPU(const FFinstance* instance); diff --git a/src/detection/gpu/gpu_apple.c b/src/detection/gpu/gpu_apple.c index 2bea79896..bc571d7e2 100644 --- a/src/detection/gpu/gpu_apple.c +++ b/src/detection/gpu/gpu_apple.c @@ -60,6 +60,8 @@ const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance) FFGPUResult* gpu = ffListAdd(gpus); + gpu->id = 0; + gpu->dedicatedTotal = gpu->dedicatedUsed = gpu->sharedTotal = gpu->sharedUsed = FF_GPU_VMEM_SIZE_UNSET; gpu->type = FF_GPU_TYPE_UNKNOWN; ffStrbufInit(&gpu->vendor); diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index ae7239d43..19f4b455a 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -199,6 +199,9 @@ static void pciHandleDevice(const FFinstance* instance, FFlist* results, PCIData FFGPUResult* gpu = ffListAdd(results); + gpu->id = 0; + gpu->dedicatedTotal = gpu->dedicatedUsed = gpu->sharedTotal = gpu->sharedUsed = FF_GPU_VMEM_SIZE_UNSET; + ffStrbufInit(&gpu->vendor); pciDetectVendorName(gpu, pci, device); diff --git a/src/detection/gpu/gpu_windows.cpp b/src/detection/gpu/gpu_windows.cpp index 8e6d74ef2..587ca96e0 100644 --- a/src/detection/gpu/gpu_windows.cpp +++ b/src/detection/gpu/gpu_windows.cpp @@ -48,6 +48,10 @@ static const char* detectWithRegistry(FFlist* gpus) gpu->temperature = FF_GPU_TEMP_UNSET; gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->type = FF_GPU_TYPE_UNKNOWN; + gpu->id = 0; + gpu->dedicatedTotal = gpu->dedicatedUsed = gpu->sharedTotal = gpu->sharedUsed = FF_GPU_VMEM_SIZE_UNSET; + + ffRegReadUint64(hSubKey, L"AdapterLuid", &gpu->id, nullptr); ffRegReadStrbuf(hSubKey, L"Description", &gpu->name, nullptr); @@ -55,10 +59,18 @@ static const char* detectWithRegistry(FFlist* gpus) if(ffRegReadUint(hSubKey, L"VendorId", &vendorId, nullptr)) ffStrbufAppendS(&gpu->vendor, ffGetGPUVendorString(vendorId)); - uint64_t dedicatedVideoMemory; + uint64_t dedicatedVideoMemory = 0; if(ffRegReadUint64(hSubKey, L"DedicatedVideoMemory", &dedicatedVideoMemory, nullptr)) gpu->type = dedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; + uint64_t dedicatedSystemMemory, sharedSystemMemory; + if(ffRegReadUint64(hSubKey, L"DedicatedSystemMemory", &dedicatedSystemMemory, nullptr) && + ffRegReadUint64(hSubKey, L"SharedSystemMemory", &sharedSystemMemory, nullptr)) + { + gpu->dedicatedTotal = dedicatedVideoMemory + dedicatedSystemMemory; + gpu->sharedTotal = sharedSystemMemory; + } + uint64_t driverVersion; if(ffRegReadUint64(hSubKey, L"DriverVersion", &driverVersion, nullptr)) { @@ -90,16 +102,21 @@ static const char* detectWithDxgi(FFlist* gpus) continue; FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); + gpu->dedicatedTotal = gpu->dedicatedUsed = gpu->sharedTotal = gpu->sharedUsed = FF_GPU_VMEM_SIZE_UNSET; ffStrbufInit(&gpu->vendor); ffStrbufAppendS(&gpu->vendor, ffGetGPUVendorString(desc.VendorId)); + gpu->id = (uint64_t&)desc.AdapterLuid; + ffStrbufInit(&gpu->name); ffStrbufSetWS(&gpu->name, desc.Description); ffStrbufInit(&gpu->driver); gpu->type = desc.DedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; + gpu->dedicatedTotal = desc.DedicatedVideoMemory + desc.DedicatedSystemMemory; + gpu->sharedTotal = desc.SharedSystemMemory; adapter->Release(); @@ -112,46 +129,44 @@ static const char* detectWithDxgi(FFlist* gpus) return nullptr; } -static const char* detectWithWmi(FFlist* gpus) +static const char* detectMemoryUsage(FFlist* gpus) { - FFWmiQuery query(L"SELECT Name, AdapterCompatibility, DriverVersion FROM Win32_VideoController", nullptr); + FFWmiQuery query(L"SELECT Name, DedicatedUsage, SharedUsage FROM Win32_PerfRawData_GPUPerformanceCounters_GPUAdapterMemory", nullptr); if(!query) return "Query WMI service failed"; + FF_STRBUF_AUTO_DESTROY name; + ffStrbufInit(&name); + while(FFWmiRecord record = query.next()) { - FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); + record.getString(L"Name", &name); // luid_0x00000000_0x000146E8_phys_0 + assert(name.length == strlen("luid_0x00000000_0x000146E8_phys_0")); + ffStrbufSubstrBefore(&name, strlen("luid_0x00000000_0x000146E8")); // luid_0x00000000_0x000146E8 + ffStrbufSubstrAfter(&name, strlen("luid_0x00000000_0x") - 1); // 000146E8 + uint64_t luid = strtoull(name.chars, nullptr, 16); - gpu->type = FF_GPU_TYPE_UNKNOWN; - - ffStrbufInit(&gpu->vendor); - record.getString(L"AdapterCompatibility", &gpu->vendor); - if(ffStrbufStartsWithS(&gpu->vendor, "Intel ")) + FF_LIST_FOR_EACH(FFGPUResult, gpu, *gpus) { - //Intel returns "Intel Corporation", not sure about AMD - ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL); + if (gpu->id != luid) continue; + record.getUnsigned(L"DedicatedUsage", &gpu->dedicatedUsed); + record.getUnsigned(L"SharedUsage", &gpu->sharedUsed); + break; } - - ffStrbufInit(&gpu->name); - record.getString(L"Name", &gpu->name); - - ffStrbufInit(&gpu->driver); - record.getString(L"DriverVersion", &gpu->driver); - - gpu->temperature = FF_GPU_TEMP_UNSET; - gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; } - return nullptr; + return NULL; } extern "C" const char* ffDetectGPUImpl(FFlist* gpus, FF_MAYBE_UNUSED const FFinstance* instance) { - if (instance->config.allowSlowOperations) - return detectWithWmi(gpus); + const char* error = detectWithRegistry(gpus); + if (error) + error = detectWithDxgi(gpus); - if (!detectWithRegistry(gpus)) - return nullptr; - return detectWithDxgi(gpus); + if (!error && gpus->length > 0 && instance->config.allowSlowOperations) + detectMemoryUsage(gpus); + + return error; } diff --git a/src/detection/vulkan.c b/src/detection/vulkan.c index 93d5ea2da..5d8b3f4f9 100644 --- a/src/detection/vulkan.c +++ b/src/detection/vulkan.c @@ -195,12 +195,14 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu gpu->type = FF_GPU_TYPE_INTEGRATED; else gpu->type = FF_GPU_TYPE_DISCRETE; + gpu->id = physicalDeviceProperties.properties.deviceID; + ffStrbufInitS(&gpu->vendor, ffGetGPUVendorString(physicalDeviceProperties.properties.vendorID)); + ffStrbufInitF(&gpu->driver, "%X", (unsigned) physicalDeviceProperties.properties.driverVersion); //No way to detect those using vulkan - ffStrbufInit(&gpu->vendor); - ffStrbufInit(&gpu->driver); gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->temperature = FF_GPU_TEMP_UNSET; + gpu->dedicatedTotal = gpu->dedicatedUsed = gpu->sharedTotal = gpu->sharedUsed = 0; //VkPhysicalDeviceMemoryProperties? } //If the highest device version is lower than the instance version, use it as our vulkan version diff --git a/src/modules/gpu.c b/src/modules/gpu.c index 6c673df36..3ff02c5ff 100644 --- a/src/modules/gpu.c +++ b/src/modules/gpu.c @@ -1,4 +1,6 @@ #include "fastfetch.h" +#include "common/bar.h" +#include "common/parsing.h" #include "common/printing.h" #include "detection/host/host.h" #include "detection/gpu/gpu.h" @@ -14,7 +16,7 @@ static void printGPUResult(FFinstance* instance, uint8_t index, const FFGPUResul { ffPrintLogoAndKey(instance, FF_GPU_MODULE_NAME, index, &instance->config.gpu.key); - FFstrbuf output; + FF_STRBUF_AUTO_DESTROY output; ffStrbufInitA(&output, gpu->vendor.length + 1 + gpu->name.length); if(gpu->vendor.length > 0 && !ffStrbufStartsWith(&gpu->name, &gpu->vendor)) @@ -31,9 +33,25 @@ static void printGPUResult(FFinstance* instance, uint8_t index, const FFGPUResul if(gpu->temperature == gpu->temperature) //FF_GPU_TEMP_UNSET ffStrbufAppendF(&output, " - %.1f°C", gpu->temperature); - ffStrbufPutTo(&output, stdout); + if(gpu->dedicatedTotal != FF_GPU_VMEM_SIZE_UNSET) + { + ffStrbufAppendS(&output, " ("); - ffStrbufDestroy(&output); + if(gpu->dedicatedUsed != FF_GPU_VMEM_SIZE_UNSET) + { + ffParseSize(gpu->dedicatedUsed, instance->config.binaryPrefixType, &output); + ffStrbufAppendS(&output, " / "); + } + ffParseSize(gpu->dedicatedTotal, instance->config.binaryPrefixType, &output); + if(gpu->dedicatedUsed != FF_GPU_VMEM_SIZE_UNSET) + { + ffStrbufAppendS(&output, ", "); + ffAppendPercentNum(instance, &output, (uint8_t) (gpu->dedicatedUsed * 100 / gpu->dedicatedTotal), 50, 80, false); + } + ffStrbufAppendC(&output, ')'); + } + + ffStrbufPutTo(&output, stdout); } else {