Files
fastfetch/src/modules/gpu.c
T

219 lines
6.9 KiB
C
Raw Normal View History

2021-02-18 22:25:36 +01:00
#include "fastfetch.h"
#include "common/printing.h"
#include "common/caching.h"
2021-02-18 22:25:36 +01:00
2022-07-17 16:11:08 +02:00
#include <stdlib.h>
2021-04-15 18:59:26 +02:00
#define FF_GPU_MODULE_NAME "GPU"
2022-06-17 23:38:33 +02:00
#define FF_GPU_NUM_FORMAT_ARGS 6
2021-04-03 21:51:50 +02:00
2022-06-01 00:04:58 +02:00
static void printGPUResult(FFinstance* instance, uint8_t index, FFcache* cache, FFGPUResult* result)
2021-11-13 18:25:35 +01:00
{
2022-06-01 00:04:58 +02:00
const char* vendorPretty;
if(ffStrbufIgnCaseCompS(&result->vendor, "Advanced Micro Devices, Inc. [AMD/ATI]") == 0)
vendorPretty = "AMD ATI";
else if(ffStrbufIgnCaseCompS(&result->vendor, "NVIDIA Corporation") == 0)
vendorPretty = "Nvidia";
else if(ffStrbufIgnCaseCompS(&result->vendor, "Intel Corporation") == 0)
vendorPretty = "Intel";
else
vendorPretty = result->vendor.chars;
2022-06-01 00:04:58 +02:00
FFstrbuf namePretty;
ffStrbufInitCopy(&namePretty, &result->name);
ffStrbufSubstrBeforeLastC(&namePretty, ']');
ffStrbufSubstrAfterFirstC(&namePretty, '[');
2021-11-13 18:25:35 +01:00
2022-06-01 00:04:58 +02:00
FFstrbuf gpu;
ffStrbufInitA(&gpu, result->vendor.length + 1 + namePretty.length);
2021-11-13 18:25:35 +01:00
2022-06-01 00:04:58 +02:00
if(ffStrSet(vendorPretty))
2021-11-13 18:25:35 +01:00
{
2022-06-01 00:04:58 +02:00
ffStrbufAppendS(&gpu, vendorPretty);
ffStrbufAppendC(&gpu, ' ');
2021-11-13 18:25:35 +01:00
}
2022-06-01 00:04:58 +02:00
ffStrbufAppend(&gpu, &namePretty);
2021-11-13 18:25:35 +01:00
2022-06-17 18:15:36 +02:00
ffPrintAndAppendToCache(instance, FF_GPU_MODULE_NAME, index, &instance->config.gpu, cache, &gpu, FF_GPU_NUM_FORMAT_ARGS, (FFformatarg[]){
2022-06-01 00:04:58 +02:00
{FF_FORMAT_ARG_TYPE_STRBUF, &result->vendor},
{FF_FORMAT_ARG_TYPE_STRING, vendorPretty},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->name},
{FF_FORMAT_ARG_TYPE_STRBUF, &namePretty},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->driver},
2022-06-17 23:38:33 +02:00
{FF_FORMAT_ARG_TYPE_DOUBLE, &result->temperature}
2022-06-01 00:04:58 +02:00
});
2021-11-13 18:25:35 +01:00
2022-06-01 00:04:58 +02:00
ffStrbufDestroy(&result->vendor);
ffStrbufDestroy(&result->name);
ffStrbufDestroy(&result->driver);
ffStrbufDestroy(&gpu);
ffStrbufDestroy(&namePretty);
}
2021-11-13 18:25:35 +01:00
2022-06-01 00:04:58 +02:00
static void printGPUList(FFinstance* instance, const FFlist* list)
{
FFcache cache;
ffCacheOpenWrite(instance, FF_GPU_MODULE_NAME, &cache);
2021-11-13 18:25:35 +01:00
2022-06-01 00:04:58 +02:00
for(uint8_t i = 0; i < (uint8_t) list->length; i++)
printGPUResult(instance, list->length == 1 ? 0 : (uint8_t) (i + 1), &cache, ffListGet(list, i));
2021-11-13 18:25:35 +01:00
2022-06-01 00:04:58 +02:00
ffCacheClose(&cache);
}
2021-11-13 18:25:35 +01:00
#ifdef FF_HAVE_LIBPCI
#include "common/library.h"
2022-06-18 14:25:31 +02:00
#include <string.h>
2022-01-12 18:57:35 +01:00
#include <unistd.h>
2022-06-18 14:25:31 +02:00
#include <pci/pci.h>
2022-01-12 18:57:35 +01:00
//see https://github.com/pciutils/pciutils/blob/5bdf63b6b1bc35b59c4b3f47f7ca83ca1868155b/ls-kernel.c#L220
static void pciGetDriver(struct pci_dev* dev, FFstrbuf* driver, char*(*ffpci_get_param)(struct pci_access*, char*))
{
if(dev->access->method != PCI_ACCESS_SYS_BUS_PCI)
return;
const char* base = ffpci_get_param(dev->access, "sysfs.path");
if(!ffStrSet(base))
return;
FFstrbuf path;
ffStrbufInitA(&path, 64);
ffStrbufAppendF(&path, "%s/devices/%04x:%02x:%02x.%d/driver", base, dev->domain, dev->bus, dev->dev, dev->func);
ffStrbufEnsureFree(driver, 1023);
ssize_t resultLength = readlink(path.chars, driver->chars, driver->allocated - 1); //-1 for null terminator
if(resultLength > 0)
{
driver->length = (uint32_t) resultLength;
driver->chars[resultLength] = '\0';
ffStrbufSubstrAfterLastC(driver, '/');
}
ffStrbufDestroy(&path);
}
2022-06-17 23:38:33 +02:00
static double pciGetTemperatur(const FFinstance* instance, uint16_t deviceClass)
{
const FFTempsResult* tempsResult = ffDetectTemps(instance);
for(uint32_t i = 0; i < tempsResult->values.length; i++)
{
FFTempValue* tempValue = ffListGet(&tempsResult->values, i);
uint32_t tempClass;
if(sscanf(tempValue->deviceClass.chars, "%x", &tempClass) != 1)
continue;
//The kernel exposes the device class multiplied by 256 for some reason
if(tempClass == deviceClass * 256)
return tempValue->value;
}
return 0.0 / 0.0; //NaN
}
2022-06-01 00:04:58 +02:00
static bool pciPrintGPUs(FFinstance* instance)
2021-04-03 21:51:50 +02:00
{
2022-06-01 00:04:58 +02:00
FF_LIBRARY_LOAD(pci, instance->config.libPCI, false, "libpci.so", 4)
FF_LIBRARY_LOAD_SYMBOL(pci, pci_alloc, false)
FF_LIBRARY_LOAD_SYMBOL(pci, pci_init, false)
FF_LIBRARY_LOAD_SYMBOL(pci, pci_scan_bus, false)
FF_LIBRARY_LOAD_SYMBOL(pci, pci_fill_info, false)
FF_LIBRARY_LOAD_SYMBOL(pci, pci_lookup_name, false)
FF_LIBRARY_LOAD_SYMBOL(pci, pci_get_param, false)
FF_LIBRARY_LOAD_SYMBOL(pci, pci_cleanup, false)
FFlist results;
ffListInit(&results, sizeof(FFGPUResult));
2021-02-18 22:25:36 +01:00
2021-11-13 18:25:35 +01:00
struct pci_access *pacc = ffpci_alloc();
ffpci_init(pacc);
ffpci_scan_bus(pacc);
struct pci_dev* dev;
for (dev=pacc->devices; dev; dev=dev->next)
{
ffpci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_CLASS);
char class[1024];
ffpci_lookup_name(pacc, class, sizeof(class), PCI_LOOKUP_CLASS, dev->device_class);
if(
strcasecmp("VGA compatible controller", class) == 0 ||
strcasecmp("3D controller", class) == 0 ||
strcasecmp("Display controller", class) == 0
) {
2022-06-01 00:04:58 +02:00
FFGPUResult* result = ffListAdd(&results);
2021-11-13 18:25:35 +01:00
ffStrbufInitA(&result->vendor, 256);
2022-06-17 23:38:33 +02:00
ffpci_lookup_name(pacc, result->vendor.chars, (int) ffStrbufGetFree(&result->vendor), PCI_LOOKUP_VENDOR, dev->vendor_id, dev->device_id);
2021-11-13 18:25:35 +01:00
ffStrbufRecalculateLength(&result->vendor);
ffStrbufInitA(&result->name, 256);
2022-06-17 23:38:33 +02:00
ffpci_lookup_name(pacc, result->name.chars, (int) ffStrbufGetFree(&result->name), PCI_LOOKUP_DEVICE, dev->vendor_id, dev->device_id);
2021-11-13 18:25:35 +01:00
ffStrbufRecalculateLength(&result->name);
2022-01-12 18:57:35 +01:00
ffStrbufInit(&result->driver);
2022-06-17 23:38:33 +02:00
result->temperature = 0;
//We only need it for the format string, so don't detect it if it isn't needed
if(instance->config.gpu.outputFormat.length > 0)
{
2022-01-12 18:57:35 +01:00
pciGetDriver(dev, &result->driver, ffpci_get_param);
2022-06-17 23:38:33 +02:00
result->temperature = pciGetTemperatur(instance, dev->device_class);
}
2021-11-13 18:25:35 +01:00
};
}
ffpci_cleanup(pacc);
dlclose(pci);
2022-06-01 00:04:58 +02:00
if(results.length == 0)
2021-11-13 18:25:35 +01:00
{
2022-06-01 00:04:58 +02:00
ffListDestroy(&results);
return false;
2021-11-13 18:25:35 +01:00
}
2021-03-19 20:57:07 +01:00
2022-06-01 00:04:58 +02:00
printGPUList(instance, &results);
2021-02-22 16:52:51 +01:00
2022-06-01 00:04:58 +02:00
ffListDestroy(&results);
return true;
}
2021-04-03 21:51:50 +02:00
2022-06-01 00:04:58 +02:00
#endif
static bool vulkanPrintGPUs(FFinstance* instance)
{
const FFVulkanResult* result = ffDetectVulkan(instance);
if(result->devices.length == 0)
return false;
printGPUList(instance, &result->devices);
return true;
2021-02-18 22:25:36 +01:00
}
2021-11-13 18:25:35 +01:00
void ffPrintGPU(FFinstance* instance)
2021-02-18 22:25:36 +01:00
{
2022-06-17 18:15:36 +02:00
if(ffPrintFromCache(instance, FF_GPU_MODULE_NAME, &instance->config.gpu, FF_GPU_NUM_FORMAT_ARGS))
2021-11-13 18:25:35 +01:00
return;
2021-02-28 17:38:26 +01:00
2022-07-17 16:11:08 +02:00
if(
getenv("WSLENV") != NULL ||
getenv("WSL_DISTRO") != NULL ||
getenv("WSL_INTEROP") != NULL
) {
2022-07-20 20:44:16 +02:00
ffPrintError(instance, FF_GPU_MODULE_NAME, 0, &instance->config.gpu, "WSL doesn't expose senseful GPU names");
2022-07-17 16:11:08 +02:00
return;
}
2021-11-13 18:25:35 +01:00
#ifdef FF_HAVE_LIBPCI
2022-06-01 00:04:58 +02:00
if(pciPrintGPUs(instance))
return;
2021-11-13 18:25:35 +01:00
#endif
2021-04-03 21:51:50 +02:00
2022-06-01 00:04:58 +02:00
if(vulkanPrintGPUs(instance))
return;
2022-06-17 18:15:36 +02:00
ffPrintError(instance, FF_GPU_MODULE_NAME, 0, &instance->config.gpu, "No GPUs found.");
2021-11-13 18:25:35 +01:00
}