Vulkan module

This commit is contained in:
Linus Dierheimer
2022-06-01 00:04:58 +02:00
parent 032ba375b6
commit 0dffd8debf
15 changed files with 469 additions and 196 deletions
+2
View File
@@ -123,6 +123,7 @@ add_library(libfastfetch STATIC
src/detection/plasma.c
src/detection/gtk.c
src/detection/terminalShell.c
src/detection/vulkan.c
src/detection/media.c
src/detection/datetime.c
src/detection/displayserver/displayServer.c
@@ -158,6 +159,7 @@ add_library(libfastfetch STATIC
src/modules/disk.c
src/modules/battery.c
src/modules/locale.c
src/modules/vulkan.c
src/modules/localip.c
src/modules/publicip.c
src/modules/player.c
+1 -1
View File
@@ -41,7 +41,7 @@ All categories not listed here should work without needing a specific implementa
##### Available Modules
```
Title, Separator, OS, Host, Kernel, Uptime, Processes, Packages, Shell, Resolution, DE, WM, WMTheme, Theme, Icons, Font, Cursor, Terminal, Terminal Font, CPU, CPUUsage, GPU, Memory, Disk, Battery, Player, Song, LocalIP, PublicIP, DateTime, Date, Time, Locale, Colors, Break, Custom
Title, Separator, OS, Host, Kernel, Uptime, Processes, Packages, Shell, Resolution, DE, WM, WMTheme, Theme, Icons, Font, Cursor, Terminal, Terminal Font, CPU, CPUUsage, GPU, Memory, Disk, Battery, Player, Song, Vulkan, LocalIP, PublicIP, DateTime, Date, Time, Locale, Colors, Break, Custom
```
##### Logos
+1 -1
View File
@@ -1 +1 @@
--structure Title:Separator:OS:Host:Kernel:Uptime:Processes:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Disk:Battery:Player:Song:PublicIP:LocalIP:DateTime:Locale:Break:Colors
--structure Title:Separator:OS:Host:Kernel:Uptime:Processes:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Disk:Battery:Player:Song:PublicIP:LocalIP:DateTime:Locale:Vulkan:Break:Colors
+1
View File
@@ -26,3 +26,4 @@
--player-format "Name: {}"
--song-format "Song: {}; Artist: {}; Album: {}"
--datetime-format "year: {}; yearShort: {}; month: {}; monthPretty: {}; monthName: {}; monthNameShort: {}; weekNumber: {}; weekday: {}; weekdayShort: {}; dayInYear: {}; dayInMonth: {}; dayInWeek: {}; hour: {}; hourPretty: {}; hour12: {}; hour12Pretty: {}; minute: {}; minutePretty: {}; second: {}; secondPretty: {}"
--vulkan-format "driver: {}; Api Version: {}; Conformance Version: {}"
+2
View File
@@ -187,6 +187,8 @@ static void defaultConfig(FFinstance* instance)
ffStrbufInitA(&instance->config.dateFormat, 0);
ffStrbufInitA(&instance->config.timeKey, 0);
ffStrbufInitA(&instance->config.timeFormat, 0);
ffStrbufInitA(&instance->config.vulkanKey, 0);
ffStrbufInitA(&instance->config.vulkanFormat, 0);
ffStrbufInitA(&instance->config.libPCI, 0);
ffStrbufInitA(&instance->config.libVulkan, 0);
+26
View File
@@ -39,6 +39,32 @@ void ffParseSemver(FFstrbuf* buffer, const FFstrbuf* major, const FFstrbuf* mino
ffStrbufAppend(buffer, patch);
}
int8_t ffVersionCompare(const FFVersion* version1, const FFVersion* version2)
{
if(version1->major != version2->major)
return version1->major > version2->major ? 1 : -1;
if(version1->minor != version2->minor)
return version1->minor > version2->minor ? 1 : -1;
if(version1->patch != version2->patch)
return version1->patch > version2->patch ? 1 : -1;
return 0;
}
void ffVersionToPretty(const FFVersion* version, FFstrbuf* pretty)
{
if(version->major > 0 || version->minor > 0 || version->patch > 0)
ffStrbufAppendF(pretty, "%u", version->major);
if(version->minor > 0 || version->patch > 0)
ffStrbufAppendF(pretty, ".%u", version->minor);
if(version->patch > 0)
ffStrbufAppendF(pretty, ".%u", version->patch);
}
void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, const FFstrbuf* gtk4)
{
if(gtk2->length > 0 && gtk3->length > 0 && gtk4->length > 0)
+2
View File
@@ -183,6 +183,7 @@
#--player-key Media Player
#--song-key Song
#--datetime-key Date Time
#--vulkan-key Vulkan
# Format options:
# Sets the format string for module values.
@@ -218,6 +219,7 @@
#--player-format
#--song-format
#--datetime-format
#--vulkan-format
# Library options:
# Sets an user specific path to a library to load.
+2
View File
@@ -76,6 +76,7 @@ Format options: Provide the format string for custom output. Use fastfetch --hel
--datetime-format <format>
--time-format <format>
--date-format <format>
--vulkan-format <format>
Key options: Provide a custom key for an output
--os-key <key>
@@ -109,6 +110,7 @@ Key options: Provide a custom key for an output
--datetime-key <key>
--time-key <key>
--date-key <key>
--vulkan-key <key>
Library options: Set the path of a library to load
--lib-PCI <path>
+1
View File
@@ -31,5 +31,6 @@ Theme
Time
Title
Uptime
Vulkan
WM
WMTheme
+223
View File
@@ -0,0 +1,223 @@
#include "fastfetch.h"
#include <pthread.h>
#ifdef FF_HAVE_VULKAN
#include <vulkan/vulkan.h>
static inline void applyVulkanVersion(uint32_t vulkanVersion, FFVersion* ffVersion)
{
ffVersion->major = VK_VERSION_MAJOR(vulkanVersion);
ffVersion->minor = VK_VERSION_MINOR(vulkanVersion);
ffVersion->patch = VK_VERSION_PATCH(vulkanVersion);
}
static void applyDriverName(VkPhysicalDeviceDriverProperties* properties, FFstrbuf* result)
{
if(!ffStrSet(properties->driverName))
return;
ffStrbufAppendS(result, properties->driverName);
if(!ffStrSet(properties->driverInfo))
return;
ffStrbufAppendS(result, " [");
ffStrbufAppendS(result, properties->driverInfo);
ffStrbufAppendC(result, ']');
}
static void detectVulkan(const FFinstance* instance, FFVulkanResult* result)
{
FF_LIBRARY_LOAD(vulkan, instance->config.libVulkan, , "libvulkan.so", 2)
FF_LIBRARY_LOAD_SYMBOL(vulkan, vkGetInstanceProcAddr,)
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);
FFVersion instanceVersion = FF_VERSION_INIT;
//We need to get the function pointer this way, because it is only provided by vulkan 1.1 and higher.
//a dlsym would fail on 1.0 implementations
PFN_vkEnumerateInstanceVersion ffvkEnumerateInstanceVersion = (PFN_vkEnumerateInstanceVersion) ffvkGetInstanceProcAddr(NULL, "vkEnumerateInstanceVersion");
if(ffvkEnumerateInstanceVersion != NULL)
{
uint32_t version;
if(ffvkEnumerateInstanceVersion(&version) == VK_SUCCESS)
applyVulkanVersion(version, &instanceVersion);
}
const uint32_t projectVersion = VK_MAKE_VERSION(
FASTFETCH_PROJECT_VERSION_MAJOR,
FASTFETCH_PROJECT_VERSION_MINOR,
FASTFETCH_PROJECT_VERSION_PATCH
);
//We need to request 1.2 to get physicalDeviceDriverProperties
uint32_t requestedVkVersion = VK_API_VERSION_1_0;
if(instanceVersion.minor >= 2)
requestedVkVersion = VK_API_VERSION_1_2;
const VkApplicationInfo applicationInfo = {
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pNext = NULL,
.pApplicationName = FASTFETCH_PROJECT_NAME,
.applicationVersion = projectVersion,
.pEngineName = "vulkanPrintGPUs",
.engineVersion = projectVersion,
.apiVersion = requestedVkVersion
};
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;
}
//if instance creation succeeded, but vkEnumerateInstanceVersion didn't, this means we are running against a vulkan 1.0 implementation
//explicitly set this version, if no device is found, so we still have at least this info
if(instanceVersion.major == 0 && instanceVersion.minor == 0 && instanceVersion.patch == 0)
instanceVersion.major = 1;
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;
}
PFN_vkGetPhysicalDeviceProperties2 ffvkGetPhysicalDeviceProperties2 = (PFN_vkGetPhysicalDeviceProperties2) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceProperties2");
FFVersion maxDeviceApiVersion = FF_VERSION_INIT;
FFVersion maxDeviceConformanceVersion = FF_VERSION_INIT;
for(uint32_t i = 0; i < physicalDeviceCount; i++)
{
//Get device properties.
//On VK 1.2 and up, we use vkGetPhysicalDeviceProperties2, so we can put VkPhysicalDeviceDriverProperties in the pNext chain.
//This is required to get the driver name and conformance version.
VkPhysicalDeviceDriverProperties driverProperties;
driverProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
driverProperties.pNext = NULL;
driverProperties.driverName[0] = '\0';
driverProperties.conformanceVersion = (VkConformanceVersion) {0, 0, 0, 0};
VkPhysicalDeviceProperties2 physicalDeviceProperties;
physicalDeviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
physicalDeviceProperties.pNext = &driverProperties;
if(ffvkGetPhysicalDeviceProperties2 != NULL)
ffvkGetPhysicalDeviceProperties2(physicalDevices[i], &physicalDeviceProperties);
else
ffvkGetPhysicalDeviceProperties(physicalDevices[i], &physicalDeviceProperties.properties);
//If the device api version is higher than the current highest device api version, overwrite it
//In this case, also use the current device driver name as the shown driver name
FFVersion deviceAPIVersion = FF_VERSION_INIT;
applyVulkanVersion(physicalDeviceProperties.properties.apiVersion, &deviceAPIVersion);
if(ffVersionCompare(&deviceAPIVersion, &maxDeviceApiVersion) > 0)
{
maxDeviceApiVersion = deviceAPIVersion;
applyDriverName(&driverProperties, &result->driver);
}
//If the device conformance version is higher than the current highest device conformance version, overwrite it
FFVersion deviceConformanceVersion = FF_VERSION_INIT;
deviceConformanceVersion.major = driverProperties.conformanceVersion.major;
deviceConformanceVersion.minor = driverProperties.conformanceVersion.minor;
deviceConformanceVersion.patch = driverProperties.conformanceVersion.patch;
if(ffVersionCompare(&deviceConformanceVersion, &maxDeviceConformanceVersion) > 0)
maxDeviceConformanceVersion = deviceConformanceVersion;
//Add the device to the list of devices shown by the GPU module
//We don't want softare rasterizers to show up as physical gpu
if(physicalDeviceProperties.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU)
continue;
FFGPUResult* gpu = ffListAdd(&result->devices);
ffStrbufInit(&gpu->vendor);
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
ffStrbufAppendS(&gpu->name, physicalDeviceProperties.properties.deviceName);
}
//If the highest device version is lower than the instance version, use it as our vulkan version
//otherwise the instance version is the vulkan version
if(ffVersionCompare(&instanceVersion, &maxDeviceApiVersion) > 0)
ffVersionToPretty(&maxDeviceApiVersion, &result->apiVersion);
else
ffVersionToPretty(&instanceVersion, &result->apiVersion);
//Use the highest device conformace version as our conformance version
ffVersionToPretty(&maxDeviceConformanceVersion, &result->conformanceVersion);
free(physicalDevices);
ffvkDestroyInstance(vkInstance, NULL);
dlclose(vulkan);
ffSuppressIO(false);
}
#endif
const FFVulkanResult* ffDetectVulkan(const FFinstance* instance)
{
static FFVulkanResult result;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static bool init = false;
pthread_mutex_lock(&mutex);
if(init)
{
pthread_mutex_unlock(&mutex);
return &result;
}
init = true;
ffStrbufInit(&result.driver);
ffStrbufInit(&result.apiVersion);
ffStrbufInit(&result.conformanceVersion);
ffListInit(&result.devices, sizeof(FFGPUResult));
#ifdef FF_HAVE_VULKAN
detectVulkan(instance, &result);
#endif
pthread_mutex_unlock(&mutex);
return &result;
}
+14
View File
@@ -343,6 +343,14 @@ static inline void printCommandHelp(const char* command)
"second with leading zero"
);
}
else if(strcasecmp(command, "vulkan-format") == 0)
{
constructAndPrintCommandHelpFormat("vulkan", "{} (driver), {} (api version)", 3,
"Driver name",
"API version",
"Conformance version"
);
}
else
fprintf(stderr, "No specific help for command %s provided\n", command);
}
@@ -964,6 +972,10 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
optionParseString(key, value, &instance->config.timeKey);
else if(strcasecmp(key, "--time-format") == 0)
optionParseString(key, value, &instance->config.timeFormat);
else if(strcasecmp(key, "--vulkan-key") == 0)
optionParseString(key, value, &instance->config.vulkanKey);
else if(strcasecmp(key, "--vulkan-format") == 0)
optionParseString(key, value, &instance->config.vulkanFormat);
///////////////////
//Library options//
@@ -1165,6 +1177,8 @@ static void parseStructureCommand(FFinstance* instance, FFdata* data, const char
ffPrintTime(instance);
else if(strcasecmp(line, "colors") == 0)
ffPrintColors(instance);
else if(strcasecmp(line, "vulkan") == 0)
ffPrintVulkan(instance);
else
ffPrintError(instance, line, 0, NULL, NULL, 0, "<no implementation provided>");
}
+32
View File
@@ -125,6 +125,8 @@ typedef struct FFconfig
FFstrbuf dateFormat;
FFstrbuf timeKey;
FFstrbuf timeFormat;
FFstrbuf vulkanKey;
FFstrbuf vulkanFormat;
FFstrbuf libPCI;
FFstrbuf libVulkan;
@@ -180,6 +182,14 @@ typedef struct FFinstance
FFstate state;
} FFinstance;
typedef struct FFVersion
{
uint32_t major;
uint32_t minor;
uint32_t patch;
} FFVersion;
#define FF_VERSION_INIT ((FFVersion) {0})
typedef struct FFTitleResult
{
FFstrbuf userName;
@@ -235,6 +245,21 @@ typedef struct FFTerminalShellResult
FFstrbuf userShellVersion;
} FFTerminalShellResult;
typedef struct FFGPUResult
{
FFstrbuf vendor;
FFstrbuf name;
FFstrbuf driver;
} FFGPUResult;
typedef struct FFVulkanResult
{
FFstrbuf driver;
FFstrbuf apiVersion;
FFstrbuf conformanceVersion;
FFlist devices; //List of FFGPUResult
} FFVulkanResult;
typedef struct FFResolutionResult
{
uint32_t width;
@@ -452,6 +477,9 @@ bool ffStrSet(const char* str);
void ffParseSemver(FFstrbuf* buffer, const FFstrbuf* major, const FFstrbuf* minor, const FFstrbuf* patch);
void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, const FFstrbuf* gtk4);
void ffVersionToPretty(const FFVersion* version, FFstrbuf* pretty);
int8_t ffVersionCompare(const FFVersion* version1, const FFVersion* version2);
//common/processing.c
void ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[]);
@@ -517,6 +545,9 @@ const FFMediaResult* ffDetectMedia(FFinstance* instance);
//detection/dateTime.c
const FFDateTimeResult* ffDetectDateTime(const FFinstance* instance);
//detection/vulkan.c
const FFVulkanResult* ffDetectVulkan(const FFinstance* instance);
//////////////////////
// Module functions //
//////////////////////
@@ -564,5 +595,6 @@ void ffPrintTime(FFinstance* instance);
void ffPrintLocalIp(FFinstance* instance);
void ffPrintPublicIp(FFinstance* instance);
void ffPrintColors(FFinstance* instance);
void ffPrintVulkan(FFinstance* instance);
#endif
+2
View File
@@ -4,6 +4,8 @@
#define FASTFETCH_PROJECT_NAME "@PROJECT_NAME@"
#define FASTFETCH_PROJECT_VERSION "@PROJECT_VERSION@"
#define FASTFETCH_PROJECT_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
#define FASTFETCH_PROJECT_VERSION_MINOR @PROJECT_VERSION_MINOR@
#define FASTFETCH_PROJECT_VERSION_PATCH @PROJECT_VERSION_PATCH@
#define FASTFETCH_PROJECT_VERSION_TWEAK "@PROJECT_VERSION_TWEAK@"
#define FASTFETCH_TARGET_DIR_ROOT "@TARGET_DIR_ROOT@"
+119 -194
View File
@@ -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.");
}
+41
View File
@@ -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}
});
}
}