Files
fastfetch/src/modules/gpu.c
T

286 lines
8.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"
#include "common/parsing.h"
2022-08-28 15:51:28 +02:00
#include "common/properties.h"
#include "detection/temps.h"
#include "detection/vulkan.h"
2022-09-04 12:43:30 +02:00
#include "detection/host/host.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-09-01 17:14:50 +02:00
#define FF_GPU_NUM_FORMAT_ARGS 4
2021-04-03 21:51:50 +02:00
2022-09-01 17:14:50 +02:00
#define FF_PCI_VENDOR_NAME_AMD "AMD"
#define FF_PCI_VENDOR_NAME_INTEL "Intel"
#define FF_PCI_VENDOR_NAME_NVIDIA "NVIDIA"
2022-08-28 15:51:28 +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
FFstrbuf gpu;
2022-09-01 17:14:50 +02:00
ffStrbufInitA(&gpu, result->vendor.length + 1 + result->device.length);
2021-11-13 18:25:35 +01:00
2022-09-01 17:14:50 +02:00
if(result->vendor.length > 0)
2021-11-13 18:25:35 +01:00
{
2022-09-01 17:14:50 +02:00
ffStrbufAppend(&gpu, &result->vendor);
2022-06-01 00:04:58 +02:00
ffStrbufAppendC(&gpu, ' ');
2021-11-13 18:25:35 +01:00
}
2022-09-01 17:14:50 +02:00
ffStrbufAppend(&gpu, &result->device);
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},
2022-09-01 17:14:50 +02:00
{FF_FORMAT_ARG_TYPE_STRBUF, &result->device},
2022-06-01 00:04:58 +02:00
{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(&gpu);
}
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
2022-09-01 17:14:50 +02:00
typedef struct PCIData
{
struct pci_access* access;
FF_LIBRARY_SYMBOL(pci_read_byte);
FF_LIBRARY_SYMBOL(pci_read_word);
FF_LIBRARY_SYMBOL(pci_lookup_name);
FF_LIBRARY_SYMBOL(pci_get_param);
} PCIData;
static bool pciIDsContains(u16 searched, const u16* ids)
{
while(*ids != 0)
{
if(*ids == searched)
return true;
ids++;
}
return false;
}
static void pciDetectVendorName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
2022-01-12 18:57:35 +01:00
{
2022-09-01 17:14:50 +02:00
if(pciIDsContains(device->vendor_id, (const u16[]) {0x1002, 0x1022, 0}))
ffStrbufAppendS(&gpu->vendor, FF_PCI_VENDOR_NAME_AMD);
else if(pciIDsContains(device->vendor_id, (const u16[]) {0x03e7, 0x8086, 0x8087, 0}))
ffStrbufAppendS(&gpu->vendor, FF_PCI_VENDOR_NAME_INTEL);
else if(pciIDsContains(device->vendor_id, (const u16[]) {0x0955, 0x10de, 0x12d2, 0}))
ffStrbufAppendS(&gpu->vendor, FF_PCI_VENDOR_NAME_NVIDIA);
if(gpu->vendor.length > 0)
2022-01-12 18:57:35 +01:00
return;
2022-09-01 17:14:50 +02:00
pci->ffpci_lookup_name(pci->access, gpu->vendor.chars, (int) ffStrbufGetFree(&gpu->vendor), PCI_LOOKUP_VENDOR, device->vendor_id);
ffStrbufRecalculateLength(&gpu->vendor);
if(ffStrbufFirstIndexS(&gpu->vendor, "AMD") < gpu->vendor.length || ffStrbufFirstIndexS(&gpu->vendor, "ATI") < gpu->vendor.length)
ffStrbufSetS(&gpu->vendor, FF_PCI_VENDOR_NAME_AMD);
else if(ffStrbufFirstIndexS(&gpu->vendor, "Intel") < gpu->vendor.length)
ffStrbufSetS(&gpu->vendor, FF_PCI_VENDOR_NAME_INTEL);
else if(ffStrbufFirstIndexS(&gpu->vendor, "NVIDIA") < gpu->vendor.length)
ffStrbufSetS(&gpu->vendor, FF_PCI_VENDOR_NAME_NVIDIA);
}
2022-09-01 17:22:35 +02:00
static void drmDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
2022-09-01 17:14:50 +02:00
{
FFstrbuf query;
ffStrbufInit(&query);
2022-09-01 17:22:35 +02:00
ffStrbufAppendF(&query, "%X, %X,", device->device_id, pci->ffpci_read_byte(device, PCI_REVISION_ID));
2022-09-01 17:14:50 +02:00
2022-09-03 10:53:30 +02:00
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/libdrm/amdgpu.ids", query.chars, &gpu->device);
2022-09-01 17:14:50 +02:00
ffStrbufDestroy(&query);
const char* removeStrings[] = {
2022-09-03 10:53:30 +02:00
"AMD ", "ATI ",
2022-09-01 17:14:50 +02:00
" (TM)", "(TM)",
" Graphics Adapter", " Graphics", " Series", " Edition"
};
ffStrbufRemoveStringsA(&gpu->device, sizeof(removeStrings) / sizeof(removeStrings[0]), removeStrings);
}
static void pciDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
{
if(ffStrbufCompS(&gpu->vendor, FF_PCI_VENDOR_NAME_AMD) == 0)
{
2022-09-01 17:22:35 +02:00
drmDetectDeviceName(gpu, pci, device);
2022-09-01 17:14:50 +02:00
if(gpu->device.length > 0)
return;
}
pci->ffpci_lookup_name(pci->access, gpu->device.chars, (int) ffStrbufGetFree(&gpu->device), PCI_LOOKUP_DEVICE, device->vendor_id, device->device_id);
ffStrbufRecalculateLength(&gpu->device);
}
static void pciDetectDriverName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
{
const char* base = pci->ffpci_get_param(pci->access, "sysfs.path");
2022-01-12 18:57:35 +01:00
if(!ffStrSet(base))
return;
FFstrbuf path;
ffStrbufInitA(&path, 64);
2022-09-01 17:14:50 +02:00
ffStrbufAppendF(&path, "%s/devices/%04x:%02x:%02x.%d/driver", base, device->domain, device->bus, device->dev, device->func);
2022-01-12 18:57:35 +01:00
2022-09-01 17:14:50 +02:00
ffStrbufEnsureFree(&gpu->driver, 1023);
ssize_t resultLength = readlink(path.chars, gpu->driver.chars, gpu->driver.allocated - 1); //-1 for null terminator
2022-01-12 18:57:35 +01:00
if(resultLength > 0)
{
2022-09-01 17:14:50 +02:00
gpu->driver.length = (uint32_t) resultLength;
gpu->driver.chars[resultLength] = '\0';
ffStrbufSubstrAfterLastC(&gpu->driver, '/');
2022-01-12 18:57:35 +01:00
}
ffStrbufDestroy(&path);
}
2022-09-01 17:14:50 +02:00
static void pciDetectTemperatur(FFGPUResult* gpu, struct pci_dev* device)
2022-06-17 23:38:33 +02:00
{
2022-09-01 17:14:50 +02:00
const FFTempsResult* tempsResult = ffDetectTemps();
2022-06-17 23:38:33 +02:00
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
2022-09-01 17:14:50 +02:00
if(tempClass == device->device_class * 256)
{
gpu->temperature = tempValue->value;
return;
}
2022-06-17 23:38:33 +02:00
}
}
2022-09-01 17:14:50 +02:00
static void pciHandleDevice(FFlist* results, PCIData* pci, struct pci_dev* device)
2022-08-28 15:51:28 +02:00
{
2022-09-01 17:14:50 +02:00
device->device_class = pci->ffpci_read_word(device, PCI_CLASS_DEVICE);
2022-09-01 17:14:50 +02:00
char class[1024];
pci->ffpci_lookup_name(pci->access, class, sizeof(class) - 1, PCI_LOOKUP_CLASS, device->device_class);
2022-08-28 15:51:28 +02:00
2022-09-01 17:14:50 +02:00
if(
strcasecmp("VGA compatible controller", class) != 0 &&
strcasecmp("3D controller", class) != 0 &&
strcasecmp("Display controller", class) != 0
) return;
2022-08-28 15:51:28 +02:00
2022-09-01 17:14:50 +02:00
device->vendor_id = pci->ffpci_read_word(device, PCI_VENDOR_ID);
device->device_id = pci->ffpci_read_word(device, PCI_DEVICE_ID);
2022-08-28 15:51:28 +02:00
2022-09-01 17:14:50 +02:00
FFGPUResult* gpu = ffListAdd(results);
2022-08-28 15:51:28 +02:00
2022-09-01 17:14:50 +02:00
ffStrbufInit(&gpu->vendor);
pciDetectVendorName(gpu, pci, device);
ffStrbufInit(&gpu->device);
pciDetectDeviceName(gpu, pci, device);
ffStrbufInit(&gpu->driver);
pciDetectDriverName(gpu, pci, device);
gpu->temperature = FF_GPU_TEMP_UNSET;
pciDetectTemperatur(gpu, device);
2022-08-28 15:51:28 +02:00
}
2022-06-01 00:04:58 +02:00
static bool pciPrintGPUs(FFinstance* instance)
2021-04-03 21:51:50 +02:00
{
2022-09-01 17:14:50 +02:00
PCIData pci;
FF_LIBRARY_LOAD(libpci, instance->config.libPCI, false, "libpci.so", 4)
FF_LIBRARY_LOAD_SYMBOL(libpci, pci_alloc, false)
FF_LIBRARY_LOAD_SYMBOL(libpci, pci_init, false)
FF_LIBRARY_LOAD_SYMBOL(libpci, pci_scan_bus, false)
FF_LIBRARY_LOAD_SYMBOL(libpci, pci_cleanup, false)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(libpci, pci.ffpci_read_byte, pci_read_byte, false)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(libpci, pci.ffpci_read_word, pci_read_word, false)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(libpci, pci.ffpci_lookup_name, pci_lookup_name, false)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(libpci, pci.ffpci_get_param, pci_get_param, false)
2022-06-01 00:04:58 +02:00
FFlist results;
ffListInit(&results, sizeof(FFGPUResult));
2021-02-18 22:25:36 +01:00
2022-09-01 17:14:50 +02:00
pci.access = ffpci_alloc();
ffpci_init(pci.access);
ffpci_scan_bus(pci.access);
2021-11-13 18:25:35 +01:00
2022-09-01 17:14:50 +02:00
struct pci_dev* device = pci.access->devices;
while(device != NULL)
2021-11-13 18:25:35 +01:00
{
2022-09-01 17:14:50 +02:00
pciHandleDevice(&results, &pci, device);
device = device->next;
2021-11-13 18:25:35 +01:00
}
2022-09-01 17:14:50 +02:00
ffpci_cleanup(pci.access);
dlclose(libpci);
2021-11-13 18:25:35 +01:00
2022-09-01 17:14:50 +02:00
printGPUList(instance, &results);
for(uint32_t i = 0; i < results.length; i++)
2021-11-13 18:25:35 +01:00
{
2022-09-01 17:14:50 +02:00
FFGPUResult* gpu = ffListGet(&results, i);
ffStrbufDestroy(&gpu->vendor);
ffStrbufDestroy(&gpu->device);
ffStrbufDestroy(&gpu->driver);
2021-11-13 18:25:35 +01:00
}
2021-03-19 20:57:07 +01:00
2022-06-01 00:04:58 +02:00
ffListDestroy(&results);
2022-09-01 17:14:50 +02:00
return results.length > 0;
2022-06-01 00:04:58 +02:00
}
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-09-04 12:43:30 +02:00
if(ffStrbufCompS(&ffDetectHost()->productName, FF_HOST_PRODUCT_NAME_WSL) == 0)
{
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
}