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};