2023-02-14 17:50:53 +08:00
|
|
|
#include "detection/gpu/gpu.h"
|
|
|
|
|
#include "detection/vulkan/vulkan.h"
|
2024-04-18 16:41:19 +08:00
|
|
|
#include "detection/cpu/cpu.h"
|
2024-06-22 22:03:28 +08:00
|
|
|
#include "detection/gpu/gpu_driver_specific.h"
|
2024-01-31 10:20:49 +08:00
|
|
|
#include "common/io/io.h"
|
2024-09-23 14:32:38 +08:00
|
|
|
#include "common/library.h"
|
2024-02-12 00:43:06 +08:00
|
|
|
#include "common/properties.h"
|
2023-02-01 15:56:25 +01:00
|
|
|
#include "util/stringUtils.h"
|
2024-09-27 16:38:01 +08:00
|
|
|
#include "util/mallocHelper.h"
|
2022-09-05 17:42:42 +02:00
|
|
|
|
2024-01-31 10:20:49 +08:00
|
|
|
#include <inttypes.h>
|
2022-09-05 17:42:42 +02:00
|
|
|
|
2024-09-27 00:12:52 +08:00
|
|
|
#ifdef FF_HAVE_DRM_AMDGPU
|
2024-09-23 14:32:38 +08:00
|
|
|
#include <amdgpu.h>
|
|
|
|
|
#include <amdgpu_drm.h>
|
2024-08-02 14:10:07 +08:00
|
|
|
#include <fcntl.h>
|
2024-05-20 15:32:13 +08:00
|
|
|
#endif
|
2024-05-19 20:01:32 +08:00
|
|
|
|
2024-09-27 16:38:01 +08:00
|
|
|
#ifdef FF_HAVE_DRM
|
2024-09-28 08:13:54 +08:00
|
|
|
#include "intel_drm.h"
|
2024-09-27 16:38:01 +08:00
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2024-09-23 14:32:38 +08:00
|
|
|
#include "gpu_asahi.h"
|
|
|
|
|
|
2024-07-30 11:06:27 +08:00
|
|
|
#define FF_STR_INDIR(x) #x
|
|
|
|
|
#define FF_STR(x) FF_STR_INDIR(x)
|
|
|
|
|
|
2024-09-23 14:32:38 +08:00
|
|
|
static bool pciDetectDriver(FFstrbuf* result, FFstrbuf* pciDir, FFstrbuf* buffer, FF_MAYBE_UNUSED const char* drmKey)
|
2024-05-19 20:01:32 +08:00
|
|
|
{
|
2024-07-11 09:51:56 +08:00
|
|
|
uint32_t pciDirLength = pciDir->length;
|
2024-01-31 10:20:49 +08:00
|
|
|
ffStrbufAppendS(pciDir, "/driver");
|
|
|
|
|
char pathBuf[PATH_MAX];
|
2024-10-18 16:15:48 +08:00
|
|
|
ssize_t resultLength = readlink(pciDir->chars, pathBuf, ARRAY_SIZE(pathBuf));
|
2024-07-11 09:51:56 +08:00
|
|
|
if(resultLength <= 0) return false;
|
|
|
|
|
|
|
|
|
|
const char* slash = memrchr(pathBuf, '/', (size_t) resultLength);
|
|
|
|
|
if (slash)
|
2023-01-12 12:54:04 +01:00
|
|
|
{
|
2024-07-11 09:51:56 +08:00
|
|
|
slash++;
|
2024-09-23 14:32:38 +08:00
|
|
|
ffStrbufSetNS(result, (uint32_t) (resultLength - (slash - pathBuf)), slash);
|
2024-07-11 09:51:56 +08:00
|
|
|
}
|
2023-06-24 19:38:12 +08:00
|
|
|
|
2024-09-23 14:32:38 +08:00
|
|
|
if (ffStrbufEqualS(result, "nvidia"))
|
2024-08-01 00:06:22 +08:00
|
|
|
{
|
|
|
|
|
if (ffReadFileBuffer("/proc/driver/nvidia/version", buffer))
|
|
|
|
|
{
|
|
|
|
|
if (ffStrbufContainS(buffer, " Open "))
|
2024-09-23 14:32:38 +08:00
|
|
|
ffStrbufAppendS(result, " (open source)");
|
2024-08-01 00:06:22 +08:00
|
|
|
else
|
2024-09-23 14:32:38 +08:00
|
|
|
ffStrbufAppendS(result, " (proprietary)");
|
2024-08-01 00:06:22 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-11 09:51:56 +08:00
|
|
|
if (instance.config.general.detectVersion)
|
|
|
|
|
{
|
2024-01-31 10:20:49 +08:00
|
|
|
ffStrbufAppendS(pciDir, "/module/version");
|
|
|
|
|
if (ffReadFileBuffer(pciDir->chars, buffer))
|
|
|
|
|
{
|
|
|
|
|
ffStrbufTrimRightSpace(buffer);
|
2024-09-23 14:32:38 +08:00
|
|
|
ffStrbufAppendC(result, ' ');
|
|
|
|
|
ffStrbufAppend(result, buffer);
|
2024-07-11 09:51:56 +08:00
|
|
|
}
|
2024-09-23 14:32:38 +08:00
|
|
|
else if (ffStrbufEqualS(result, "zx"))
|
2024-07-11 09:51:56 +08:00
|
|
|
{
|
|
|
|
|
ffStrbufSubstrBefore(pciDir, pciDirLength);
|
|
|
|
|
ffStrbufAppendS(pciDir, "/zx_info/driver_version");
|
|
|
|
|
if (ffReadFileBuffer(pciDir->chars, buffer))
|
|
|
|
|
{
|
|
|
|
|
ffStrbufTrimRightSpace(buffer);
|
2024-09-23 14:32:38 +08:00
|
|
|
ffStrbufAppendC(result, ' ');
|
|
|
|
|
ffStrbufAppend(result, buffer);
|
2024-07-11 09:51:56 +08:00
|
|
|
}
|
2024-01-31 10:20:49 +08:00
|
|
|
}
|
2023-06-24 19:38:12 +08:00
|
|
|
}
|
2024-05-19 19:34:48 +08:00
|
|
|
|
2024-07-11 09:51:56 +08:00
|
|
|
return true;
|
2023-01-12 11:41:07 +01:00
|
|
|
}
|
|
|
|
|
|
2024-10-06 23:01:49 +08:00
|
|
|
FF_MAYBE_UNUSED static const char* drmFindRenderFromCard(const char* drmCardKey, FFstrbuf* result)
|
2024-09-27 10:47:57 +08:00
|
|
|
{
|
|
|
|
|
char path[PATH_MAX];
|
|
|
|
|
sprintf(path, "/sys/class/drm/%s/device/drm", drmCardKey);
|
|
|
|
|
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(path);
|
|
|
|
|
if (!dirp) return "Failed to open `/sys/class/drm/{drmCardKey}/device/drm`";
|
|
|
|
|
|
|
|
|
|
struct dirent* entry;
|
|
|
|
|
while ((entry = readdir(dirp)) != NULL)
|
|
|
|
|
{
|
|
|
|
|
if (ffStrStartsWith(entry->d_name, "render"))
|
|
|
|
|
{
|
|
|
|
|
ffStrbufSetS(result, "/dev/dri/");
|
|
|
|
|
ffStrbufAppendS(result, entry->d_name);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return "Failed to find render device";
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-23 14:32:38 +08:00
|
|
|
static const char* drmDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu, const char* drmKey, FFstrbuf* buffer)
|
|
|
|
|
{
|
2024-09-27 00:12:52 +08:00
|
|
|
#if FF_HAVE_DRM_AMDGPU
|
2024-09-27 10:47:57 +08:00
|
|
|
|
2024-09-27 00:12:52 +08:00
|
|
|
FF_LIBRARY_LOAD(libdrm, "dlopen libdrm_amdgpu" FF_LIBRARY_EXTENSION " failed", "libdrm_amdgpu" FF_LIBRARY_EXTENSION, 1)
|
2024-09-23 14:32:38 +08:00
|
|
|
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_device_initialize)
|
|
|
|
|
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_get_marketing_name)
|
|
|
|
|
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_gpu_info)
|
|
|
|
|
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_sensor_info)
|
|
|
|
|
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_heap_info)
|
|
|
|
|
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_device_deinitialize)
|
|
|
|
|
|
2024-09-27 10:47:57 +08:00
|
|
|
{
|
|
|
|
|
const char* error = drmFindRenderFromCard(drmKey, buffer);
|
|
|
|
|
if (error) return error;
|
|
|
|
|
}
|
2024-09-23 14:32:38 +08:00
|
|
|
FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY);
|
|
|
|
|
if (fd < 0) return "Failed to open DRM device";
|
|
|
|
|
|
|
|
|
|
amdgpu_device_handle handle;
|
|
|
|
|
uint32_t majorVersion, minorVersion;
|
|
|
|
|
if (ffamdgpu_device_initialize(fd, &majorVersion, &minorVersion, &handle) < 0)
|
|
|
|
|
return "Failed to initialize AMDGPU device";
|
|
|
|
|
|
|
|
|
|
ffStrbufAppendF(&gpu->driver, " %u.%u", (unsigned) majorVersion, (unsigned) minorVersion);
|
|
|
|
|
|
|
|
|
|
uint32_t value;
|
|
|
|
|
|
|
|
|
|
if (options->temp)
|
|
|
|
|
{
|
|
|
|
|
if (ffamdgpu_query_sensor_info(handle, AMDGPU_INFO_SENSOR_GPU_TEMP, sizeof(value), &value) >= 0)
|
2024-09-26 23:53:13 +08:00
|
|
|
gpu->temperature = value / 1000.;
|
2024-09-23 14:32:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ffStrbufSetS(&gpu->name, ffamdgpu_get_marketing_name(handle));
|
|
|
|
|
|
|
|
|
|
struct amdgpu_gpu_info gpuInfo;
|
|
|
|
|
if (ffamdgpu_query_gpu_info(handle, &gpuInfo) >= 0)
|
|
|
|
|
{
|
2024-09-26 23:53:13 +08:00
|
|
|
gpu->coreCount = (int32_t) gpuInfo.cu_active_number;
|
2024-09-23 14:32:38 +08:00
|
|
|
gpu->frequency = (uint32_t) (gpuInfo.max_engine_clk / 1000u);
|
2024-09-26 23:53:13 +08:00
|
|
|
gpu->index = FF_GPU_INDEX_UNSET;
|
2024-09-23 20:40:36 +08:00
|
|
|
gpu->type = gpuInfo.ids_flags & AMDGPU_IDS_FLAGS_FUSION ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
|
|
|
|
|
|
|
|
|
|
struct amdgpu_heap_info heapInfo;
|
|
|
|
|
if (ffamdgpu_query_heap_info(handle, AMDGPU_GEM_DOMAIN_VRAM, 0, &heapInfo) >= 0)
|
|
|
|
|
{
|
|
|
|
|
if (gpu->type == FF_GPU_TYPE_DISCRETE)
|
|
|
|
|
{
|
|
|
|
|
gpu->dedicated.total = heapInfo.heap_size;
|
|
|
|
|
gpu->dedicated.used = heapInfo.heap_usage;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
gpu->shared.total = heapInfo.heap_size;
|
|
|
|
|
gpu->shared.used = heapInfo.heap_usage;
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-09-23 14:32:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ffamdgpu_query_sensor_info(handle, AMDGPU_INFO_SENSOR_GPU_LOAD, sizeof(value), &value) >= 0)
|
|
|
|
|
gpu->coreUsage = value;
|
|
|
|
|
|
|
|
|
|
ffamdgpu_device_deinitialize(handle);
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
#else
|
2024-09-27 00:12:52 +08:00
|
|
|
FF_UNUSED(options, gpu, drmKey, buffer);
|
2024-09-23 14:32:38 +08:00
|
|
|
return "Fastfetch is compiled without libdrm support";
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-29 20:05:40 +08:00
|
|
|
static void pciDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
|
2024-04-17 14:21:30 +08:00
|
|
|
{
|
|
|
|
|
// https://www.kernel.org/doc/html/v5.10/gpu/amdgpu.html#mem-info-vis-vram-total
|
2024-04-29 20:05:40 +08:00
|
|
|
const uint32_t pciDirLen = pciDir->length;
|
|
|
|
|
|
|
|
|
|
ffStrbufAppendS(pciDir, "/hwmon/");
|
|
|
|
|
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(pciDir->chars);
|
2024-05-03 08:28:20 +08:00
|
|
|
if (!dirp) return;
|
|
|
|
|
|
2024-04-29 20:28:50 +08:00
|
|
|
struct dirent* entry;
|
|
|
|
|
while ((entry = readdir(dirp)) != NULL)
|
|
|
|
|
{
|
|
|
|
|
if (entry->d_name[0] == '.') continue;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2024-04-29 20:05:40 +08:00
|
|
|
if (!entry) return;
|
|
|
|
|
ffStrbufAppendS(pciDir, entry->d_name);
|
|
|
|
|
ffStrbufAppendC(pciDir, '/');
|
|
|
|
|
|
|
|
|
|
const uint32_t hwmonLen = pciDir->length;
|
|
|
|
|
ffStrbufAppendS(pciDir, "in1_input"); // Northbridge voltage in millivolts (APUs only)
|
2024-07-08 09:11:53 +08:00
|
|
|
if (ffPathExists(pciDir->chars, FF_PATHTYPE_ANY))
|
2024-04-29 20:05:40 +08:00
|
|
|
gpu->type = FF_GPU_TYPE_INTEGRATED;
|
|
|
|
|
else
|
|
|
|
|
gpu->type = FF_GPU_TYPE_DISCRETE;
|
|
|
|
|
|
|
|
|
|
uint64_t value = 0;
|
|
|
|
|
if (options->temp)
|
|
|
|
|
{
|
|
|
|
|
ffStrbufSubstrBefore(pciDir, hwmonLen);
|
|
|
|
|
ffStrbufAppendS(pciDir, "temp1_input"); // The on die GPU temperature in millidegrees Celsius
|
|
|
|
|
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
|
2024-04-29 20:43:19 +08:00
|
|
|
gpu->temperature = (double) value / 1000;
|
2024-04-29 20:05:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (options->driverSpecific)
|
2024-04-17 14:21:30 +08:00
|
|
|
{
|
2024-04-29 20:05:40 +08:00
|
|
|
ffStrbufSubstrBefore(pciDir, pciDirLen);
|
|
|
|
|
ffStrbufAppendS(pciDir, "/mem_info_vis_vram_total");
|
|
|
|
|
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
|
2024-04-17 14:21:30 +08:00
|
|
|
{
|
2024-09-23 14:32:38 +08:00
|
|
|
if (gpu->type == FF_GPU_TYPE_DISCRETE)
|
|
|
|
|
gpu->dedicated.total = value;
|
|
|
|
|
else
|
|
|
|
|
gpu->shared.total = value;
|
|
|
|
|
|
2024-04-29 20:05:40 +08:00
|
|
|
ffStrbufSubstrBefore(pciDir, pciDir->length - (uint32_t) strlen("/mem_info_vis_vram_total"));
|
2024-04-29 14:17:13 +08:00
|
|
|
ffStrbufAppendS(pciDir, "/mem_info_vis_vram_used");
|
2024-04-29 20:05:40 +08:00
|
|
|
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
|
|
|
|
|
{
|
|
|
|
|
if (gpu->type == FF_GPU_TYPE_DISCRETE)
|
|
|
|
|
gpu->dedicated.used = value;
|
|
|
|
|
else
|
|
|
|
|
gpu->shared.used = value;
|
|
|
|
|
}
|
2024-04-17 14:21:30 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-27 16:38:01 +08:00
|
|
|
static void pciDetectIntelSpecific(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer, const char* drmKey)
|
2024-04-18 16:41:19 +08:00
|
|
|
{
|
|
|
|
|
// Works for Intel GPUs
|
|
|
|
|
// https://patchwork.kernel.org/project/intel-gfx/patch/1422039866-11572-3-git-send-email-ville.syrjala@linux.intel.com/
|
2024-04-29 20:05:40 +08:00
|
|
|
|
2024-09-23 20:40:36 +08:00
|
|
|
// 0000:00:02.0 is reserved for Intel integrated graphics
|
|
|
|
|
gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
|
2024-05-19 18:40:32 +08:00
|
|
|
|
2024-09-27 16:38:01 +08:00
|
|
|
if (!drmKey) return;
|
|
|
|
|
|
2024-07-12 19:24:55 +08:00
|
|
|
if (ffStrbufEqualS(&gpu->driver, "xe"))
|
|
|
|
|
ffStrbufAppendS(pciDir, "/tile0/gt0/freq0/max_freq");
|
|
|
|
|
else
|
2024-09-28 08:13:54 +08:00
|
|
|
ffStrbufAppendF(pciDir, "/drm/%s/gt_max_freq_mhz", drmKey);
|
2024-05-19 18:40:32 +08:00
|
|
|
if (ffReadFileBuffer(pciDir->chars, buffer))
|
2024-07-17 14:52:35 +08:00
|
|
|
gpu->frequency = (uint32_t) ffStrbufToUInt(buffer, 0);
|
2024-04-18 16:41:19 +08:00
|
|
|
}
|
|
|
|
|
|
2024-09-27 16:38:01 +08:00
|
|
|
static inline int popcountBytes(uint8_t* bytes, uint32_t length)
|
|
|
|
|
{
|
|
|
|
|
int count = 0;
|
|
|
|
|
while (length >= 8)
|
|
|
|
|
{
|
|
|
|
|
count += __builtin_popcountll(*(uint64_t*) bytes);
|
|
|
|
|
bytes += 8;
|
|
|
|
|
length -= 8;
|
|
|
|
|
}
|
|
|
|
|
if (length >= 4)
|
|
|
|
|
{
|
|
|
|
|
count += __builtin_popcountl(*(uint32_t*) bytes);
|
|
|
|
|
bytes += 4;
|
|
|
|
|
length -= 4;
|
|
|
|
|
}
|
|
|
|
|
if (length >= 2)
|
|
|
|
|
{
|
|
|
|
|
count += __builtin_popcountl(*(uint16_t*) bytes);
|
|
|
|
|
bytes += 2;
|
|
|
|
|
length -= 2;
|
|
|
|
|
}
|
|
|
|
|
if (length)
|
|
|
|
|
{
|
|
|
|
|
count += __builtin_popcountl(*(uint8_t*) bytes);
|
|
|
|
|
}
|
|
|
|
|
return count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char* drmDetectIntelSpecific(FFGPUResult* gpu, const char* drmKey, FFstrbuf* buffer)
|
|
|
|
|
{
|
|
|
|
|
#if FF_HAVE_DRM
|
|
|
|
|
ffStrbufSetS(buffer, "/dev/dri/");
|
|
|
|
|
ffStrbufAppendS(buffer, drmKey);
|
|
|
|
|
FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY);
|
|
|
|
|
if (fd < 0) return "Failed to open drm device";
|
|
|
|
|
|
|
|
|
|
if (ffStrbufEqualS(&gpu->driver, "xe"))
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
struct drm_xe_device_query query = {
|
|
|
|
|
.extensions = 0,
|
|
|
|
|
.query = DRM_XE_DEVICE_QUERY_GT_TOPOLOGY,
|
|
|
|
|
.size = 0,
|
|
|
|
|
.data = 0,
|
|
|
|
|
};
|
|
|
|
|
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0)
|
|
|
|
|
{
|
|
|
|
|
FF_AUTO_FREE uint8_t* buffer = malloc(query.size);
|
|
|
|
|
query.data = (uintptr_t) buffer;
|
|
|
|
|
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0)
|
|
|
|
|
{
|
|
|
|
|
int dssCount = 0, euPerDssCount = 0;
|
|
|
|
|
for (struct drm_xe_query_topology_mask* topo = (void*) buffer;
|
|
|
|
|
(uint8_t*) topo < buffer + query.size;
|
|
|
|
|
topo = (void*) (topo->mask + topo->num_bytes)
|
|
|
|
|
) {
|
|
|
|
|
switch (topo->type)
|
|
|
|
|
{
|
|
|
|
|
case DRM_XE_TOPO_DSS_COMPUTE:
|
|
|
|
|
case DRM_XE_TOPO_DSS_GEOMETRY:
|
|
|
|
|
dssCount += popcountBytes(topo->mask, topo->num_bytes);
|
|
|
|
|
break;
|
|
|
|
|
case DRM_XE_TOPO_EU_PER_DSS:
|
|
|
|
|
euPerDssCount += popcountBytes(topo->mask, topo->num_bytes);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
gpu->coreCount = dssCount * euPerDssCount;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
struct drm_xe_device_query query = {
|
|
|
|
|
.query = DRM_XE_DEVICE_QUERY_MEM_REGIONS,
|
|
|
|
|
};
|
|
|
|
|
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0)
|
|
|
|
|
{
|
|
|
|
|
FF_AUTO_FREE uint8_t* buffer = malloc(query.size);
|
|
|
|
|
query.data = (uintptr_t) buffer;
|
|
|
|
|
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0)
|
|
|
|
|
{
|
|
|
|
|
gpu->dedicated.total = gpu->shared.total = gpu->dedicated.used = gpu->shared.used = 0;
|
|
|
|
|
struct drm_xe_query_mem_regions* regionInfo = (void*) buffer;
|
|
|
|
|
for (uint32_t i = 0; i < regionInfo->num_mem_regions; i++)
|
|
|
|
|
{
|
|
|
|
|
struct drm_xe_mem_region* region = regionInfo->mem_regions + i;
|
|
|
|
|
switch (region->mem_class)
|
|
|
|
|
{
|
|
|
|
|
case DRM_XE_MEM_REGION_CLASS_SYSMEM:
|
|
|
|
|
gpu->shared.total += region->total_size;
|
|
|
|
|
gpu->shared.used += region->used;
|
|
|
|
|
break;
|
|
|
|
|
case DRM_XE_MEM_REGION_CLASS_VRAM:
|
|
|
|
|
gpu->dedicated.total += region->total_size;
|
|
|
|
|
gpu->dedicated.used += region->used;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (ffStrbufEqualS(&gpu->driver, "i915"))
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
int value;
|
|
|
|
|
drm_i915_getparam_t getparam = { .param = I915_PARAM_EU_TOTAL, .value = &value };
|
|
|
|
|
if (ioctl(fd, DRM_IOCTL_I915_GETPARAM, &getparam) >= 0)
|
|
|
|
|
gpu->coreCount = value;
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_query_item queryItem = {
|
|
|
|
|
.query_id = DRM_I915_QUERY_MEMORY_REGIONS,
|
|
|
|
|
};
|
|
|
|
|
struct drm_i915_query query = {
|
|
|
|
|
.items_ptr = (uintptr_t) &queryItem,
|
|
|
|
|
.num_items = 1,
|
|
|
|
|
};
|
|
|
|
|
if (ioctl(fd, DRM_IOCTL_I915_QUERY, &query) >= 0 )
|
|
|
|
|
{
|
|
|
|
|
FF_AUTO_FREE uint8_t* buffer = calloc(1, (size_t) queryItem.length);
|
|
|
|
|
queryItem.data_ptr = (uintptr_t) buffer;
|
|
|
|
|
if (ioctl(fd, DRM_IOCTL_I915_QUERY, &query) >= 0)
|
|
|
|
|
{
|
|
|
|
|
gpu->dedicated.total = gpu->shared.total = gpu->dedicated.used = gpu->shared.used = 0;
|
|
|
|
|
struct drm_i915_query_memory_regions* regionInfo = (void*) buffer;
|
|
|
|
|
for (uint32_t i = 0; i < regionInfo->num_regions; i++)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_memory_region_info* region = regionInfo->regions + i;
|
|
|
|
|
switch (region->region.memory_class)
|
|
|
|
|
{
|
|
|
|
|
case I915_MEMORY_CLASS_SYSTEM:
|
|
|
|
|
gpu->shared.total += region->probed_size;
|
|
|
|
|
gpu->shared.used += region->probed_size - region->unallocated_size;
|
|
|
|
|
break;
|
|
|
|
|
case I915_MEMORY_CLASS_DEVICE:
|
|
|
|
|
gpu->dedicated.total += region->probed_size;
|
|
|
|
|
gpu->dedicated.used += region->probed_size - region->unallocated_size;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
#else
|
2024-10-06 23:01:49 +08:00
|
|
|
FF_UNUSED(gpu, drmKey, buffer);
|
2024-09-27 16:38:01 +08:00
|
|
|
return "Fastfetch is not compiled with drm support";
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-19 20:01:32 +08:00
|
|
|
static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf* buffer, FFstrbuf* deviceDir, const char* drmKey)
|
2024-01-31 10:20:49 +08:00
|
|
|
{
|
2024-05-19 19:34:48 +08:00
|
|
|
const uint32_t drmDirPathLength = deviceDir->length;
|
2024-04-18 16:41:19 +08:00
|
|
|
uint32_t vendorId, deviceId, subVendorId, subDeviceId;
|
|
|
|
|
uint8_t classId, subclassId;
|
|
|
|
|
if (sscanf(buffer->chars + strlen("pci:"), "v%8" SCNx32 "d%8" SCNx32 "sv%8" SCNx32 "sd%8" SCNx32 "bc%2" SCNx8 "sc%2" SCNx8, &vendorId, &deviceId, &subVendorId, &subDeviceId, &classId, &subclassId) != 6)
|
2024-09-24 16:34:35 +08:00
|
|
|
return "Failed to parse pci modalias";
|
2024-04-18 16:41:19 +08:00
|
|
|
|
|
|
|
|
if (classId != 0x03 /*PCI_BASE_CLASS_DISPLAY*/)
|
2024-04-18 21:00:47 +08:00
|
|
|
return "Not a GPU device";
|
2024-04-18 16:41:19 +08:00
|
|
|
|
|
|
|
|
char pciPath[PATH_MAX];
|
2024-05-19 19:34:48 +08:00
|
|
|
const char* pPciPath = NULL;
|
2024-05-19 20:01:32 +08:00
|
|
|
if (drmKey)
|
2024-05-19 19:34:48 +08:00
|
|
|
{
|
2024-10-18 16:15:48 +08:00
|
|
|
ssize_t pathLength = readlink(deviceDir->chars, pciPath, ARRAY_SIZE(pciPath) - 1);
|
2024-05-19 19:34:48 +08:00
|
|
|
if (pathLength <= 0)
|
|
|
|
|
return "Unable to get PCI device path";
|
|
|
|
|
pciPath[pathLength] = '\0';
|
|
|
|
|
pPciPath = strrchr(pciPath, '/');
|
|
|
|
|
if (__builtin_expect(pPciPath != NULL, true))
|
|
|
|
|
pPciPath++;
|
|
|
|
|
else
|
|
|
|
|
pPciPath = pciPath;
|
|
|
|
|
}
|
2024-04-18 16:41:19 +08:00
|
|
|
else
|
2024-05-19 19:34:48 +08:00
|
|
|
{
|
|
|
|
|
pPciPath = memrchr(deviceDir->chars, '/', deviceDir->length) + 1;
|
|
|
|
|
}
|
2024-04-18 16:41:19 +08:00
|
|
|
|
|
|
|
|
uint32_t pciDomain, pciBus, pciDevice, pciFunc;
|
|
|
|
|
if (sscanf(pPciPath, "%" SCNx32 ":%" SCNx32 ":%" SCNx32 ".%" SCNx32, &pciDomain, &pciBus, &pciDevice, &pciFunc) != 4)
|
|
|
|
|
return "Invalid PCI device path";
|
|
|
|
|
|
|
|
|
|
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
|
|
|
|
|
ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString((uint16_t) vendorId));
|
|
|
|
|
ffStrbufInit(&gpu->name);
|
|
|
|
|
ffStrbufInit(&gpu->driver);
|
|
|
|
|
ffStrbufInit(&gpu->platformApi);
|
2024-09-19 15:22:09 +08:00
|
|
|
gpu->index = FF_GPU_INDEX_UNSET;
|
2024-04-18 16:41:19 +08:00
|
|
|
gpu->temperature = FF_GPU_TEMP_UNSET;
|
2024-08-10 21:08:35 +08:00
|
|
|
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
|
2024-04-18 16:41:19 +08:00
|
|
|
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
|
|
|
|
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
|
|
|
|
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
2024-09-23 20:40:36 +08:00
|
|
|
gpu->deviceId = (pciDomain * 100000ull) + (pciBus * 1000ull) + (pciDevice * 10ull) + pciFunc;
|
2024-04-18 16:41:19 +08:00
|
|
|
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
|
|
|
|
|
2024-09-27 16:38:01 +08:00
|
|
|
char drmKeyBuffer[8];
|
2024-09-28 08:13:54 +08:00
|
|
|
if (!drmKey)
|
2024-09-27 16:38:01 +08:00
|
|
|
{
|
|
|
|
|
ffStrbufAppendS(deviceDir, "/drm");
|
|
|
|
|
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(deviceDir->chars);
|
|
|
|
|
if (dirp)
|
|
|
|
|
{
|
|
|
|
|
struct dirent* entry;
|
|
|
|
|
while ((entry = readdir(dirp)) != NULL)
|
|
|
|
|
{
|
|
|
|
|
if (ffStrStartsWith(entry->d_name, "card"))
|
|
|
|
|
{
|
2024-11-11 18:02:23 +08:00
|
|
|
ffStrCopy(drmKeyBuffer, entry->d_name, ARRAY_SIZE(drmKeyBuffer));
|
2024-09-27 16:38:01 +08:00
|
|
|
drmKey = drmKeyBuffer;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-19 20:01:32 +08:00
|
|
|
if (drmKey) ffStrbufSetF(&gpu->platformApi, "DRM (%s)", drmKey);
|
|
|
|
|
|
2024-09-23 14:32:38 +08:00
|
|
|
pciDetectDriver(&gpu->driver, deviceDir, buffer, drmKey);
|
2024-05-19 19:34:48 +08:00
|
|
|
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
|
2023-06-22 04:06:08 +00:00
|
|
|
|
2024-04-29 20:05:40 +08:00
|
|
|
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
|
2023-10-27 21:05:03 +08:00
|
|
|
{
|
2024-09-23 14:32:38 +08:00
|
|
|
bool ok = false;
|
|
|
|
|
if (drmKey && options->driverSpecific)
|
|
|
|
|
ok = drmDetectAmdSpecific(options, gpu, drmKey, buffer) == NULL;
|
|
|
|
|
|
|
|
|
|
if (!ok)
|
|
|
|
|
{
|
|
|
|
|
pciDetectAmdSpecific(options, gpu, deviceDir, buffer);
|
|
|
|
|
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
|
|
|
|
|
|
|
|
|
|
ffStrbufAppendS(deviceDir, "/revision");
|
|
|
|
|
if (ffReadFileBuffer(deviceDir->chars, buffer))
|
|
|
|
|
{
|
|
|
|
|
char* pend;
|
|
|
|
|
uint64_t revision = strtoul(buffer->chars, &pend, 16);
|
|
|
|
|
if (pend != buffer->chars)
|
|
|
|
|
{
|
|
|
|
|
char query[32];
|
2024-10-18 16:15:48 +08:00
|
|
|
snprintf(query, ARRAY_SIZE(query), "%X,\t%X,", (unsigned) deviceId, (unsigned) revision);
|
2024-09-23 14:32:38 +08:00
|
|
|
#ifdef FF_CUSTOM_AMDGPU_IDS_PATH
|
|
|
|
|
ffParsePropFile(FF_STR(FF_CUSTOM_AMDGPU_IDS_PATH), query, &gpu->name);
|
|
|
|
|
#else
|
|
|
|
|
ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
|
|
|
|
|
}
|
2024-04-18 16:41:19 +08:00
|
|
|
}
|
2024-04-29 20:05:40 +08:00
|
|
|
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
|
|
|
|
|
{
|
2024-09-27 16:38:01 +08:00
|
|
|
pciDetectIntelSpecific(gpu, deviceDir, buffer, drmKey);
|
2024-05-19 19:34:48 +08:00
|
|
|
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
|
2024-09-27 16:38:01 +08:00
|
|
|
if (options->driverSpecific && drmKey)
|
|
|
|
|
drmDetectIntelSpecific(gpu, drmKey, buffer);
|
2024-04-29 20:05:40 +08:00
|
|
|
}
|
2024-08-02 16:29:23 +08:00
|
|
|
else
|
2024-04-29 20:05:40 +08:00
|
|
|
{
|
2024-08-02 16:29:23 +08:00
|
|
|
__typeof__(&ffDetectNvidiaGpuInfo) detectFn;
|
|
|
|
|
const char* soName;
|
|
|
|
|
if (getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &soName) && (options->temp || options->driverSpecific))
|
2024-04-29 20:05:40 +08:00
|
|
|
{
|
2024-08-02 16:29:23 +08:00
|
|
|
detectFn(&(FFGpuDriverCondition) {
|
2024-04-29 20:05:40 +08:00
|
|
|
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
|
|
|
|
|
.pciBusId = {
|
|
|
|
|
.domain = pciDomain,
|
|
|
|
|
.bus = pciBus,
|
|
|
|
|
.device = pciDevice,
|
|
|
|
|
.func = pciFunc,
|
|
|
|
|
},
|
|
|
|
|
}, (FFGpuDriverResult) {
|
2024-09-19 15:22:09 +08:00
|
|
|
.index = &gpu->index,
|
2024-04-29 20:05:40 +08:00
|
|
|
.temp = options->temp ? &gpu->temperature : NULL,
|
|
|
|
|
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
|
|
|
|
|
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
|
2024-08-02 16:29:23 +08:00
|
|
|
.coreUsage = options->driverSpecific ? &gpu->coreUsage : NULL,
|
2024-04-29 20:05:40 +08:00
|
|
|
.type = &gpu->type,
|
2024-06-28 22:17:37 +08:00
|
|
|
.frequency = options->driverSpecific ? &gpu->frequency : NULL,
|
2024-09-27 10:58:35 +08:00
|
|
|
.name = &gpu->name,
|
2024-08-02 16:29:23 +08:00
|
|
|
}, soName);
|
2024-04-29 20:05:40 +08:00
|
|
|
}
|
2023-03-13 17:45:36 +08:00
|
|
|
|
2024-04-29 20:05:40 +08:00
|
|
|
if (gpu->type == FF_GPU_TYPE_UNKNOWN)
|
|
|
|
|
{
|
2024-08-02 16:29:23 +08:00
|
|
|
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA)
|
|
|
|
|
{
|
|
|
|
|
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "GeForce") ||
|
|
|
|
|
ffStrbufStartsWithIgnCaseS(&gpu->name, "Quadro") ||
|
|
|
|
|
ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla"))
|
|
|
|
|
gpu->type = FF_GPU_TYPE_DISCRETE;
|
|
|
|
|
}
|
|
|
|
|
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS)
|
|
|
|
|
{
|
|
|
|
|
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT "))
|
|
|
|
|
gpu->type = FF_GPU_TYPE_DISCRETE;
|
|
|
|
|
}
|
2024-08-02 16:00:54 +08:00
|
|
|
}
|
|
|
|
|
}
|
2022-09-05 17:42:42 +02:00
|
|
|
|
2024-09-27 10:58:35 +08:00
|
|
|
if (gpu->name.length == 0)
|
|
|
|
|
ffGPUFillVendorAndName(subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu);
|
|
|
|
|
|
2024-04-18 16:41:19 +08:00
|
|
|
return NULL;
|
|
|
|
|
}
|
2024-01-31 10:20:49 +08:00
|
|
|
|
2024-08-02 14:13:33 +08:00
|
|
|
#if __aarch64__
|
|
|
|
|
|
2024-09-24 16:34:35 +08:00
|
|
|
FF_MAYBE_UNUSED static const char* drmDetectAsahiSpecific(FFGPUResult* gpu, const char* name, FFstrbuf* buffer, const char* drmKey)
|
2024-04-18 16:41:19 +08:00
|
|
|
{
|
2024-09-24 16:34:35 +08:00
|
|
|
if (sscanf(name, "agx-t%lu", &gpu->deviceId) == 1)
|
|
|
|
|
ffStrbufSetStatic(&gpu->name, ffCPUAppleCodeToName((uint32_t) gpu->deviceId));
|
|
|
|
|
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE);
|
2024-04-18 16:41:19 +08:00
|
|
|
|
2024-08-02 14:07:04 +08:00
|
|
|
#if FF_HAVE_DRM
|
2024-05-20 15:32:13 +08:00
|
|
|
ffStrbufSetS(buffer, "/dev/dri/");
|
|
|
|
|
ffStrbufAppendS(buffer, drmKey);
|
|
|
|
|
FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY);
|
|
|
|
|
if (fd >= 0)
|
|
|
|
|
{
|
|
|
|
|
struct drm_asahi_params_global paramsGlobal = {};
|
2024-09-23 14:32:38 +08:00
|
|
|
if (ioctl(fd, DRM_IOCTL_ASAHI_GET_PARAMS, &(struct drm_asahi_get_params) {
|
2024-05-20 15:32:13 +08:00
|
|
|
.param_group = DRM_ASAHI_GET_PARAMS,
|
|
|
|
|
.pointer = (uint64_t) ¶msGlobal,
|
|
|
|
|
.size = sizeof(paramsGlobal),
|
|
|
|
|
}) >= 0)
|
|
|
|
|
{
|
2024-09-24 16:34:35 +08:00
|
|
|
ffStrbufAppendF(&gpu->driver, " %u", paramsGlobal.unstable_uabi_version);
|
2024-09-23 14:32:38 +08:00
|
|
|
|
2024-08-06 10:14:39 +08:00
|
|
|
// FIXME: They will introduce ABI breaking changes. Always check the latest version
|
|
|
|
|
// https://www.reddit.com/r/AsahiLinux/comments/1ei2qiv/comment/lgm0v5s/
|
|
|
|
|
if (paramsGlobal.unstable_uabi_version == DRM_ASAHI_UNSTABLE_UABI_VERSION)
|
|
|
|
|
{
|
|
|
|
|
gpu->coreCount = (int) paramsGlobal.num_cores_total_active;
|
|
|
|
|
gpu->frequency = paramsGlobal.max_frequency_khz / 1000;
|
|
|
|
|
gpu->deviceId = paramsGlobal.chip_id;
|
2024-09-23 14:32:38 +08:00
|
|
|
|
|
|
|
|
if (!gpu->name.length)
|
|
|
|
|
{
|
|
|
|
|
const char* variant = " Unknown";
|
|
|
|
|
switch (paramsGlobal.gpu_variant) {
|
|
|
|
|
case 'G':
|
|
|
|
|
variant = "";
|
|
|
|
|
break;
|
|
|
|
|
case 'S':
|
|
|
|
|
variant = " Pro";
|
|
|
|
|
break;
|
|
|
|
|
case 'C':
|
|
|
|
|
variant = " Max";
|
|
|
|
|
break;
|
|
|
|
|
case 'D':
|
|
|
|
|
variant = " Ultra";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
ffStrbufSetF(&gpu->name, "Apple M%d%s (G%d%c %02X)",
|
|
|
|
|
paramsGlobal.gpu_generation - 12, variant,
|
|
|
|
|
paramsGlobal.gpu_generation, paramsGlobal.gpu_variant,
|
|
|
|
|
paramsGlobal.gpu_revision + 0xA0);
|
|
|
|
|
}
|
2024-08-06 10:14:39 +08:00
|
|
|
}
|
2024-05-20 15:32:13 +08:00
|
|
|
}
|
|
|
|
|
}
|
2024-09-24 16:34:35 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static const char* detectOf(FFlist* gpus, FFstrbuf* buffer, FFstrbuf* drmDir, const char* drmKey)
|
|
|
|
|
{
|
|
|
|
|
char compatible[256]; // vendor,model-name
|
2024-10-01 09:30:39 +08:00
|
|
|
if (sscanf(buffer->chars + strlen("of:"), "NgpuT%*[^C]C%255[^C]", compatible) != 1)
|
2024-09-24 16:34:35 +08:00
|
|
|
return "Failed to parse of modalias or not a GPU device";
|
2024-09-23 14:32:38 +08:00
|
|
|
|
2024-09-24 16:34:35 +08:00
|
|
|
char* name = strchr(compatible, ',');
|
|
|
|
|
if (name)
|
2024-09-23 14:32:38 +08:00
|
|
|
{
|
2024-09-24 16:34:35 +08:00
|
|
|
*name = '\0';
|
|
|
|
|
++name;
|
2024-09-23 14:32:38 +08:00
|
|
|
}
|
2024-09-24 16:34:35 +08:00
|
|
|
|
|
|
|
|
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
|
|
|
|
|
gpu->index = FF_GPU_INDEX_UNSET;
|
|
|
|
|
gpu->deviceId = 0;
|
|
|
|
|
ffStrbufInit(&gpu->name);
|
|
|
|
|
ffStrbufInit(&gpu->vendor);
|
|
|
|
|
ffStrbufInit(&gpu->driver);
|
|
|
|
|
ffStrbufInitF(&gpu->platformApi, "DRM (%s)", drmKey);
|
|
|
|
|
gpu->temperature = FF_GPU_TEMP_UNSET;
|
|
|
|
|
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
|
|
|
|
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
|
|
|
|
|
gpu->type = FF_GPU_TYPE_INTEGRATED;
|
|
|
|
|
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
|
|
|
|
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
|
|
|
|
|
|
|
|
|
pciDetectDriver(&gpu->driver, drmDir, buffer, drmKey);
|
|
|
|
|
|
|
|
|
|
#ifdef __aarch64__
|
|
|
|
|
if (ffStrbufEqualS(&gpu->driver, "asahi"))
|
|
|
|
|
drmDetectAsahiSpecific(gpu, name, buffer, drmKey);
|
2024-05-20 15:32:13 +08:00
|
|
|
#endif
|
|
|
|
|
|
2024-09-24 16:34:35 +08:00
|
|
|
if (!gpu->name.length)
|
2024-09-29 23:08:41 +08:00
|
|
|
{
|
2024-09-24 16:34:35 +08:00
|
|
|
ffStrbufSetS(&gpu->name, name ? name : compatible);
|
2024-09-29 23:08:41 +08:00
|
|
|
ffStrbufTrimRightSpace(&gpu->name);
|
|
|
|
|
}
|
2024-09-24 16:34:35 +08:00
|
|
|
if (!gpu->vendor.length && name)
|
|
|
|
|
{
|
2024-09-30 15:02:49 +08:00
|
|
|
if (ffStrEquals(compatible, "brcm"))
|
|
|
|
|
ffStrbufSetStatic(&gpu->vendor, "Broadcom"); // Raspberry Pi
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ffStrbufSetS(&gpu->vendor, compatible);
|
|
|
|
|
gpu->vendor.chars[0] = (char) toupper(compatible[0]);
|
|
|
|
|
}
|
2024-09-24 16:34:35 +08:00
|
|
|
}
|
|
|
|
|
|
2024-04-18 16:41:19 +08:00
|
|
|
return NULL;
|
|
|
|
|
}
|
2024-01-31 10:20:49 +08:00
|
|
|
|
2024-04-18 16:41:19 +08:00
|
|
|
static const char* drmDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
|
|
|
|
|
{
|
|
|
|
|
FF_STRBUF_AUTO_DESTROY drmDir = ffStrbufCreateA(64);
|
|
|
|
|
ffStrbufAppendS(&drmDir, "/sys/class/drm/");
|
|
|
|
|
const uint32_t drmDirLength = drmDir.length;
|
2024-01-31 10:20:49 +08:00
|
|
|
|
2024-04-18 16:41:19 +08:00
|
|
|
FF_AUTO_CLOSE_DIR DIR* dir = opendir(drmDir.chars);
|
|
|
|
|
if(dir == NULL)
|
2024-04-18 21:00:47 +08:00
|
|
|
return "Failed to open `/sys/class/drm/`";
|
2024-02-12 00:43:06 +08:00
|
|
|
|
2024-04-18 16:41:19 +08:00
|
|
|
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
2022-09-05 17:42:42 +02:00
|
|
|
|
2024-04-18 16:41:19 +08:00
|
|
|
struct dirent* entry;
|
|
|
|
|
while ((entry = readdir(dir)) != NULL)
|
|
|
|
|
{
|
|
|
|
|
if (!ffStrStartsWith(entry->d_name, "card") ||
|
|
|
|
|
strchr(entry->d_name + 4, '-') != NULL)
|
|
|
|
|
continue;
|
2024-04-17 14:21:30 +08:00
|
|
|
|
2024-04-18 16:41:19 +08:00
|
|
|
ffStrbufAppendS(&drmDir, entry->d_name);
|
2023-03-13 17:45:36 +08:00
|
|
|
|
2024-04-18 16:41:19 +08:00
|
|
|
ffStrbufAppendS(&drmDir, "/device/modalias");
|
|
|
|
|
if (!ffReadFileBuffer(drmDir.chars, &buffer))
|
|
|
|
|
continue;
|
|
|
|
|
ffStrbufSubstrBefore(&drmDir, drmDir.length - (uint32_t) strlen("/modalias"));
|
2022-09-05 17:42:42 +02:00
|
|
|
|
2024-04-18 16:41:19 +08:00
|
|
|
if (ffStrbufStartsWithS(&buffer, "pci:"))
|
2024-05-19 19:34:48 +08:00
|
|
|
detectPci(options, gpus, &buffer, &drmDir, entry->d_name);
|
2024-04-18 16:41:19 +08:00
|
|
|
else if (ffStrbufStartsWithS(&buffer, "of:"))
|
2024-09-24 16:34:35 +08:00
|
|
|
detectOf(gpus, &buffer, &drmDir, entry->d_name);
|
2024-04-18 16:41:19 +08:00
|
|
|
|
|
|
|
|
ffStrbufSubstrBefore(&drmDir, drmDirLength);
|
2022-09-05 17:42:42 +02:00
|
|
|
}
|
|
|
|
|
|
2022-09-16 18:11:39 +08:00
|
|
|
return NULL;
|
2022-09-05 17:42:42 +02:00
|
|
|
}
|
|
|
|
|
|
2024-04-18 21:00:47 +08:00
|
|
|
|
|
|
|
|
static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
|
|
|
|
|
{
|
|
|
|
|
//https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-bus-pci
|
|
|
|
|
const char* pciDirPath = "/sys/bus/pci/devices/";
|
|
|
|
|
|
|
|
|
|
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(pciDirPath);
|
|
|
|
|
if(dirp == NULL)
|
|
|
|
|
return "Failed to open `/sys/bus/pci/devices/`";
|
|
|
|
|
|
|
|
|
|
FF_STRBUF_AUTO_DESTROY pciDir = ffStrbufCreateA(64);
|
|
|
|
|
ffStrbufAppendS(&pciDir, pciDirPath);
|
|
|
|
|
|
|
|
|
|
const uint32_t pciBaseDirLength = pciDir.length;
|
|
|
|
|
|
|
|
|
|
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
|
|
|
|
|
|
|
|
|
struct dirent* entry;
|
|
|
|
|
while((entry = readdir(dirp)) != NULL)
|
|
|
|
|
{
|
|
|
|
|
if(entry->d_name[0] == '.')
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
ffStrbufSubstrBefore(&pciDir, pciBaseDirLength);
|
|
|
|
|
ffStrbufAppendS(&pciDir, entry->d_name);
|
|
|
|
|
const uint32_t pciDevDirLength = pciDir.length;
|
|
|
|
|
|
|
|
|
|
ffStrbufAppendS(&pciDir, "/modalias");
|
|
|
|
|
if (!ffReadFileBuffer(pciDir.chars, &buffer))
|
|
|
|
|
continue;
|
|
|
|
|
ffStrbufSubstrBefore(&pciDir, pciDevDirLength);
|
|
|
|
|
assert(ffStrbufStartsWithS(&buffer, "pci:"));
|
|
|
|
|
|
2024-05-19 19:34:48 +08:00
|
|
|
detectPci(options, gpus, &buffer, &pciDir, NULL);
|
2024-04-18 21:00:47 +08:00
|
|
|
ffStrbufSubstrBefore(&pciDir, pciBaseDirLength);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
|
2022-09-05 17:42:42 +02:00
|
|
|
{
|
2024-08-08 18:53:56 +08:00
|
|
|
#ifdef FF_HAVE_DIRECTX_HEADERS
|
|
|
|
|
const char* ffGPUDetectByDirectX(const FFGPUOptions* options, FFlist* gpus);
|
|
|
|
|
if (ffGPUDetectByDirectX(options, gpus) == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
#endif
|
|
|
|
|
|
2024-05-20 16:45:23 +08:00
|
|
|
if (options->detectionMethod == FF_GPU_DETECTION_METHOD_AUTO)
|
|
|
|
|
{
|
|
|
|
|
if (drmDetectGPUs(options, gpus) == NULL && gpus->length > 0)
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2024-04-18 21:00:47 +08:00
|
|
|
return pciDetectGPUs(options, gpus);
|
2022-09-05 17:42:42 +02:00
|
|
|
}
|