Skip to content

Commit 40e33c6

Browse files
committed
GPU (FreeBSD): support detection by DRM [wip]
1 parent d203710 commit 40e33c6

File tree

2 files changed

+310
-39
lines changed

2 files changed

+310
-39
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR FreeB
6161
cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
6262
cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
6363
cmake_dependent_option(ENABLE_DRM "Enable libdrm" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
64-
cmake_dependent_option(ENABLE_DRM_AMDGPU "Enable libdrm_amdgpu" ON "LINUX" OFF)
64+
cmake_dependent_option(ENABLE_DRM_AMDGPU "Enable libdrm_amdgpu" ON "LINUX OR FreeBSD" OFF)
6565
cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
6666
cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
6767
cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR Haiku" OFF)

src/detection/gpu/gpu_bsd.c

Lines changed: 309 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "gpu_driver_specific.h"
22

33
#include "common/io/io.h"
4+
#include "util/mallocHelper.h"
45

56
#include <sys/pciio.h>
67
#include <fcntl.h>
@@ -10,7 +11,285 @@
1011
#include <bus/pci/pcireg.h> // DragonFly
1112
#endif
1213

13-
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
14+
#include "common/library.h"
15+
#include "util/stringUtils.h"
16+
#include <xf86drm.h>
17+
#include <i915_drm.h>
18+
19+
#ifdef FF_HAVE_DRM_AMDGPU
20+
#include <amdgpu.h>
21+
#include <amdgpu_drm.h>
22+
#include <fcntl.h>
23+
#endif
24+
25+
static void fillGPUTypeGeneric(FFGPUResult* gpu)
26+
{
27+
if (gpu->type == FF_GPU_TYPE_UNKNOWN)
28+
{
29+
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA)
30+
{
31+
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "GeForce") ||
32+
ffStrbufStartsWithIgnCaseS(&gpu->name, "Quadro") ||
33+
ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla"))
34+
gpu->type = FF_GPU_TYPE_DISCRETE;
35+
}
36+
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS)
37+
{
38+
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT "))
39+
gpu->type = FF_GPU_TYPE_DISCRETE;
40+
}
41+
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
42+
{
43+
// 0000:00:02.0 is reserved for Intel integrated graphics
44+
gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
45+
}
46+
}
47+
}
48+
49+
#if FF_HAVE_DRM
50+
static const char* drmDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu, const char* renderPath)
51+
{
52+
#if FF_HAVE_DRM_AMDGPU
53+
FF_LIBRARY_LOAD(libdrm, "dlopen libdrm_amdgpu" FF_LIBRARY_EXTENSION " failed", "libdrm_amdgpu" FF_LIBRARY_EXTENSION, 1)
54+
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_device_initialize)
55+
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_get_marketing_name)
56+
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_gpu_info)
57+
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_sensor_info)
58+
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_heap_info)
59+
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_device_deinitialize)
60+
61+
FF_AUTO_CLOSE_FD int fd = open(renderPath, O_RDONLY);
62+
if (fd < 0) return "Failed to open DRM device";
63+
64+
amdgpu_device_handle handle;
65+
uint32_t majorVersion, minorVersion;
66+
if (ffamdgpu_device_initialize(fd, &majorVersion, &minorVersion, &handle) < 0)
67+
return "Failed to initialize AMDGPU device";
68+
69+
ffStrbufAppendF(&gpu->driver, " %u.%u", (unsigned) majorVersion, (unsigned) minorVersion);
70+
71+
uint32_t value;
72+
73+
if (options->temp)
74+
{
75+
if (ffamdgpu_query_sensor_info(handle, AMDGPU_INFO_SENSOR_GPU_TEMP, sizeof(value), &value) >= 0)
76+
gpu->temperature = value / 1000.;
77+
}
78+
79+
ffStrbufSetS(&gpu->name, ffamdgpu_get_marketing_name(handle));
80+
81+
struct amdgpu_gpu_info gpuInfo;
82+
if (ffamdgpu_query_gpu_info(handle, &gpuInfo) >= 0)
83+
{
84+
gpu->coreCount = (int32_t) gpuInfo.cu_active_number;
85+
gpu->frequency = (uint32_t) (gpuInfo.max_engine_clk / 1000u);
86+
gpu->index = FF_GPU_INDEX_UNSET;
87+
gpu->type = gpuInfo.ids_flags & AMDGPU_IDS_FLAGS_FUSION ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
88+
#define FF_VRAM_CASE(name, value) case value /* AMDGPU_VRAM_TYPE_ ## name */: ffStrbufSetStatic(&gpu->memoryType, #name); break
89+
switch (gpuInfo.vram_type)
90+
{
91+
FF_VRAM_CASE(UNKNOWN, 0);
92+
FF_VRAM_CASE(GDDR1, 1);
93+
FF_VRAM_CASE(DDR2, 2);
94+
FF_VRAM_CASE(GDDR3, 3);
95+
FF_VRAM_CASE(GDDR4, 4);
96+
FF_VRAM_CASE(GDDR5, 5);
97+
FF_VRAM_CASE(HBM, 6);
98+
FF_VRAM_CASE(DDR3, 7);
99+
FF_VRAM_CASE(DDR4, 8);
100+
FF_VRAM_CASE(GDDR6, 9);
101+
FF_VRAM_CASE(DDR5, 10);
102+
FF_VRAM_CASE(LPDDR4, 11);
103+
FF_VRAM_CASE(LPDDR5, 12);
104+
default:
105+
ffStrbufAppendF(&gpu->memoryType, "Unknown (%u)", gpuInfo.vram_type);
106+
break;
107+
}
108+
109+
struct amdgpu_heap_info heapInfo;
110+
if (ffamdgpu_query_heap_info(handle, AMDGPU_GEM_DOMAIN_VRAM, 0, &heapInfo) >= 0)
111+
{
112+
if (gpu->type == FF_GPU_TYPE_DISCRETE)
113+
{
114+
gpu->dedicated.total = heapInfo.heap_size;
115+
gpu->dedicated.used = heapInfo.heap_usage;
116+
}
117+
else
118+
{
119+
gpu->shared.total = heapInfo.heap_size;
120+
gpu->shared.used = heapInfo.heap_usage;
121+
}
122+
}
123+
}
124+
125+
if (ffamdgpu_query_sensor_info(handle, AMDGPU_INFO_SENSOR_GPU_LOAD, sizeof(value), &value) >= 0)
126+
gpu->coreUsage = value;
127+
128+
ffamdgpu_device_deinitialize(handle);
129+
130+
return NULL;
131+
#else
132+
FF_UNUSED(options, gpu, drmKey, buffer);
133+
return "Fastfetch is compiled without libdrm support";
134+
#endif
135+
}
136+
137+
static const char* drmDetectIntelSpecific(FFGPUResult* gpu, int fd)
138+
{
139+
{
140+
int value;
141+
drm_i915_getparam_t getparam = { .param = I915_PARAM_EU_TOTAL, .value = &value };
142+
if (ioctl(fd, DRM_IOCTL_I915_GETPARAM, &getparam) >= 0)
143+
gpu->coreCount = value;
144+
}
145+
{
146+
struct drm_i915_query_item queryItem = {
147+
.query_id = DRM_I915_QUERY_MEMORY_REGIONS,
148+
};
149+
struct drm_i915_query query = {
150+
.items_ptr = (uintptr_t) &queryItem,
151+
.num_items = 1,
152+
};
153+
if (ioctl(fd, DRM_IOCTL_I915_QUERY, &query) >= 0 )
154+
{
155+
FF_AUTO_FREE uint8_t* buffer = calloc(1, (size_t) queryItem.length);
156+
queryItem.data_ptr = (uintptr_t) buffer;
157+
if (ioctl(fd, DRM_IOCTL_I915_QUERY, &query) >= 0)
158+
{
159+
gpu->dedicated.total = gpu->shared.total = gpu->dedicated.used = gpu->shared.used = 0;
160+
struct drm_i915_query_memory_regions* regionInfo = (void*) buffer;
161+
for (uint32_t i = 0; i < regionInfo->num_regions; i++)
162+
{
163+
struct drm_i915_memory_region_info* region = regionInfo->regions + i;
164+
switch (region->region.memory_class)
165+
{
166+
case I915_MEMORY_CLASS_SYSTEM:
167+
gpu->shared.total += region->probed_size;
168+
gpu->shared.used += region->probed_size - region->unallocated_size;
169+
break;
170+
case I915_MEMORY_CLASS_DEVICE:
171+
gpu->dedicated.total += region->probed_size;
172+
gpu->dedicated.used += region->probed_size - region->unallocated_size;
173+
break;
174+
}
175+
}
176+
}
177+
}
178+
}
179+
return NULL;
180+
}
181+
182+
static const char* detectByDrm(const FFGPUOptions* options, FFlist* gpus)
183+
{
184+
FF_LIBRARY_LOAD(libdrm, "dlopen libdrm" FF_LIBRARY_EXTENSION " failed", "libdrm" FF_LIBRARY_EXTENSION, 2)
185+
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmGetDevices)
186+
187+
drmDevicePtr devices[64];
188+
int nDevices = ffdrmGetDevices(devices, ARRAY_SIZE(devices));
189+
190+
for (int iDev = 0; iDev < nDevices; ++iDev)
191+
{
192+
drmDevice* dev = devices[iDev];
193+
194+
if (!(dev->available_nodes & (1 << DRM_NODE_PRIMARY)))
195+
continue;
196+
197+
const char* path = dev->nodes[DRM_NODE_PRIMARY];
198+
199+
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
200+
ffStrbufInit(&gpu->vendor);
201+
ffStrbufInit(&gpu->name);
202+
ffStrbufInit(&gpu->driver);
203+
ffStrbufInitS(&gpu->platformApi, path);
204+
ffStrbufInit(&gpu->memoryType);
205+
gpu->index = FF_GPU_INDEX_UNSET;
206+
gpu->temperature = FF_GPU_TEMP_UNSET;
207+
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
208+
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
209+
gpu->type = FF_GPU_TYPE_UNKNOWN;
210+
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
211+
gpu->deviceId = 0;
212+
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
213+
214+
switch (dev->bustype)
215+
{
216+
case DRM_BUS_PCI:
217+
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(dev->deviceinfo.pci->vendor_id));
218+
gpu->deviceId = (dev->businfo.pci->domain * 100000ull) + (dev->businfo.pci->bus * 1000ull) + (dev->businfo.pci->dev * 10ull) + dev->businfo.pci->func;
219+
break;
220+
case DRM_BUS_HOST1X:
221+
ffStrbufSetS(&gpu->name, dev->deviceinfo.host1x->compatible[0]);
222+
gpu->type = FF_GPU_TYPE_INTEGRATED;
223+
break;
224+
case DRM_BUS_PLATFORM:
225+
ffStrbufSetS(&gpu->name, dev->deviceinfo.platform->compatible[0]);
226+
gpu->type = FF_GPU_TYPE_INTEGRATED;
227+
break;
228+
case DRM_BUS_USB:
229+
ffStrbufSetF(&gpu->name, "USB Device (%u-%u)", dev->deviceinfo.usb->vendor, dev->deviceinfo.usb->product);
230+
gpu->type = FF_GPU_TYPE_DISCRETE;
231+
break;
232+
}
233+
234+
FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY);
235+
if (fd < 0) continue;
236+
237+
char driverName[64];
238+
char driverDesc[64];
239+
struct drm_version ver = {
240+
.name = driverName,
241+
.name_len = ARRAY_SIZE(driverName),
242+
.desc = driverDesc,
243+
.desc_len = ARRAY_SIZE(driverDesc),
244+
};
245+
if (ioctl(fd, DRM_IOCTL_VERSION, &ver) == 0)
246+
ffStrbufSetF(&gpu->driver, "%*s %d.%d.%d", (int) ver.name_len, ver.name, ver.version_major, ver.version_minor, ver.version_patchlevel);
247+
248+
if (dev->bustype != DRM_BUS_PCI)
249+
continue;
250+
251+
if (ffStrEquals(ver.name, "i915"))
252+
drmDetectIntelSpecific(gpu, fd);
253+
else if (ffStrEquals(ver.name, "amdgpu"))
254+
drmDetectAmdSpecific(options, gpu, dev->nodes[DRM_NODE_RENDER]);
255+
else if (ffStrEquals(ver.name, "nvidia-drm") && (options->temp || options->driverSpecific))
256+
{
257+
ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) {
258+
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
259+
.pciBusId = {
260+
.domain = (uint32_t) dev->businfo.pci->domain,
261+
.bus = dev->businfo.pci->bus,
262+
.device = dev->businfo.pci->dev,
263+
.func = dev->businfo.pci->func,
264+
},
265+
}, (FFGpuDriverResult) {
266+
.index = &gpu->index,
267+
.temp = options->temp ? &gpu->temperature : NULL,
268+
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
269+
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
270+
.type = &gpu->type,
271+
.frequency = &gpu->frequency,
272+
.coreUsage = &gpu->coreUsage,
273+
.name = &gpu->name,
274+
}, "libnvidia-ml.so");
275+
}
276+
277+
if (gpu->name.length == 0)
278+
{
279+
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
280+
ffGPUQueryAmdGpuName(dev->deviceinfo.pci->device_id, dev->deviceinfo.pci->revision_id, gpu);
281+
if (gpu->name.length == 0)
282+
ffGPUFillVendorAndName(0, dev->deviceinfo.pci->vendor_id, dev->deviceinfo.pci->device_id, gpu);
283+
}
284+
285+
fillGPUTypeGeneric(gpu);
286+
}
287+
288+
return NULL;
289+
}
290+
#endif
291+
292+
static const char* detectByPci(const FFGPUOptions* options, FFlist* gpus)
14293
{
15294
FF_AUTO_CLOSE_FD int fd = open("/dev/pci", O_RDONLY, 0);
16295
if (fd < 0)
@@ -57,23 +336,23 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
57336
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific))
58337
{
59338
ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) {
60-
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
61-
.pciBusId = {
62-
.domain = (uint32_t) pc->pc_sel.pc_domain,
63-
.bus = pc->pc_sel.pc_bus,
64-
.device = pc->pc_sel.pc_dev,
65-
.func = pc->pc_sel.pc_func,
66-
},
67-
}, (FFGpuDriverResult) {
68-
.index = &gpu->index,
69-
.temp = options->temp ? &gpu->temperature : NULL,
70-
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
71-
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
72-
.type = &gpu->type,
73-
.frequency = &gpu->frequency,
74-
.coreUsage = &gpu->coreUsage,
75-
.name = &gpu->name,
76-
}, "libnvidia-ml.so");
339+
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
340+
.pciBusId = {
341+
.domain = (uint32_t) pc->pc_sel.pc_domain,
342+
.bus = pc->pc_sel.pc_bus,
343+
.device = pc->pc_sel.pc_dev,
344+
.func = pc->pc_sel.pc_func,
345+
},
346+
}, (FFGpuDriverResult) {
347+
.index = &gpu->index,
348+
.temp = options->temp ? &gpu->temperature : NULL,
349+
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
350+
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
351+
.type = &gpu->type,
352+
.frequency = &gpu->frequency,
353+
.coreUsage = &gpu->coreUsage,
354+
.name = &gpu->name,
355+
}, "libnvidia-ml.so");
77356
}
78357

79358
if (gpu->name.length == 0)
@@ -84,27 +363,19 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
84363
ffGPUFillVendorAndName(pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu);
85364
}
86365

87-
if (gpu->type == FF_GPU_TYPE_UNKNOWN)
88-
{
89-
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA)
90-
{
91-
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "GeForce") ||
92-
ffStrbufStartsWithIgnCaseS(&gpu->name, "Quadro") ||
93-
ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla"))
94-
gpu->type = FF_GPU_TYPE_DISCRETE;
95-
}
96-
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS)
97-
{
98-
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT "))
99-
gpu->type = FF_GPU_TYPE_DISCRETE;
100-
}
101-
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
102-
{
103-
// 0000:00:02.0 is reserved for Intel integrated graphics
104-
gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
105-
}
106-
}
366+
fillGPUTypeGeneric(gpu);
107367
}
108368

109369
return NULL;
110370
}
371+
372+
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
373+
{
374+
if (options->detectionMethod == FF_GPU_DETECTION_METHOD_AUTO)
375+
{
376+
detectByDrm(options, gpus);
377+
if (gpus->length > 0) return NULL;
378+
}
379+
380+
return detectByPci(options, gpus);
381+
}

0 commit comments

Comments
 (0)