mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-13 02:14:37 +02:00
GPU: vulkan fallback
This commit is contained in:
@@ -60,6 +60,13 @@ else(LIBPCI_FOUND)
|
||||
message(WARNING "Package libpci not found. Building without support.")
|
||||
endif(LIBPCI_FOUND)
|
||||
|
||||
pkg_check_modules (VULKAN vulkan)
|
||||
if(VULKAN_FOUND)
|
||||
add_compile_definitions(FF_HAVE_VULKAN=1)
|
||||
else(VULKAN_FOUND)
|
||||
message(WARNING "Package vulkan not found. Building without support.")
|
||||
endif(VULKAN_FOUND)
|
||||
|
||||
pkg_check_modules (X11 x11)
|
||||
if(X11_FOUND)
|
||||
add_compile_definitions(FF_HAVE_X11=1)
|
||||
|
||||
@@ -18,7 +18,8 @@ There are some presets defined for fastfech in [`presets`](presets), you can can
|
||||
|
||||
In order to run properly on every machine, fastfetch dynamically loads needed libraries if they are available. Therefore its only hard dependency is [`glibc`](https://www.gnu.org/software/libc/) (`libc`, `libdl` and `libpthread` are actually used) which is automatically shipped with every linux system.
|
||||
The following libraries are used if present:
|
||||
* [`libpci`](https://github.com/pciutils/pciutils): Needed for GPU output. _Should_ be available on every linux system.
|
||||
* [`libpci`](https://github.com/pciutils/pciutils): GPU output.
|
||||
* [`libvulkan`](https://www.vulkan.org/): Fallback for GPU output.
|
||||
* [`libX11`](https://gitlab.freedesktop.org/xorg/lib/libx11): Needed for resolution output
|
||||
* [`libXrandr`](https://gitlab.freedesktop.org/xorg/lib/libxrandr): Needed for appending refresh rate to resolution output.
|
||||
* [`libwayland-client`](https://wayland.freedesktop.org/): Better resolution performance in wayland sessions.
|
||||
|
||||
@@ -192,6 +192,7 @@ __fastfetch_completion()
|
||||
|
||||
local FF_OPTIONS_PATH=(
|
||||
"--lib-PCI"
|
||||
"--lib-vulkan"
|
||||
"--lib-X11"
|
||||
"--lib-Xrandr"
|
||||
"--lib-gio"
|
||||
|
||||
@@ -168,6 +168,7 @@ static void defaultConfig(FFinstance* instance)
|
||||
ffStrbufInitA(&instance->config.localIpFormat, 1);
|
||||
|
||||
ffStrbufInitA(&instance->config.libPCI, 1);
|
||||
ffStrbufInitA(&instance->config.libVulkan, 1);
|
||||
ffStrbufInitA(&instance->config.libX11, 1);
|
||||
ffStrbufInitA(&instance->config.libXrandr, 1);
|
||||
ffStrbufInitA(&instance->config.libGIO, 1);
|
||||
|
||||
@@ -159,6 +159,7 @@
|
||||
# Sets an user specific path to a library to load.
|
||||
# Must be a valid path to a library.
|
||||
#--lib-PCI /usr/lib/libpci.so
|
||||
#--lib-vulkan /usr/lib/libvulkan.so
|
||||
#--lib-X11 /usr/lib/libX11.so
|
||||
#--lib-Xrandr /usr/lib/libXrandr.so
|
||||
#--lib-gio /usr/lib/libgio-2.0.so
|
||||
|
||||
@@ -87,6 +87,7 @@ Key options: Provide a custom key for an output
|
||||
|
||||
Library options: Set the path of a library to load
|
||||
--lib-PCI <path>
|
||||
--lib-vulkan <path>
|
||||
--lib-X11 <path>
|
||||
--lib-Xrandr <path>
|
||||
--lib-gio <path>
|
||||
|
||||
@@ -346,6 +346,9 @@ static inline void listSupportedFeatures()
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
"libpci\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_VULKAN
|
||||
"vulkan\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_X11
|
||||
"x11\n"
|
||||
#endif
|
||||
@@ -738,6 +741,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
|
||||
optionParseString(key, value, &instance->config.localIpFormat);
|
||||
else if(strcasecmp(key, "--lib-PCI") == 0)
|
||||
optionParseString(key, value, &instance->config.libPCI);
|
||||
else if(strcasecmp(key, "--lib-vulkan") == 0)
|
||||
optionParseString(key, value, &instance->config.libVulkan);
|
||||
else if(strcasecmp(key, "--lib-X11") == 0)
|
||||
optionParseString(key, value, &instance->config.libX11);
|
||||
else if(strcasecmp(key, "--lib-Xrandr") == 0)
|
||||
|
||||
+1
-1
@@ -101,6 +101,7 @@ typedef struct FFconfig
|
||||
FFstrbuf localIpFormat;
|
||||
|
||||
FFstrbuf libPCI;
|
||||
FFstrbuf libVulkan;
|
||||
FFstrbuf libX11;
|
||||
FFstrbuf libXrandr;
|
||||
FFstrbuf libWayland;
|
||||
@@ -274,7 +275,6 @@ typedef enum FFInitState
|
||||
#define FF_LIBRARY_SYMBOL(symbolName) \
|
||||
__typeof__(&symbolName) ff ## symbolName;
|
||||
|
||||
|
||||
#define FF_LIBRARY_LOAD(libraryObjectName, libraryName, userLibraryName, returnValue) \
|
||||
void* libraryObjectName = dlopen(userLibraryName.length == 0 ? libraryName : userLibraryName.chars, RTLD_LAZY); \
|
||||
if(dlerror() != NULL || libraryObjectName == NULL) \
|
||||
|
||||
+169
-76
@@ -5,83 +5,110 @@
|
||||
#define FF_GPU_MODULE_NAME "GPU"
|
||||
#define FF_GPU_NUM_FORMAT_ARGS 4
|
||||
|
||||
#ifndef FF_HAVE_LIBPCI
|
||||
|
||||
void ffPrintGPU(FFinstance* instance)
|
||||
typedef struct GPUResult
|
||||
{
|
||||
ffPrintError(instance, FF_GPU_MODULE_NAME, 0, &instance->config.gpuKey, &instance->config.gpuFormat, FF_GPU_NUM_FORMAT_ARGS, "Fastfetch was compiled without libpci support");
|
||||
FFstrbuf vendor;
|
||||
FFstrbuf name;
|
||||
} GPUResult;
|
||||
|
||||
#ifdef FF_HAVE_VULKAN
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
static void vulkanFillGPUs(FFinstance* instance, FFlist* results)
|
||||
{
|
||||
FF_LIBRARY_LOAD(vulkan, "libvulkan.so", instance->config.libVulkan,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(vulkan, vkCreateInstance,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(vulkan, vkDestroyInstance,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(vulkan, vkEnumeratePhysicalDevices,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(vulkan, vkGetPhysicalDeviceProperties,)
|
||||
|
||||
const VkApplicationInfo applicationInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
||||
.pNext = NULL,
|
||||
.pApplicationName = FASTFETCH_PROJECT_NAME,
|
||||
.applicationVersion = VK_MAKE_VERSION(FASTFETCH_PROJECT_NAME, 0, 0),
|
||||
.pEngineName = "vulkanPrintGPUs",
|
||||
.engineVersion = VK_MAKE_VERSION(FASTFETCH_PROJECT_NAME, 0, 0),
|
||||
.apiVersion = VK_API_VERSION_1_0,
|
||||
};
|
||||
|
||||
const VkInstanceCreateInfo instanceCreateInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||
.pNext = NULL,
|
||||
.pApplicationInfo = &applicationInfo,
|
||||
.enabledLayerCount = 0,
|
||||
.ppEnabledLayerNames = NULL,
|
||||
.enabledExtensionCount = 0,
|
||||
.ppEnabledExtensionNames = NULL,
|
||||
.flags = 0
|
||||
};
|
||||
|
||||
VkInstance vkInstance;
|
||||
if(ffvkCreateInstance(&instanceCreateInfo, NULL, &vkInstance) != VK_SUCCESS)
|
||||
{
|
||||
dlclose(vulkan);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t physicalDeviceCount;
|
||||
if(ffvkEnumeratePhysicalDevices(vkInstance, &physicalDeviceCount, NULL) != VK_SUCCESS)
|
||||
{
|
||||
ffvkDestroyInstance(vkInstance, NULL);
|
||||
dlclose(vulkan);
|
||||
return;
|
||||
}
|
||||
|
||||
VkPhysicalDevice* physicalDevices = malloc(sizeof(VkPhysicalDevice) * physicalDeviceCount);
|
||||
if(ffvkEnumeratePhysicalDevices(vkInstance, &physicalDeviceCount, physicalDevices) != VK_SUCCESS)
|
||||
{
|
||||
free(physicalDevices);
|
||||
ffvkDestroyInstance(vkInstance, NULL);
|
||||
dlclose(vulkan);
|
||||
return;
|
||||
}
|
||||
|
||||
for(uint32_t i = 0; i < physicalDeviceCount; i++)
|
||||
{
|
||||
VkPhysicalDeviceProperties physicalDeviceProperties;
|
||||
ffvkGetPhysicalDeviceProperties(physicalDevices[i], &physicalDeviceProperties);
|
||||
|
||||
//We don't want softare rasterizers
|
||||
if(physicalDeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU)
|
||||
continue;
|
||||
|
||||
GPUResult* result = ffListAdd(results);
|
||||
ffStrbufInit(&result->vendor);
|
||||
ffStrbufInit(&result->name);
|
||||
|
||||
ffStrbufAppendS(&result->name, physicalDeviceProperties.deviceName);
|
||||
}
|
||||
|
||||
free(physicalDevices);
|
||||
ffvkDestroyInstance(vkInstance, NULL);
|
||||
dlclose(vulkan);
|
||||
return;
|
||||
}
|
||||
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
#include <pci/pci.h>
|
||||
|
||||
static void printGPU(FFinstance* instance, struct pci_access* pacc, struct pci_dev* dev, FFcache* cache, uint8_t counter, char*(*ffpci_lookup_name)(struct pci_access*, char*, int, int, ...))
|
||||
static void pciFillGPUs(FFinstance* instance, FFlist* results)
|
||||
{
|
||||
char vendor[512];
|
||||
vendor[0] = '\0';
|
||||
ffpci_lookup_name(pacc, vendor, sizeof(vendor), PCI_LOOKUP_VENDOR, dev->vendor_id, dev->device_id);
|
||||
FF_LIBRARY_LOAD(pci, "libpci.so", instance->config.libPCI,)
|
||||
|
||||
const char* vendorPretty;
|
||||
if(strcasecmp(vendor, "Advanced Micro Devices, Inc. [AMD/ATI]") == 0)
|
||||
vendorPretty = "AMD ATI";
|
||||
else if(strcasecmp(vendor, "NVIDIA Corporation") == 0)
|
||||
vendorPretty = "Nvidia";
|
||||
else if(strcasecmp(vendor, "Intel Corporation") == 0)
|
||||
vendorPretty = "Intel";
|
||||
else
|
||||
vendorPretty = vendor;
|
||||
|
||||
char name[512];
|
||||
name[0] = '\0';
|
||||
ffpci_lookup_name(pacc, name, sizeof(name), PCI_LOOKUP_DEVICE, dev->vendor_id, dev->device_id);
|
||||
|
||||
FFstrbuf namePretty;
|
||||
ffStrbufInitA(&namePretty, 512);
|
||||
ffStrbufAppendS(&namePretty, name);
|
||||
ffStrbufSubstrBeforeLastC(&namePretty, ']');
|
||||
ffStrbufSubstrAfterFirstC(&namePretty, '[');
|
||||
|
||||
FFstrbuf gpu;
|
||||
ffStrbufInitA(&gpu, 128);
|
||||
|
||||
ffStrbufSetF(&gpu, "%s %s", vendorPretty, namePretty.chars);
|
||||
|
||||
ffPrintAndAppendToCache(instance, FF_GPU_MODULE_NAME, counter, &instance->config.gpuKey, cache, &gpu, &instance->config.gpuFormat, FF_GPU_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRING, vendor},
|
||||
{FF_FORMAT_ARG_TYPE_STRING, vendorPretty},
|
||||
{FF_FORMAT_ARG_TYPE_STRING, name},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &namePretty}
|
||||
});
|
||||
|
||||
ffStrbufDestroy(&gpu);
|
||||
ffStrbufDestroy(&namePretty);
|
||||
}
|
||||
|
||||
static const char* printGPUs(FFinstance* instance)
|
||||
{
|
||||
if(ffPrintFromCache(instance, FF_GPU_MODULE_NAME, &instance->config.gpuKey, &instance->config.gpuFormat, FF_GPU_NUM_FORMAT_ARGS))
|
||||
return NULL;
|
||||
|
||||
FF_LIBRARY_LOAD(pci, "libpci.so", instance->config.libPCI, "gpu: dlopen of libpci failed")
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_alloc, "gpu: dlsym of pci_alloc failed")
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_init, "gpu: dlsym of pci_init failed")
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_scan_bus, "gpu: dlsym of pci_scan_bus failed")
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_fill_info, "gpu: dlsym of pci_fill_info failed")
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_lookup_name, "gpu: dlsym of pci_lookup_name failed")
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_cleanup, "gpu: dlsym of pci_cleanup failed")
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_alloc,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_init,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_scan_bus,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_fill_info,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_lookup_name,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_cleanup,)
|
||||
|
||||
struct pci_access *pacc = ffpci_alloc();
|
||||
ffpci_init(pacc);
|
||||
ffpci_scan_bus(pacc);
|
||||
|
||||
FFlist devices;
|
||||
ffListInitA(&devices, sizeof(struct pci_dev*), 4);
|
||||
|
||||
FFcache cache;
|
||||
ffCacheOpenWrite(instance, FF_GPU_MODULE_NAME, &cache);
|
||||
|
||||
struct pci_dev* dev;
|
||||
for (dev=pacc->devices; dev; dev=dev->next)
|
||||
{
|
||||
@@ -92,24 +119,90 @@ static const char* printGPUs(FFinstance* instance)
|
||||
strcasecmp("VGA compatible controller", class) == 0 ||
|
||||
strcasecmp("3D controller", class) == 0 ||
|
||||
strcasecmp("Display controller", class) == 0
|
||||
) *(struct pci_dev**)ffListAdd(&devices) = dev;
|
||||
) {
|
||||
GPUResult* result = ffListAdd(results);
|
||||
|
||||
ffStrbufInitA(&result->vendor, 256);
|
||||
ffpci_lookup_name(pacc, result->vendor.chars, result->vendor.allocated -1, PCI_LOOKUP_VENDOR, dev->vendor_id, dev->device_id);
|
||||
ffStrbufRecalculateLength(&result->vendor);
|
||||
|
||||
ffStrbufInitA(&result->name, 256);
|
||||
ffpci_lookup_name(pacc, result->name.chars, result->name.allocated - 1, PCI_LOOKUP_DEVICE, dev->vendor_id, dev->device_id);
|
||||
ffStrbufRecalculateLength(&result->name);
|
||||
};
|
||||
}
|
||||
|
||||
for(uint32_t i = 0; i < devices.length; i++)
|
||||
printGPU(instance, pacc, *(struct pci_dev**)ffListGet(&devices, i), &cache, devices.length == 1 ? 0 : i + 1, ffpci_lookup_name);
|
||||
|
||||
ffCacheClose(&cache);
|
||||
ffListDestroy(&devices);
|
||||
ffpci_cleanup(pacc);
|
||||
dlclose(pci);
|
||||
return devices.length > 0 ? NULL : "No GPU found";
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void printGPUResult(FFinstance* instance, uint8_t index, FFcache* cache, GPUResult* result)
|
||||
{
|
||||
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;
|
||||
|
||||
FFstrbuf namePretty;
|
||||
ffStrbufInitCopy(&namePretty, &result->name);
|
||||
ffStrbufSubstrBeforeLastC(&namePretty, ']');
|
||||
ffStrbufSubstrAfterFirstC(&namePretty, '[');
|
||||
|
||||
FFstrbuf gpu;
|
||||
ffStrbufInitA(&gpu, result->vendor.length + namePretty.length);
|
||||
|
||||
if(*vendorPretty != '\0')
|
||||
{
|
||||
ffStrbufAppendS(&gpu, vendorPretty);
|
||||
ffStrbufAppendC(&gpu, ' ');
|
||||
}
|
||||
|
||||
ffStrbufAppend(&gpu, &namePretty);
|
||||
|
||||
ffPrintAndAppendToCache(instance, FF_GPU_MODULE_NAME, index, &instance->config.gpuKey, cache, &gpu, &instance->config.gpuFormat, FF_GPU_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{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}
|
||||
});
|
||||
|
||||
ffStrbufDestroy(&gpu);
|
||||
ffStrbufDestroy(&namePretty);
|
||||
}
|
||||
|
||||
void ffPrintGPU(FFinstance* instance)
|
||||
{
|
||||
const char* error = printGPUs(instance);
|
||||
if(error != NULL)
|
||||
ffPrintError(instance, FF_GPU_MODULE_NAME, 0, &instance->config.gpuKey, &instance->config.gpuFormat, FF_GPU_NUM_FORMAT_ARGS, error);
|
||||
}
|
||||
if(ffPrintFromCache(instance, FF_GPU_MODULE_NAME, &instance->config.gpuKey, &instance->config.gpuFormat, FF_GPU_NUM_FORMAT_ARGS))
|
||||
return;
|
||||
|
||||
#endif
|
||||
FFlist gpus;
|
||||
ffListInitA(&gpus, sizeof(GPUResult), 4);
|
||||
|
||||
FFcache cache;
|
||||
ffCacheOpenWrite(instance, FF_GPU_MODULE_NAME, &cache);
|
||||
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
pciFillGPUs(instance, &gpus);
|
||||
#endif
|
||||
|
||||
#ifdef FF_HAVE_VULKAN
|
||||
if(gpus.length == 0)
|
||||
vulkanFillGPUs(instance, &gpus);
|
||||
#endif
|
||||
|
||||
for(uint32_t i = 0; i < gpus.length; i++)
|
||||
printGPUResult(instance, gpus.length == 1 ? 0 : i + 1, &cache, ffListGet(&gpus, i));
|
||||
|
||||
if(gpus.length == 0)
|
||||
ffPrintError(instance, FF_GPU_MODULE_NAME, 0, &instance->config.gpuKey, &instance->config.gpuFormat, FF_GPU_NUM_FORMAT_ARGS, "No GPUs found.");
|
||||
|
||||
ffCacheClose(&cache);
|
||||
ffListDestroy(&gpus);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user