mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2025-02-20 11:43:27 +08:00
Separate gpu detection and printing logic
This commit is contained in:
parent
0f70cb408f
commit
54cb74c999
@ -167,6 +167,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/detection/host/host.c
|
||||
src/detection/os/os.c
|
||||
src/detection/cpu/cpu.c
|
||||
src/detection/gpu/gpu.c
|
||||
src/detection/memory/memory.c
|
||||
src/detection/displayserver/displayServer.c
|
||||
src/detection/displayserver/wayland.c
|
||||
@ -219,6 +220,7 @@ if(APPLE)
|
||||
src/detection/host/host_apple.c
|
||||
src/detection/os/os_apple.c
|
||||
src/detection/cpu/cpu_apple.c
|
||||
src/detection/gpu/gpu_apple.c
|
||||
src/detection/memory/memory_apple.c
|
||||
)
|
||||
elseif(ANDROID)
|
||||
@ -226,6 +228,7 @@ elseif(ANDROID)
|
||||
src/detection/host/host_android.c
|
||||
src/detection/os/os_android.c
|
||||
src/detection/cpu/cpu_linux.c
|
||||
src/detection/gpu/gpu_android.c
|
||||
src/detection/memory/memory_linux.c
|
||||
)
|
||||
elseif(UNIX)
|
||||
@ -233,6 +236,7 @@ elseif(UNIX)
|
||||
src/detection/host/host_linux.c
|
||||
src/detection/os/os_linux.c
|
||||
src/detection/cpu/cpu_linux.c
|
||||
src/detection/gpu/gpu_linux.c
|
||||
src/detection/memory/memory_linux.c
|
||||
)
|
||||
else()
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/format.h"
|
||||
#include "common/parsing.h"
|
||||
|
||||
void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg)
|
||||
{
|
||||
@ -63,11 +64,10 @@ static inline void appendEmptyPlaceholder(FFstrbuf* buffer, const char* placehol
|
||||
static inline bool formatArgSet(const FFformatarg* arg)
|
||||
{
|
||||
return arg->value != NULL && (
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_DOUBLE && *(double*)arg->value > 0) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_DOUBLE && *(double*)arg->value == *(double*)arg->value) || //NaN
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_DOUBLE && *(double*)arg->value > 0.0) || //Also is false for NaN
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_INT && *(int*)arg->value > 0) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_STRBUF && ((FFstrbuf*)arg->value)->length > 0) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_STRING && *(const char*)arg->value != '\0') ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_STRING && ffStrSet(arg->value)) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_UINT8 && *(uint8_t*)arg->value > 0) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_UINT16 && *(uint16_t*)arg->value > 0) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_UINT && *(uint32_t*)arg->value > 0)
|
||||
|
12
src/detection/gpu/gpu.c
Normal file
12
src/detection/gpu/gpu.c
Normal file
@ -0,0 +1,12 @@
|
||||
#include "gpu.h"
|
||||
#include "detection/internal.h"
|
||||
|
||||
void ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance);
|
||||
|
||||
const FFlist* ffDetectGPU(const FFinstance* instance)
|
||||
{
|
||||
FF_DETECTION_INTERNAL_GUARD(FFlist,
|
||||
ffListInit(&result, sizeof(FFGPUResult));
|
||||
ffDetectGPUImpl(&result, instance);
|
||||
);
|
||||
}
|
20
src/detection/gpu/gpu.h
Normal file
20
src/detection/gpu/gpu.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_detection_gpu_gpu
|
||||
#define FF_INCLUDED_detection_gpu_gpu
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
#define FF_GPU_TEMP_UNSET (0/0.0)
|
||||
|
||||
typedef struct FFGPUResult
|
||||
{
|
||||
FFstrbuf vendor;
|
||||
FFstrbuf name;
|
||||
FFstrbuf driver;
|
||||
double temperature;
|
||||
} FFGPUResult;
|
||||
|
||||
const FFlist* ffDetectGPU(const FFinstance* instance);
|
||||
|
||||
#endif
|
6
src/detection/gpu/gpu_android.c
Normal file
6
src/detection/gpu/gpu_android.c
Normal file
@ -0,0 +1,6 @@
|
||||
#include "gpu.h"
|
||||
|
||||
void ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance)
|
||||
{
|
||||
FF_UNUSED(gpus, instance);
|
||||
}
|
6
src/detection/gpu/gpu_apple.c
Normal file
6
src/detection/gpu/gpu_apple.c
Normal file
@ -0,0 +1,6 @@
|
||||
#include "gpu.h"
|
||||
|
||||
void ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance)
|
||||
{
|
||||
FF_UNUSED(gpus, instance);
|
||||
}
|
208
src/detection/gpu/gpu_linux.c
Normal file
208
src/detection/gpu/gpu_linux.c
Normal file
@ -0,0 +1,208 @@
|
||||
#include "gpu.h"
|
||||
#include "detection/vulkan.h"
|
||||
|
||||
#define FF_GPU_VENDOR_NAME_AMD "AMD"
|
||||
#define FF_GPU_VENDOR_NAME_INTEL "Intel"
|
||||
#define FF_GPU_VENDOR_NAME_NVIDIA "NVIDIA"
|
||||
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
#include "common/library.h"
|
||||
#include "common/properties.h"
|
||||
#include "common/parsing.h"
|
||||
#include "detection/temps.h"
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <pci/pci.h>
|
||||
|
||||
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)
|
||||
{
|
||||
if(pciIDsContains(device->vendor_id, (const u16[]) {0x1002, 0x1022, 0}))
|
||||
ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
|
||||
else if(pciIDsContains(device->vendor_id, (const u16[]) {0x03e7, 0x8086, 0x8087, 0}))
|
||||
ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
|
||||
else if(pciIDsContains(device->vendor_id, (const u16[]) {0x0955, 0x10de, 0x12d2, 0}))
|
||||
ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
|
||||
|
||||
if(gpu->vendor.length > 0)
|
||||
return;
|
||||
|
||||
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_GPU_VENDOR_NAME_AMD);
|
||||
else if(ffStrbufFirstIndexS(&gpu->vendor, "Intel") < gpu->vendor.length)
|
||||
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
|
||||
else if(ffStrbufFirstIndexS(&gpu->vendor, "NVIDIA") < gpu->vendor.length)
|
||||
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
|
||||
}
|
||||
|
||||
static void drmDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
|
||||
{
|
||||
FFstrbuf query;
|
||||
ffStrbufInit(&query);
|
||||
ffStrbufAppendF(&query, "%X, %X,", device->device_id, pci->ffpci_read_byte(device, PCI_REVISION_ID));
|
||||
|
||||
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/libdrm/amdgpu.ids", query.chars, &gpu->name);
|
||||
|
||||
ffStrbufDestroy(&query);
|
||||
|
||||
const char* removeStrings[] = {
|
||||
"AMD ", "ATI ",
|
||||
" (TM)", "(TM)",
|
||||
" Graphics Adapter", " Graphics", " Series", " Edition"
|
||||
};
|
||||
ffStrbufRemoveStringsA(&gpu->name, sizeof(removeStrings) / sizeof(removeStrings[0]), removeStrings);
|
||||
}
|
||||
|
||||
static void pciDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
|
||||
{
|
||||
if(ffStrbufCompS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD) == 0)
|
||||
{
|
||||
drmDetectDeviceName(gpu, pci, device);
|
||||
if(gpu->name.length > 0)
|
||||
return;
|
||||
}
|
||||
|
||||
pci->ffpci_lookup_name(pci->access, gpu->name.chars, (int) ffStrbufGetFree(&gpu->name), PCI_LOOKUP_DEVICE, device->vendor_id, device->device_id);
|
||||
ffStrbufRecalculateLength(&gpu->name);
|
||||
}
|
||||
|
||||
static void pciDetectDriverName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
|
||||
{
|
||||
const char* base = pci->ffpci_get_param(pci->access, "sysfs.path");
|
||||
if(!ffStrSet(base))
|
||||
return;
|
||||
|
||||
FFstrbuf path;
|
||||
ffStrbufInitA(&path, 64);
|
||||
ffStrbufAppendF(&path, "%s/devices/%04x:%02x:%02x.%d/driver", base, device->domain, device->bus, device->dev, device->func);
|
||||
|
||||
ffStrbufEnsureFree(&gpu->driver, 1023);
|
||||
ssize_t resultLength = readlink(path.chars, gpu->driver.chars, gpu->driver.allocated - 1); //-1 for null terminator
|
||||
if(resultLength > 0)
|
||||
{
|
||||
gpu->driver.length = (uint32_t) resultLength;
|
||||
gpu->driver.chars[resultLength] = '\0';
|
||||
ffStrbufSubstrAfterLastC(&gpu->driver, '/');
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&path);
|
||||
}
|
||||
|
||||
static void pciDetectTemperatur(FFGPUResult* gpu, struct pci_dev* device)
|
||||
{
|
||||
const FFTempsResult* tempsResult = ffDetectTemps();
|
||||
|
||||
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 == device->device_class * 256)
|
||||
{
|
||||
gpu->temperature = tempValue->value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void pciHandleDevice(FFlist* results, PCIData* pci, struct pci_dev* device)
|
||||
{
|
||||
device->device_class = pci->ffpci_read_word(device, PCI_CLASS_DEVICE);
|
||||
|
||||
char class[1024];
|
||||
pci->ffpci_lookup_name(pci->access, class, sizeof(class) - 1, PCI_LOOKUP_CLASS, device->device_class);
|
||||
|
||||
if(
|
||||
strcasecmp("VGA compatible controller", class) != 0 &&
|
||||
strcasecmp("3D controller", class) != 0 &&
|
||||
strcasecmp("Display controller", class) != 0
|
||||
) return;
|
||||
|
||||
device->vendor_id = pci->ffpci_read_word(device, PCI_VENDOR_ID);
|
||||
device->device_id = pci->ffpci_read_word(device, PCI_DEVICE_ID);
|
||||
|
||||
FFGPUResult* gpu = ffListAdd(results);
|
||||
|
||||
ffStrbufInit(&gpu->vendor);
|
||||
pciDetectVendorName(gpu, pci, device);
|
||||
|
||||
ffStrbufInit(&gpu->name);
|
||||
pciDetectDeviceName(gpu, pci, device);
|
||||
|
||||
ffStrbufInit(&gpu->driver);
|
||||
pciDetectDriverName(gpu, pci, device);
|
||||
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
pciDetectTemperatur(gpu, device);
|
||||
}
|
||||
|
||||
static bool pciDetectGPUs(const FFinstance* instance, FFlist* gpus)
|
||||
{
|
||||
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)
|
||||
|
||||
pci.access = ffpci_alloc();
|
||||
ffpci_init(pci.access);
|
||||
ffpci_scan_bus(pci.access);
|
||||
|
||||
struct pci_dev* device = pci.access->devices;
|
||||
while(device != NULL)
|
||||
{
|
||||
pciHandleDevice(gpus, &pci, device);
|
||||
device = device->next;
|
||||
}
|
||||
|
||||
ffpci_cleanup(pci.access);
|
||||
dlclose(libpci);
|
||||
|
||||
return gpus->length > 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance)
|
||||
{
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
if(pciDetectGPUs(instance, gpus))
|
||||
return;
|
||||
#endif
|
||||
|
||||
const FFVulkanResult* vulkan = ffDetectVulkan(instance);
|
||||
*gpus = vulkan->gpus;
|
||||
}
|
@ -7,6 +7,7 @@
|
||||
#include "common/library.h"
|
||||
#include "common/io.h"
|
||||
#include "common/parsing.h"
|
||||
#include "detection/gpu/gpu.h"
|
||||
#include <stdlib.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
@ -175,12 +176,15 @@ static void detectVulkan(const FFinstance* instance, FFVulkanResult* result)
|
||||
if(physicalDeviceProperties.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU)
|
||||
continue;
|
||||
|
||||
FFGPUResult* gpu = ffListAdd(&result->devices);
|
||||
FFGPUResult* gpu = ffListAdd(&result->gpus);
|
||||
|
||||
ffStrbufInit(&gpu->name);
|
||||
ffStrbufAppendS(&gpu->name, physicalDeviceProperties.properties.deviceName);
|
||||
|
||||
//No way to detect those using vulkan
|
||||
ffStrbufInit(&gpu->vendor);
|
||||
ffStrbufInit(&gpu->device);
|
||||
ffStrbufInit(&gpu->driver);
|
||||
gpu->temperature = 0.0 / 0.0; //NaN, no way to detect temperature using vulkan
|
||||
ffStrbufAppendS(&gpu->device, physicalDeviceProperties.properties.deviceName);
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
}
|
||||
|
||||
//If the highest device version is lower than the instance version, use it as our vulkan version
|
||||
@ -218,7 +222,7 @@ const FFVulkanResult* ffDetectVulkan(const FFinstance* instance)
|
||||
ffStrbufInit(&result.driver);
|
||||
ffStrbufInit(&result.apiVersion);
|
||||
ffStrbufInit(&result.conformanceVersion);
|
||||
ffListInit(&result.devices, sizeof(FFGPUResult));
|
||||
ffListInit(&result.gpus, sizeof(FFGPUResult));
|
||||
|
||||
#ifdef FF_HAVE_VULKAN
|
||||
detectVulkan(instance, &result);
|
||||
|
@ -5,22 +5,12 @@
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
#define FF_GPU_TEMP_UNSET (0/0.0)
|
||||
|
||||
typedef struct FFGPUResult
|
||||
{
|
||||
FFstrbuf vendor;
|
||||
FFstrbuf device;
|
||||
FFstrbuf driver;
|
||||
double temperature;
|
||||
} FFGPUResult;
|
||||
|
||||
typedef struct FFVulkanResult
|
||||
{
|
||||
FFstrbuf driver;
|
||||
FFstrbuf apiVersion;
|
||||
FFstrbuf conformanceVersion;
|
||||
FFlist devices; //List of FFGPUResult
|
||||
FFlist gpus; //List of FFGPUResult, see detection/gpu/gpu.h
|
||||
} FFVulkanResult;
|
||||
|
||||
const FFVulkanResult* ffDetectVulkan(const FFinstance* instance);
|
||||
|
@ -1,265 +1,35 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/printing.h"
|
||||
#include "common/caching.h"
|
||||
#include "common/parsing.h"
|
||||
#include "common/properties.h"
|
||||
#include "detection/temps.h"
|
||||
#include "detection/vulkan.h"
|
||||
#include "detection/host/host.h"
|
||||
#include "detection/gpu/gpu.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define FF_GPU_MODULE_NAME "GPU"
|
||||
#define FF_GPU_NUM_FORMAT_ARGS 4
|
||||
|
||||
#define FF_PCI_VENDOR_NAME_AMD "AMD"
|
||||
#define FF_PCI_VENDOR_NAME_INTEL "Intel"
|
||||
#define FF_PCI_VENDOR_NAME_NVIDIA "NVIDIA"
|
||||
|
||||
static void printGPUResult(FFinstance* instance, uint8_t index, FFcache* cache, FFGPUResult* result)
|
||||
static void printGPUResult(FFinstance* instance, uint8_t index, FFcache* cache, FFGPUResult* gpu)
|
||||
{
|
||||
FFstrbuf gpu;
|
||||
ffStrbufInitA(&gpu, result->vendor.length + 1 + result->device.length);
|
||||
|
||||
if(result->vendor.length > 0)
|
||||
{
|
||||
ffStrbufAppend(&gpu, &result->vendor);
|
||||
ffStrbufAppendC(&gpu, ' ');
|
||||
}
|
||||
|
||||
ffStrbufAppend(&gpu, &result->device);
|
||||
|
||||
ffPrintAndAppendToCache(instance, FF_GPU_MODULE_NAME, index, &instance->config.gpu, cache, &gpu, FF_GPU_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->vendor},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->device},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->driver},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &result->temperature}
|
||||
});
|
||||
|
||||
ffStrbufDestroy(&gpu);
|
||||
}
|
||||
|
||||
static void printGPUList(FFinstance* instance, const FFlist* list)
|
||||
{
|
||||
FFcache cache;
|
||||
ffCacheOpenWrite(instance, FF_GPU_MODULE_NAME, &cache);
|
||||
|
||||
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));
|
||||
|
||||
ffCacheClose(&cache);
|
||||
}
|
||||
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
#include "common/library.h"
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <pci/pci.h>
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
FFstrbuf output;
|
||||
ffStrbufInitA(&output, gpu->vendor.length + 1 + gpu->name.length);
|
||||
|
||||
if(gpu->vendor.length > 0)
|
||||
return;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void drmDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
|
||||
{
|
||||
FFstrbuf query;
|
||||
ffStrbufInit(&query);
|
||||
ffStrbufAppendF(&query, "%X, %X,", device->device_id, pci->ffpci_read_byte(device, PCI_REVISION_ID));
|
||||
|
||||
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/libdrm/amdgpu.ids", query.chars, &gpu->device);
|
||||
|
||||
ffStrbufDestroy(&query);
|
||||
|
||||
const char* removeStrings[] = {
|
||||
"AMD ", "ATI ",
|
||||
" (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)
|
||||
{
|
||||
drmDetectDeviceName(gpu, pci, device);
|
||||
if(gpu->device.length > 0)
|
||||
return;
|
||||
ffStrbufAppend(&output, &gpu->vendor);
|
||||
ffStrbufAppendC(&output, ' ');
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
ffStrbufAppend(&output, &gpu->name);
|
||||
|
||||
static void pciDetectDriverName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
|
||||
{
|
||||
const char* base = pci->ffpci_get_param(pci->access, "sysfs.path");
|
||||
if(!ffStrSet(base))
|
||||
return;
|
||||
ffPrintAndAppendToCache(instance, FF_GPU_MODULE_NAME, index, &instance->config.gpu, cache, &output, FF_GPU_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &gpu->vendor},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &gpu->name},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &gpu->driver},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &gpu->temperature}
|
||||
});
|
||||
|
||||
FFstrbuf path;
|
||||
ffStrbufInitA(&path, 64);
|
||||
ffStrbufAppendF(&path, "%s/devices/%04x:%02x:%02x.%d/driver", base, device->domain, device->bus, device->dev, device->func);
|
||||
|
||||
ffStrbufEnsureFree(&gpu->driver, 1023);
|
||||
ssize_t resultLength = readlink(path.chars, gpu->driver.chars, gpu->driver.allocated - 1); //-1 for null terminator
|
||||
if(resultLength > 0)
|
||||
{
|
||||
gpu->driver.length = (uint32_t) resultLength;
|
||||
gpu->driver.chars[resultLength] = '\0';
|
||||
ffStrbufSubstrAfterLastC(&gpu->driver, '/');
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&path);
|
||||
}
|
||||
|
||||
static void pciDetectTemperatur(FFGPUResult* gpu, struct pci_dev* device)
|
||||
{
|
||||
const FFTempsResult* tempsResult = ffDetectTemps();
|
||||
|
||||
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 == device->device_class * 256)
|
||||
{
|
||||
gpu->temperature = tempValue->value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void pciHandleDevice(FFlist* results, PCIData* pci, struct pci_dev* device)
|
||||
{
|
||||
device->device_class = pci->ffpci_read_word(device, PCI_CLASS_DEVICE);
|
||||
|
||||
char class[1024];
|
||||
pci->ffpci_lookup_name(pci->access, class, sizeof(class) - 1, PCI_LOOKUP_CLASS, device->device_class);
|
||||
|
||||
if(
|
||||
strcasecmp("VGA compatible controller", class) != 0 &&
|
||||
strcasecmp("3D controller", class) != 0 &&
|
||||
strcasecmp("Display controller", class) != 0
|
||||
) return;
|
||||
|
||||
device->vendor_id = pci->ffpci_read_word(device, PCI_VENDOR_ID);
|
||||
device->device_id = pci->ffpci_read_word(device, PCI_DEVICE_ID);
|
||||
|
||||
FFGPUResult* gpu = ffListAdd(results);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static bool pciPrintGPUs(FFinstance* instance)
|
||||
{
|
||||
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)
|
||||
|
||||
FFlist results;
|
||||
ffListInit(&results, sizeof(FFGPUResult));
|
||||
|
||||
pci.access = ffpci_alloc();
|
||||
ffpci_init(pci.access);
|
||||
ffpci_scan_bus(pci.access);
|
||||
|
||||
struct pci_dev* device = pci.access->devices;
|
||||
while(device != NULL)
|
||||
{
|
||||
pciHandleDevice(&results, &pci, device);
|
||||
device = device->next;
|
||||
}
|
||||
|
||||
ffpci_cleanup(pci.access);
|
||||
dlclose(libpci);
|
||||
|
||||
printGPUList(instance, &results);
|
||||
|
||||
for(uint32_t i = 0; i < results.length; i++)
|
||||
{
|
||||
FFGPUResult* gpu = ffListGet(&results, i);
|
||||
ffStrbufDestroy(&gpu->vendor);
|
||||
ffStrbufDestroy(&gpu->device);
|
||||
ffStrbufDestroy(&gpu->driver);
|
||||
}
|
||||
|
||||
ffListDestroy(&results);
|
||||
return results.length > 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static bool vulkanPrintGPUs(FFinstance* instance)
|
||||
{
|
||||
const FFVulkanResult* result = ffDetectVulkan(instance);
|
||||
if(result->devices.length == 0)
|
||||
return false;
|
||||
|
||||
printGPUList(instance, &result->devices);
|
||||
return true;
|
||||
ffStrbufDestroy(&output);
|
||||
}
|
||||
|
||||
void ffPrintGPU(FFinstance* instance)
|
||||
@ -273,13 +43,19 @@ void ffPrintGPU(FFinstance* instance)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
if(pciPrintGPUs(instance))
|
||||
return;
|
||||
#endif
|
||||
const FFlist* gpus = ffDetectGPU(instance);
|
||||
|
||||
if(vulkanPrintGPUs(instance))
|
||||
if(gpus->length == 0)
|
||||
{
|
||||
ffPrintError(instance, FF_GPU_MODULE_NAME, 0, &instance->config.gpu, "No GPUs found");
|
||||
return;
|
||||
}
|
||||
|
||||
ffPrintError(instance, FF_GPU_MODULE_NAME, 0, &instance->config.gpu, "No GPUs found.");
|
||||
FFcache cache;
|
||||
ffCacheOpenWrite(instance, FF_GPU_MODULE_NAME, &cache);
|
||||
|
||||
for(uint8_t i = 0; i < (uint8_t) gpus->length; i++)
|
||||
printGPUResult(instance, gpus->length == 1 ? 0 : (uint8_t) (i + 1), &cache, ffListGet(gpus, i));
|
||||
|
||||
ffCacheClose(&cache);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user