mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-10-29 16:26:39 +01:00
Vulkan module
This commit is contained in:
+119
-194
@@ -5,181 +5,7 @@
|
||||
#define FF_GPU_MODULE_NAME "GPU"
|
||||
#define FF_GPU_NUM_FORMAT_ARGS 5
|
||||
|
||||
typedef struct GPUResult
|
||||
{
|
||||
FFstrbuf vendor;
|
||||
FFstrbuf name;
|
||||
FFstrbuf driver;
|
||||
} GPUResult;
|
||||
|
||||
#ifdef FF_HAVE_VULKAN
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
static void vulkanFillGPUs(FFinstance* instance, FFlist* results)
|
||||
{
|
||||
FF_LIBRARY_LOAD(vulkan, instance->config.libVulkan, , "libvulkan.so", 2)
|
||||
FF_LIBRARY_LOAD_SYMBOL(vulkan, vkCreateInstance,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(vulkan, vkDestroyInstance,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(vulkan, vkEnumeratePhysicalDevices,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(vulkan, vkGetPhysicalDeviceProperties,)
|
||||
|
||||
//Some drivers (nvdc) print messages to stdout
|
||||
//and thats the best way i found to disable that
|
||||
ffSuppressIO(true);
|
||||
|
||||
const VkApplicationInfo applicationInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
||||
.pNext = NULL,
|
||||
.pApplicationName = FASTFETCH_PROJECT_NAME,
|
||||
.applicationVersion = VK_MAKE_VERSION(FASTFETCH_PROJECT_VERSION_MAJOR, 0, 0),
|
||||
.pEngineName = "vulkanPrintGPUs",
|
||||
.engineVersion = VK_MAKE_VERSION(FASTFETCH_PROJECT_VERSION_MAJOR, 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);
|
||||
ffSuppressIO(false);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t physicalDeviceCount;
|
||||
if(ffvkEnumeratePhysicalDevices(vkInstance, &physicalDeviceCount, NULL) != VK_SUCCESS)
|
||||
{
|
||||
ffvkDestroyInstance(vkInstance, NULL);
|
||||
dlclose(vulkan);
|
||||
ffSuppressIO(false);
|
||||
return;
|
||||
}
|
||||
|
||||
VkPhysicalDevice* physicalDevices = malloc(sizeof(VkPhysicalDevice) * physicalDeviceCount);
|
||||
if(ffvkEnumeratePhysicalDevices(vkInstance, &physicalDeviceCount, physicalDevices) != VK_SUCCESS)
|
||||
{
|
||||
free(physicalDevices);
|
||||
ffvkDestroyInstance(vkInstance, NULL);
|
||||
dlclose(vulkan);
|
||||
ffSuppressIO(false);
|
||||
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);
|
||||
ffStrbufInit(&result->driver);
|
||||
|
||||
ffStrbufAppendS(&result->name, physicalDeviceProperties.deviceName);
|
||||
}
|
||||
|
||||
free(physicalDevices);
|
||||
ffvkDestroyInstance(vkInstance, NULL);
|
||||
dlclose(vulkan);
|
||||
ffSuppressIO(false);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
#include <pci/pci.h>
|
||||
#include <unistd.h>
|
||||
|
||||
//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);
|
||||
}
|
||||
|
||||
static void pciFillGPUs(FFinstance* instance, FFlist* results)
|
||||
{
|
||||
FF_LIBRARY_LOAD(pci, instance->config.libPCI, , "libpci.so", 4)
|
||||
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_get_param,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_cleanup,)
|
||||
|
||||
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
|
||||
) {
|
||||
GPUResult* result = ffListAdd(results);
|
||||
|
||||
ffStrbufInitA(&result->vendor, 256);
|
||||
ffpci_lookup_name(pacc, result->vendor.chars, (int) 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, (int) result->name.allocated - 1, PCI_LOOKUP_DEVICE, dev->vendor_id, dev->device_id);
|
||||
ffStrbufRecalculateLength(&result->name);
|
||||
|
||||
ffStrbufInit(&result->driver);
|
||||
if(instance->config.gpuFormat.length > 0) //We only need it for the format string, so don't detect it if it isn't needed
|
||||
pciGetDriver(dev, &result->driver, ffpci_get_param);
|
||||
};
|
||||
}
|
||||
|
||||
ffpci_cleanup(pacc);
|
||||
dlclose(pci);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void printGPUResult(FFinstance* instance, uint8_t index, FFcache* cache, GPUResult* result)
|
||||
static void printGPUResult(FFinstance* instance, uint8_t index, FFcache* cache, FFGPUResult* result)
|
||||
{
|
||||
const char* vendorPretty;
|
||||
if(ffStrbufIgnCaseCompS(&result->vendor, "Advanced Micro Devices, Inc. [AMD/ATI]") == 0)
|
||||
@@ -222,32 +48,131 @@ static void printGPUResult(FFinstance* instance, uint8_t index, FFcache* cache,
|
||||
ffStrbufDestroy(&namePretty);
|
||||
}
|
||||
|
||||
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 <pci/pci.h>
|
||||
#include <unistd.h>
|
||||
|
||||
//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);
|
||||
}
|
||||
|
||||
static bool pciPrintGPUs(FFinstance* instance)
|
||||
{
|
||||
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));
|
||||
|
||||
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
|
||||
) {
|
||||
FFGPUResult* result = ffListAdd(&results);
|
||||
|
||||
ffStrbufInitA(&result->vendor, 256);
|
||||
ffpci_lookup_name(pacc, result->vendor.chars, (int) 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, (int) result->name.allocated - 1, PCI_LOOKUP_DEVICE, dev->vendor_id, dev->device_id);
|
||||
ffStrbufRecalculateLength(&result->name);
|
||||
|
||||
ffStrbufInit(&result->driver);
|
||||
if(instance->config.gpuFormat.length > 0) //We only need it for the format string, so don't detect it if it isn't needed
|
||||
pciGetDriver(dev, &result->driver, ffpci_get_param);
|
||||
};
|
||||
}
|
||||
|
||||
ffpci_cleanup(pacc);
|
||||
dlclose(pci);
|
||||
|
||||
if(results.length == 0)
|
||||
{
|
||||
ffListDestroy(&results);
|
||||
return false;
|
||||
}
|
||||
|
||||
printGPUList(instance, &results);
|
||||
|
||||
ffListDestroy(&results);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static bool vulkanPrintGPUs(FFinstance* instance)
|
||||
{
|
||||
const FFVulkanResult* result = ffDetectVulkan(instance);
|
||||
if(result->devices.length == 0)
|
||||
return false;
|
||||
|
||||
printGPUList(instance, &result->devices);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ffPrintGPU(FFinstance* instance)
|
||||
{
|
||||
if(ffPrintFromCache(instance, FF_GPU_MODULE_NAME, &instance->config.gpuKey, &instance->config.gpuFormat, FF_GPU_NUM_FORMAT_ARGS))
|
||||
return;
|
||||
|
||||
FFlist gpus;
|
||||
ffListInitA(&gpus, sizeof(GPUResult), 4);
|
||||
|
||||
FFcache cache;
|
||||
ffCacheOpenWrite(instance, FF_GPU_MODULE_NAME, &cache);
|
||||
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
pciFillGPUs(instance, &gpus);
|
||||
if(pciPrintGPUs(instance))
|
||||
return;
|
||||
#endif
|
||||
|
||||
#ifdef FF_HAVE_VULKAN
|
||||
if(gpus.length == 0)
|
||||
vulkanFillGPUs(instance, &gpus);
|
||||
#endif
|
||||
if(vulkanPrintGPUs(instance))
|
||||
return;
|
||||
|
||||
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));
|
||||
|
||||
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);
|
||||
ffPrintError(instance, FF_GPU_MODULE_NAME, 0, &instance->config.gpuKey, &instance->config.gpuFormat, FF_GPU_NUM_FORMAT_ARGS, "No GPUs found.");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
#define FF_VULKAN_MODULE_NAME "Vulkan"
|
||||
#define FF_VULKAN_NUM_FORMAT_ARGS 3
|
||||
|
||||
void ffPrintVulkan(FFinstance* instance)
|
||||
{
|
||||
const FFVulkanResult* vulkan = ffDetectVulkan(instance);
|
||||
|
||||
if(vulkan->apiVersion.length == 0 && vulkan->driver.length == 0)
|
||||
{
|
||||
ffPrintError(instance, FF_VULKAN_MODULE_NAME, 0, &instance->config.vulkanKey, &instance->config.vulkanFormat, FF_VULKAN_NUM_FORMAT_ARGS, "Failed to detect vulkan");
|
||||
return;
|
||||
}
|
||||
|
||||
if(instance->config.vulkanFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, FF_VULKAN_MODULE_NAME, 0, &instance->config.vulkanKey);
|
||||
|
||||
if(vulkan->driver.length > 0)
|
||||
{
|
||||
printf("%s (driver)", vulkan->driver.chars);
|
||||
|
||||
if(vulkan->apiVersion.length > 0)
|
||||
fputs(", ", stdout);
|
||||
}
|
||||
|
||||
if(vulkan->apiVersion.length > 0)
|
||||
printf("%s (api version)", vulkan->apiVersion.chars);
|
||||
|
||||
putchar('\n');
|
||||
}
|
||||
else
|
||||
{
|
||||
ffPrintFormatString(instance, FF_VULKAN_MODULE_NAME, 0, &instance->config.vulkanKey, &instance->config.vulkanFormat, NULL, FF_VULKAN_NUM_FORMAT_ARGS, (FFformatarg[]) {
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &vulkan->driver},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &vulkan->apiVersion},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &vulkan->conformanceVersion}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user