master ohmu/fastfetch-openbsd / src / modules / gpu / gpu.c
ohmu  ·  2026-10-15
  1#include "common/percent.h"
  2#include "common/printing.h"
  3#include "common/jsonconfig.h"
  4#include "common/temps.h"
  5#include "common/size.h"
  6#include "common/frequency.h"
  7#include "common/strutil.h"
  8#include "detection/host/host.h"
  9#include "detection/gpu/gpu.h"
 10#include "modules/gpu/gpu.h"
 11
 12#include <stdlib.h>
 13
 14// `hideType` is a filter, and FF_GPU_TYPE_NONE means "hide nothing" -- no detected GPU ever has
 15// that type. Both the text and the JSON path must apply it, or the two disagree about which GPUs
 16// exist.
 17static bool gpuIsHidden(const FFGPUOptions* options, const FFGPUResult* gpu) {
 18    return options->hideType != FF_GPU_TYPE_NONE && gpu->type == options->hideType;
 19}
 20
 21static void selectGPUs(const FFGPUOptions* options, const FFlist* gpus, FFlist* selectedGPUs) {
 22    FF_LIST_FOR_EACH (FFGPUResult, gpu, *gpus) {
 23        if (!gpuIsHidden(options, gpu)) {
 24            *FF_LIST_ADD(const FFGPUResult*, *selectedGPUs) = gpu;
 25        }
 26    }
 27}
 28
 29static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResult* gpu) {
 30    const char* type;
 31    switch (gpu->type) {
 32        case FF_GPU_TYPE_INTEGRATED:
 33            type = "Integrated";
 34            break;
 35        case FF_GPU_TYPE_DISCRETE:
 36            type = "Discrete";
 37            break;
 38        default:
 39            type = "Unknown";
 40            break;
 41    }
 42
 43    FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type;
 44
 45    if (options->moduleArgs.outputFormat.length == 0) {
 46        ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(GPU), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
 47
 48        FF_STRBUF_AUTO_DESTROY output = ffStrbufCreate();
 49
 50        if (gpu->vendor.length > 0 && !ffStrbufStartsWithIgnCase(&gpu->name, &gpu->vendor)) {
 51            ffStrbufAppend(&output, &gpu->vendor);
 52            ffStrbufAppendC(&output, ' ');
 53        }
 54
 55        ffStrbufAppend(&output, &gpu->name);
 56
 57        if (gpu->coreCount != FF_GPU_CORE_COUNT_UNSET) {
 58            ffStrbufAppendF(&output, " (%d)", gpu->coreCount);
 59        }
 60
 61        if (gpu->frequency > 0) {
 62            ffStrbufAppendS(&output, " @ ");
 63            ffFreqAppendNum(gpu->frequency, &output);
 64        }
 65
 66        if (gpu->temperature != FF_GPU_TEMP_UNSET) {
 67            ffStrbufAppendS(&output, " - ");
 68            ffTempsAppendNum(gpu->temperature, &output, options->tempConfig, &options->moduleArgs);
 69        }
 70
 71        if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET && gpu->dedicated.total != 0) {
 72            ffStrbufAppendS(&output, " (");
 73
 74            if (!(percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) {
 75                if (gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET) {
 76                    ffSizeAppendNum(gpu->dedicated.used, &output);
 77                    ffStrbufAppendS(&output, " / ");
 78                }
 79                ffSizeAppendNum(gpu->dedicated.total, &output);
 80            }
 81            if (gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET) {
 82                double percent = (double) gpu->dedicated.used / (double) gpu->dedicated.total * 100.0;
 83                if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) {
 84                    ffStrbufAppendS(&output, ", ");
 85                    ffPercentAppendNum(&output, percent, options->percent, false, &options->moduleArgs);
 86                }
 87                if (percentType & FF_PERCENTAGE_TYPE_BAR_BIT) {
 88                    ffStrbufAppendS(&output, " ");
 89                    ffPercentAppendBar(&output, percent, options->percent, &options->moduleArgs);
 90                }
 91            }
 92            ffStrbufAppendC(&output, ')');
 93        }
 94
 95        if (gpu->type != FF_GPU_TYPE_UNKNOWN) {
 96            ffStrbufAppendF(&output, " [%s]", type);
 97        }
 98
 99        ffStrbufPutTo(&output, stdout);
100    } else {
101        FF_STRBUF_AUTO_DESTROY tempStr = ffStrbufCreate();
102        ffTempsAppendNum(gpu->temperature, &tempStr, options->tempConfig, &options->moduleArgs);
103        FF_STRBUF_AUTO_DESTROY dTotal = ffStrbufCreate();
104        FF_STRBUF_AUTO_DESTROY dUsed = ffStrbufCreate();
105        FF_STRBUF_AUTO_DESTROY dPercentNum = ffStrbufCreate();
106        FF_STRBUF_AUTO_DESTROY dPercentBar = ffStrbufCreate();
107        if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET) {
108            ffSizeAppendNum(gpu->dedicated.total, &dTotal);
109        }
110        if (gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET) {
111            ffSizeAppendNum(gpu->dedicated.used, &dUsed);
112        }
113        if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET && gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET) {
114            double percent = (double) gpu->dedicated.used / (double) gpu->dedicated.total * 100.0;
115            if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) {
116                ffPercentAppendNum(&dPercentNum, percent, options->percent, false, &options->moduleArgs);
117            }
118            if (percentType & FF_PERCENTAGE_TYPE_BAR_BIT) {
119                ffPercentAppendBar(&dPercentBar, percent, options->percent, &options->moduleArgs);
120            }
121        }
122
123        FF_STRBUF_AUTO_DESTROY sTotal = ffStrbufCreate();
124        FF_STRBUF_AUTO_DESTROY sUsed = ffStrbufCreate();
125        FF_STRBUF_AUTO_DESTROY sPercentNum = ffStrbufCreate();
126        FF_STRBUF_AUTO_DESTROY sPercentBar = ffStrbufCreate();
127        if (gpu->shared.total != FF_GPU_VMEM_SIZE_UNSET) {
128            ffSizeAppendNum(gpu->shared.total, &sTotal);
129        }
130        if (gpu->shared.used != FF_GPU_VMEM_SIZE_UNSET) {
131            ffSizeAppendNum(gpu->shared.used, &sUsed);
132        }
133        if (gpu->shared.total != FF_GPU_VMEM_SIZE_UNSET && gpu->shared.used != FF_GPU_VMEM_SIZE_UNSET) {
134            double percent = (double) gpu->shared.used / (double) gpu->shared.total * 100.0;
135            if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) {
136                ffPercentAppendNum(&sPercentNum, percent, options->percent, false, &options->moduleArgs);
137            }
138            if (percentType & FF_PERCENTAGE_TYPE_BAR_BIT) {
139                ffPercentAppendBar(&sPercentBar, percent, options->percent, &options->moduleArgs);
140            }
141        }
142
143        FF_STRBUF_AUTO_DESTROY frequency = ffStrbufCreate();
144        ffFreqAppendNum(gpu->frequency, &frequency);
145
146        FF_STRBUF_AUTO_DESTROY coreUsageNum = ffStrbufCreate();
147        FF_STRBUF_AUTO_DESTROY coreUsageBar = ffStrbufCreate();
148        if (gpu->coreUsage != FF_GPU_CORE_USAGE_UNSET) {
149            if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) {
150                ffPercentAppendNum(&coreUsageNum, gpu->coreUsage, options->percent, false, &options->moduleArgs);
151            }
152            if (percentType & FF_PERCENTAGE_TYPE_BAR_BIT) {
153                ffPercentAppendBar(&coreUsageBar, gpu->coreUsage, options->percent, &options->moduleArgs);
154            }
155        }
156
157        char maxSpeed[32] = "", currSpeed[32] = "";
158        if (gpu->pcieSpeed != FF_GPU_PCIE_SPEED_UNSET) {
159            snprintf(maxSpeed, sizeof(maxSpeed), "%d x%d", gpu->psMax.gen, gpu->psMax.lanes);
160            snprintf(currSpeed, sizeof(currSpeed), "%d x%d", gpu->psCurr.gen, gpu->psCurr.lanes);
161        }
162
163        FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(GPU), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) {
164                                                                                                            FF_ARG(gpu->vendor, "vendor"),
165                                                                                                            FF_ARG(gpu->name, "name"),
166                                                                                                            FF_ARG(gpu->driver, "driver"),
167                                                                                                            FF_ARG(tempStr, "temperature"),
168                                                                                                            FF_ARG(gpu->coreCount, "core-count"),
169                                                                                                            FF_ARG(type, "type"),
170                                                                                                            FF_ARG(dTotal, "dedicated-total"),
171                                                                                                            FF_ARG(dUsed, "dedicated-used"),
172                                                                                                            FF_ARG(sTotal, "shared-total"),
173                                                                                                            FF_ARG(sUsed, "shared-used"),
174                                                                                                            FF_ARG(gpu->platformApi, "platform-api"),
175                                                                                                            FF_ARG(frequency, "frequency"),
176                                                                                                            FF_ARG(index, "index"),
177                                                                                                            FF_ARG(dPercentNum, "dedicated-percentage-num"),
178                                                                                                            FF_ARG(dPercentBar, "dedicated-percentage-bar"),
179                                                                                                            FF_ARG(sPercentNum, "shared-percentage-num"),
180                                                                                                            FF_ARG(sPercentBar, "shared-percentage-bar"),
181                                                                                                            FF_ARG(coreUsageNum, "core-usage-num"),
182                                                                                                            FF_ARG(coreUsageBar, "core-usage-bar"),
183                                                                                                            FF_ARG(gpu->memoryType, "memory-type"),
184                                                                                                            FF_ARG(maxSpeed, "pcie-max-speed"),
185                                                                                                            FF_ARG(currSpeed, "pcie-curr-speed"),
186                                                                                                        }));
187    }
188}
189
190bool ffPrintGPU(FFGPUOptions* options) {
191    FF_LIST_AUTO_DESTROY gpus = ffListCreate();
192    const char* error = ffDetectGPU(options, &gpus);
193    if (error) {
194        ffPrintError(FF_MODULE_GET_DISPLAY_NAME(GPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
195        return false;
196    }
197
198    FF_LIST_AUTO_DESTROY selectedGPUs = ffListCreateA(sizeof(const FFGPUResult*), gpus.length);
199
200    selectGPUs(options, &gpus, &selectedGPUs);
201
202    uint32_t i = 0;
203    FF_LIST_FOR_EACH (const FFGPUResult*, pgpu, selectedGPUs) {
204        printGPUResult(options, selectedGPUs.length == 1 ? 0 : (uint8_t) (i + 1), *pgpu);
205        ++i;
206    }
207
208    FF_LIST_FOR_EACH (FFGPUResult, gpu, gpus) {
209        ffStrbufDestroy(&gpu->vendor);
210        ffStrbufDestroy(&gpu->name);
211        ffStrbufDestroy(&gpu->driver);
212        ffStrbufDestroy(&gpu->platformApi);
213        ffStrbufDestroy(&gpu->memoryType);
214    }
215
216    if (selectedGPUs.length == 0) {
217        ffPrintError(FF_MODULE_GET_DISPLAY_NAME(GPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, (gpus.length > 0 ? "GPUs found but all hidden by hideType option" : "No GPUs detected"));
218        return false;
219    }
220
221    return true;
222}
223
224void ffParseGPUJsonObject(FFGPUOptions* options, yyjson_val* module) {
225    yyjson_val *key, *val;
226    size_t idx, max;
227    yyjson_obj_foreach (module, idx, max, key, val) {
228        if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) {
229            continue;
230        }
231
232        if (ffTempsParseJsonObject(key, val, &options->temp, &options->tempConfig)) {
233            continue;
234        }
235
236        if (unsafe_yyjson_equals_str(key, "driverSpecific")) {
237            options->driverSpecific = yyjson_get_bool(val);
238            continue;
239        }
240
241        if (unsafe_yyjson_equals_str(key, "detectionMethod")) {
242            int value;
243            const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]){
244                                                                       { "auto", FF_GPU_DETECTION_METHOD_AUTO },
245                                                                       { "pci", FF_GPU_DETECTION_METHOD_PCI },
246                                                                       { "vulkan", FF_GPU_DETECTION_METHOD_VULKAN },
247                                                                       { "opencl", FF_GPU_DETECTION_METHOD_OPENCL },
248                                                                       { "egl-ext", FF_GPU_DETECTION_METHOD_EGL_EXT },
249                                                                       { "opengl", FF_GPU_DETECTION_METHOD_OPENGL },
250                                                                       {},
251                                                                   });
252            if (error) {
253                ffPrintError(FF_MODULE_GET_DISPLAY_NAME(GPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error);
254            } else {
255                options->detectionMethod = (FFGPUDetectionMethod) value;
256            }
257            continue;
258        }
259
260        if (unsafe_yyjson_equals_str(key, "hideType")) {
261            if (yyjson_is_null(val)) {
262                options->hideType = FF_GPU_TYPE_NONE;
263            } else {
264                int value;
265                const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]){
266                                                                           { "none", FF_GPU_TYPE_NONE },
267                                                                           { "unknown", FF_GPU_TYPE_UNKNOWN },
268                                                                           { "integrated", FF_GPU_TYPE_INTEGRATED },
269                                                                           { "discrete", FF_GPU_TYPE_DISCRETE },
270                                                                           {},
271                                                                       });
272                if (error) {
273                    ffPrintError(FF_MODULE_GET_DISPLAY_NAME(GPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error);
274                } else {
275                    options->hideType = (FFGPUType) value;
276                }
277            }
278            continue;
279        }
280
281        if (ffPercentParseJsonObject(key, val, &options->percent)) {
282            continue;
283        }
284
285        ffPrintError(FF_MODULE_GET_DISPLAY_NAME(GPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
286    }
287}
288
289[[gnu::cold]]
290void ffGenerateGPUJsonConfig(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) {
291    ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs);
292
293    yyjson_mut_obj_add_bool(doc, module, "driverSpecific", options->driverSpecific);
294
295    switch (options->detectionMethod) {
296        case FF_GPU_DETECTION_METHOD_AUTO:
297            yyjson_mut_obj_add_str(doc, module, "detectionMethod", "auto");
298            break;
299        case FF_GPU_DETECTION_METHOD_PCI:
300            yyjson_mut_obj_add_str(doc, module, "detectionMethod", "pci");
301            break;
302        case FF_GPU_DETECTION_METHOD_VULKAN:
303            yyjson_mut_obj_add_str(doc, module, "detectionMethod", "vulkan");
304            break;
305        case FF_GPU_DETECTION_METHOD_OPENCL:
306            yyjson_mut_obj_add_str(doc, module, "detectionMethod", "opencl");
307            break;
308        case FF_GPU_DETECTION_METHOD_EGL_EXT:
309            yyjson_mut_obj_add_str(doc, module, "detectionMethod", "egl-ext");
310            break;
311        case FF_GPU_DETECTION_METHOD_OPENGL:
312            yyjson_mut_obj_add_str(doc, module, "detectionMethod", "opengl");
313            break;
314    }
315
316    ffTempsGenerateJsonConfig(doc, module, options->temp, options->tempConfig);
317
318    switch (options->hideType) {
319        case FF_GPU_TYPE_NONE:
320            yyjson_mut_obj_add_str(doc, module, "hideType", "none");
321            break;
322        case FF_GPU_TYPE_UNKNOWN:
323            yyjson_mut_obj_add_str(doc, module, "hideType", "unknown");
324            break;
325        case FF_GPU_TYPE_INTEGRATED:
326            yyjson_mut_obj_add_str(doc, module, "hideType", "integrated");
327            break;
328        case FF_GPU_TYPE_DISCRETE:
329            yyjson_mut_obj_add_str(doc, module, "hideType", "discrete");
330            break;
331    }
332
333    ffPercentGenerateJsonConfig(doc, module, options->percent);
334}
335
336bool ffGenerateGPUJsonResult(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) {
337    FF_LIST_AUTO_DESTROY gpus = ffListCreate();
338    const char* error = ffDetectGPU(options, &gpus);
339    if (error) {
340        yyjson_mut_obj_add_str(doc, module, "error", error);
341        return false;
342    }
343
344    FF_LIST_AUTO_DESTROY selectedGPUs = ffListCreateA(sizeof(const FFGPUResult*), gpus.length);
345
346    selectGPUs(options, &gpus, &selectedGPUs);
347
348    yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
349    FF_LIST_FOR_EACH (const FFGPUResult*, pgpu, selectedGPUs) {
350        const FFGPUResult* gpu = *pgpu;
351        yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
352
353        if (gpu->index != FF_GPU_INDEX_UNSET) {
354            yyjson_mut_obj_add_uint(doc, obj, "index", gpu->index);
355        } else {
356            yyjson_mut_obj_add_null(doc, obj, "index");
357        }
358
359        if (gpu->coreCount != FF_GPU_CORE_COUNT_UNSET) {
360            yyjson_mut_obj_add_int(doc, obj, "coreCount", gpu->coreCount);
361        } else {
362            yyjson_mut_obj_add_null(doc, obj, "coreCount");
363        }
364
365        if (gpu->coreUsage != FF_GPU_CORE_USAGE_UNSET) {
366            yyjson_mut_obj_add_real(doc, obj, "coreUsage", gpu->coreUsage);
367        } else {
368            yyjson_mut_obj_add_null(doc, obj, "coreUsage");
369        }
370
371        yyjson_mut_val* memoryObj = yyjson_mut_obj_add_obj(doc, obj, "memory");
372
373        yyjson_mut_val* dedicatedObj = yyjson_mut_obj_add_obj(doc, memoryObj, "dedicated");
374        if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET) {
375            yyjson_mut_obj_add_uint(doc, dedicatedObj, "total", gpu->dedicated.total);
376        } else {
377            yyjson_mut_obj_add_null(doc, dedicatedObj, "total");
378        }
379
380        if (gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET) {
381            yyjson_mut_obj_add_uint(doc, dedicatedObj, "used", gpu->dedicated.used);
382        } else {
383            yyjson_mut_obj_add_null(doc, dedicatedObj, "used");
384        }
385
386        yyjson_mut_val* sharedObj = yyjson_mut_obj_add_obj(doc, memoryObj, "shared");
387        if (gpu->shared.total != FF_GPU_VMEM_SIZE_UNSET) {
388            yyjson_mut_obj_add_uint(doc, sharedObj, "total", gpu->shared.total);
389        } else {
390            yyjson_mut_obj_add_null(doc, sharedObj, "total");
391        }
392        if (gpu->shared.used != FF_GPU_VMEM_SIZE_UNSET) {
393            yyjson_mut_obj_add_uint(doc, sharedObj, "used", gpu->shared.used);
394        } else {
395            yyjson_mut_obj_add_null(doc, sharedObj, "used");
396        }
397
398        if (gpu->memoryType.length) {
399            yyjson_mut_obj_add_strbuf(doc, memoryObj, "type", &gpu->memoryType);
400        } else {
401            yyjson_mut_obj_add_null(doc, memoryObj, "type");
402        }
403
404        yyjson_mut_obj_add_strbuf(doc, obj, "driver", &gpu->driver);
405        yyjson_mut_obj_add_strbuf(doc, obj, "name", &gpu->name);
406
407        if (gpu->temperature != FF_GPU_TEMP_UNSET) {
408            yyjson_mut_obj_add_real(doc, obj, "temperature", gpu->temperature);
409        } else {
410            yyjson_mut_obj_add_null(doc, obj, "temperature");
411        }
412
413        const char* type;
414        switch (gpu->type) {
415            case FF_GPU_TYPE_INTEGRATED:
416                type = "Integrated";
417                break;
418            case FF_GPU_TYPE_DISCRETE:
419                type = "Discrete";
420                break;
421            default:
422                type = nullptr;
423                break;
424        }
425        if (type) {
426            yyjson_mut_obj_add_str(doc, obj, "type", type);
427        } else {
428            yyjson_mut_obj_add_null(doc, obj, "type");
429        }
430
431        yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &gpu->vendor);
432
433        yyjson_mut_obj_add_strbuf(doc, obj, "platformApi", &gpu->platformApi);
434
435        if (gpu->frequency != FF_GPU_FREQUENCY_UNSET) {
436            yyjson_mut_obj_add_uint(doc, obj, "frequency", gpu->frequency);
437        } else {
438            yyjson_mut_obj_add_null(doc, obj, "frequency");
439        }
440
441        yyjson_mut_obj_add_uint(doc, obj, "deviceId", gpu->deviceId);
442
443        if (gpu->pcieSpeed != FF_GPU_PCIE_SPEED_UNSET) {
444            yyjson_mut_val* pcieSpeed = yyjson_mut_obj_add_obj(doc, obj, "pcieSpeed");
445            yyjson_mut_val* maxSpeed = yyjson_mut_obj_add_obj(doc, pcieSpeed, "max");
446            yyjson_mut_obj_add_uint(doc, maxSpeed, "gen", gpu->psMax.gen);
447            yyjson_mut_obj_add_uint(doc, maxSpeed, "lanes", gpu->psMax.lanes);
448            yyjson_mut_val* currSpeed = yyjson_mut_obj_add_obj(doc, pcieSpeed, "current");
449            yyjson_mut_obj_add_uint(doc, currSpeed, "gen", gpu->psCurr.gen);
450            yyjson_mut_obj_add_uint(doc, currSpeed, "lanes", gpu->psCurr.lanes);
451        } else {
452            yyjson_mut_obj_add_null(doc, obj, "pcieSpeed");
453        }
454    }
455
456    FF_LIST_FOR_EACH (FFGPUResult, gpu, gpus) {
457        ffStrbufDestroy(&gpu->vendor);
458        ffStrbufDestroy(&gpu->name);
459        ffStrbufDestroy(&gpu->driver);
460        ffStrbufDestroy(&gpu->platformApi);
461        ffStrbufDestroy(&gpu->memoryType);
462    }
463
464    return true;
465}
466
467void ffInitGPUOptions(FFGPUOptions* options) {
468    ffOptionInitModuleArg(&options->moduleArgs, "󰾲");
469
470    options->driverSpecific = false;
471    options->detectionMethod =
472#if defined(__x86_64__) || defined(__i386__)
473        FF_GPU_DETECTION_METHOD_PCI
474#else
475        FF_GPU_DETECTION_METHOD_AUTO
476#endif
477        ;
478    options->temp = false;
479    options->hideType = FF_GPU_TYPE_NONE;
480    options->tempConfig = (FFColorRangeConfig){ 60, 80 };
481    options->percent = (FFPercentageModuleConfig){ 50, 80, 0 };
482}
483
484void ffDestroyGPUOptions(FFGPUOptions* options) {
485    ffOptionDestroyModuleArg(&options->moduleArgs);
486}
487
488FFModuleBaseInfo ffGPUModuleInfo = {
489    .name = "GPU",
490    .description = "Print GPU names, memory sizes, types, etc",
491    .displayName = {
492        .en = "GPU",
493        .ar = "معالج الرسوميات",
494        .cs = "GPU",
495        .de = "GPU",
496        .es = "GPU",
497        .fi = "Grafiikkasuoritin",
498        .fr = "GPU",
499        .gl = "GPU",
500        .he = "מעבד גרפי",
501        .id = "GPU",
502        .it = "GPU",
503        .ja = "GPU",
504        .ko = "GPU",
505        .pl = "GPU",
506        .pt = "GPU",
507        .ru = "Видеокарта",
508        .tr = "GPU",
509        .uk = "GPU",
510        .vi = "GPU",
511        .zh_CN = "显卡",
512        .zh_TW = "顯卡",
513    },
514    .initOptions = (void*) ffInitGPUOptions,
515    .destroyOptions = (void*) ffDestroyGPUOptions,
516    .parseJsonObject = (void*) ffParseGPUJsonObject,
517    .printModule = (void*) ffPrintGPU,
518    .generateJsonResult = (void*) ffGenerateGPUJsonResult,
519    .generateJsonConfig = (void*) ffGenerateGPUJsonConfig,
520    .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]){
521        { "GPU vendor", "vendor" },
522        { "GPU name", "name" },
523        { "GPU driver", "driver" },
524        { "GPU temperature", "temperature" },
525        { "GPU core count", "core-count" },
526        { "GPU type", "type" },
527        { "GPU total dedicated memory", "dedicated-total" },
528        { "GPU used dedicated memory", "dedicated-used" },
529        { "GPU total shared memory", "shared-total" },
530        { "GPU used shared memory", "shared-used" },
531        { "The platform API used when detecting the GPU", "platform-api" },
532        { "Current frequency in GHz", "frequency" },
533        { "GPU vendor specific index", "index" },
534        { "Dedicated memory usage percentage num", "dedicated-percentage-num" },
535        { "Dedicated memory usage percentage bar", "dedicated-percentage-bar" },
536        { "Shared memory usage percentage num", "shared-percentage-num" },
537        { "Shared memory usage percentage bar", "shared-percentage-bar" },
538        { "Core usage percentage num", "core-usage-num" },
539        { "Core usage percentage bar", "core-usage-bar" },
540        { "Memory type (Windows only)", "memory-type" },
541        { "PCIe maximum speed in gen and lanes", "pcie-max-speed" },
542        { "PCIe current speed in gen and lanes", "pcie-curr-speed" },
543    })),
544    .defaultOrder = 36,
545};