Files
fastfetch/src/modules/gpu/gpu.c
T

381 lines
13 KiB
C
Raw Normal View History

2024-01-20 11:28:38 +08:00
#include "common/percent.h"
2023-03-26 20:42:18 +08:00
#include "common/parsing.h"
#include "common/printing.h"
2023-06-10 15:01:54 +08:00
#include "common/jsonconfig.h"
2023-03-26 20:42:18 +08:00
#include "detection/host/host.h"
#include "detection/gpu/gpu.h"
#include "modules/gpu/gpu.h"
#include "util/stringUtils.h"
2023-03-26 20:42:18 +08:00
#include <stdlib.h>
#define FF_GPU_NUM_FORMAT_ARGS 12
2023-03-26 20:42:18 +08:00
static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResult* gpu)
2023-03-26 20:42:18 +08:00
{
2023-06-24 19:49:53 +08:00
const char* type;
switch (gpu->type)
{
case FF_GPU_TYPE_INTEGRATED: type = "Integrated"; break;
case FF_GPU_TYPE_DISCRETE: type = "Discrete"; break;
default: type = "Unknown"; break;
}
2023-03-26 20:42:18 +08:00
if(options->moduleArgs.outputFormat.length == 0)
{
ffPrintLogoAndKey(FF_GPU_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
2023-03-26 20:42:18 +08:00
FF_STRBUF_AUTO_DESTROY output = ffStrbufCreateA(gpu->vendor.length + 1 + gpu->name.length);
2023-03-26 20:42:18 +08:00
if(gpu->vendor.length > 0 && !ffStrbufStartsWith(&gpu->name, &gpu->vendor))
{
ffStrbufAppend(&output, &gpu->vendor);
ffStrbufAppendC(&output, ' ');
}
ffStrbufAppend(&output, &gpu->name);
if(gpu->coreCount != FF_GPU_CORE_COUNT_UNSET)
ffStrbufAppendF(&output, " (%d)", gpu->coreCount);
if(gpu->frequency == gpu->frequency && gpu->frequency > 0 /* Inactive? */)
ffStrbufAppendF(&output, " @ %.2f GHz", gpu->frequency);
2023-03-26 20:42:18 +08:00
if(gpu->temperature == gpu->temperature) //FF_GPU_TEMP_UNSET
{
ffStrbufAppendS(&output, " - ");
ffParseTemperature(gpu->temperature, &output);
}
2023-03-26 20:42:18 +08:00
if(gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET && gpu->dedicated.total != 0)
{
ffStrbufAppendS(&output, " (");
if(gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET)
{
2023-07-27 15:17:54 +08:00
ffParseSize(gpu->dedicated.used, &output);
2023-03-26 20:42:18 +08:00
ffStrbufAppendS(&output, " / ");
}
2023-07-27 15:17:54 +08:00
ffParseSize(gpu->dedicated.total, &output);
2023-03-26 20:42:18 +08:00
if(gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET)
{
ffStrbufAppendS(&output, ", ");
ffPercentAppendNum(&output, (double) gpu->dedicated.used / (double) gpu->dedicated.total * 100.0, options->percent, false);
2023-03-26 20:42:18 +08:00
}
ffStrbufAppendC(&output, ')');
}
2023-06-24 19:49:53 +08:00
if (gpu->type != FF_GPU_TYPE_UNKNOWN)
ffStrbufAppendF(&output, " [%s]", type);
2023-03-26 20:42:18 +08:00
ffStrbufPutTo(&output, stdout);
}
else
{
ffPrintFormat(FF_GPU_MODULE_NAME, index, &options->moduleArgs, FF_GPU_NUM_FORMAT_ARGS, (FFformatarg[]){
2023-03-26 20:42:18 +08:00
{FF_FORMAT_ARG_TYPE_STRBUF, &gpu->vendor},
{FF_FORMAT_ARG_TYPE_STRBUF, &gpu->name},
{FF_FORMAT_ARG_TYPE_STRBUF, &gpu->driver},
{FF_FORMAT_ARG_TYPE_DOUBLE, &gpu->temperature},
{FF_FORMAT_ARG_TYPE_INT, &gpu->coreCount},
{FF_FORMAT_ARG_TYPE_STRING, type},
2023-10-07 13:40:40 +08:00
{FF_FORMAT_ARG_TYPE_UINT64, &gpu->dedicated.total},
{FF_FORMAT_ARG_TYPE_UINT64, &gpu->dedicated.used},
{FF_FORMAT_ARG_TYPE_UINT64, &gpu->shared.total},
{FF_FORMAT_ARG_TYPE_UINT64, &gpu->shared.used},
{FF_FORMAT_ARG_TYPE_STRBUF, &gpu->platformApi},
{FF_FORMAT_ARG_TYPE_DOUBLE, &gpu->frequency},
2023-03-26 20:42:18 +08:00
});
}
}
void ffPrintGPU(FFGPUOptions* options)
2023-03-26 20:42:18 +08:00
{
2023-06-12 11:30:18 +08:00
FF_LIST_AUTO_DESTROY gpus = ffListCreate(sizeof (FFGPUResult));
const char* error = ffDetectGPU(options, &gpus);
2023-06-12 11:30:18 +08:00
if (error)
{
ffPrintError(FF_GPU_MODULE_NAME, 0, &options->moduleArgs, "%s", error);
2023-06-12 11:30:18 +08:00
return;
}
2023-03-26 20:42:18 +08:00
FF_LIST_AUTO_DESTROY selectedGPUs;
2023-06-12 11:30:18 +08:00
ffListInitA(&selectedGPUs, sizeof(const FFGPUResult*), gpus.length);
2023-03-26 20:42:18 +08:00
2023-06-12 11:30:18 +08:00
FF_LIST_FOR_EACH(FFGPUResult, gpu, gpus)
2023-03-26 20:42:18 +08:00
{
if(gpu->type == FF_GPU_TYPE_INTEGRATED && options->hideType == FF_GPU_TYPE_INTEGRATED)
continue;
if(gpu->type == FF_GPU_TYPE_DISCRETE && options->hideType == FF_GPU_TYPE_DISCRETE)
continue;
* (const FFGPUResult**) ffListAdd(&selectedGPUs) = gpu;
}
for(uint32_t i = 0; i < selectedGPUs.length; i++)
printGPUResult(options, selectedGPUs.length == 1 ? 0 : (uint8_t) (i + 1), * (const FFGPUResult**) ffListGet(&selectedGPUs, i));
2023-03-26 20:42:18 +08:00
if(selectedGPUs.length == 0)
ffPrintError(FF_GPU_MODULE_NAME, 0, &options->moduleArgs, "No GPUs found");
2023-06-12 11:30:18 +08:00
FF_LIST_FOR_EACH(FFGPUResult, gpu, gpus)
{
ffStrbufDestroy(&gpu->vendor);
ffStrbufDestroy(&gpu->name);
ffStrbufDestroy(&gpu->driver);
}
2023-03-26 20:42:18 +08:00
}
bool ffParseGPUCommandOptions(FFGPUOptions* options, const char* key, const char* value)
{
const char* subKey = ffOptionTestPrefix(key, FF_GPU_MODULE_NAME);
if (!subKey) return false;
if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs))
return true;
2023-12-20 14:59:27 +08:00
if (ffStrEqualsIgnCase(subKey, "driver-specific"))
2023-10-30 13:46:51 +08:00
{
2023-12-20 14:59:27 +08:00
options->driverSpecific = ffOptionParseBoolean(value);
2023-10-30 13:46:51 +08:00
return true;
}
if (ffStrEqualsIgnCase(subKey, "force-vulkan"))
2023-03-26 20:42:18 +08:00
{
options->forceVulkan = ffOptionParseBoolean(value);
return true;
}
if (ffStrEqualsIgnCase(subKey, "temp"))
2023-03-26 20:42:18 +08:00
{
options->temp = ffOptionParseBoolean(value);
return true;
}
if (ffStrEqualsIgnCase(subKey, "hide-type"))
2023-03-26 20:42:18 +08:00
{
options->hideType = (FFGPUType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) {
{ "none", FF_GPU_TYPE_UNKNOWN },
{ "integrated", FF_GPU_TYPE_INTEGRATED },
2023-03-26 20:42:18 +08:00
{ "discrete", FF_GPU_TYPE_DISCRETE },
{},
});
}
if (ffPercentParseCommandOptions(key, subKey, value, &options->percent))
return true;
2023-03-26 20:42:18 +08:00
return false;
}
2023-08-17 10:56:54 +08:00
void ffParseGPUJsonObject(FFGPUOptions* options, yyjson_val* module)
2023-03-26 20:42:18 +08:00
{
2023-08-17 16:09:41 +08:00
yyjson_val *key_, *val;
size_t idx, max;
yyjson_obj_foreach(module, idx, max, key_, val)
2023-03-26 20:42:18 +08:00
{
2023-08-17 16:09:41 +08:00
const char* key = yyjson_get_str(key_);
if(ffStrEqualsIgnCase(key, "type"))
continue;
2023-03-26 20:42:18 +08:00
2023-08-17 16:09:41 +08:00
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
continue;
2023-03-26 20:42:18 +08:00
2023-08-17 16:09:41 +08:00
if (ffStrEqualsIgnCase(key, "temp"))
{
options->temp = yyjson_get_bool(val);
continue;
}
2023-03-26 20:42:18 +08:00
2023-12-20 14:59:27 +08:00
if (ffStrEqualsIgnCase(key, "driverSpecific"))
2023-10-30 13:46:51 +08:00
{
2023-12-20 14:59:27 +08:00
options->driverSpecific = yyjson_get_bool(val);
2023-10-30 13:46:51 +08:00
continue;
}
2023-08-17 16:09:41 +08:00
if (ffStrEqualsIgnCase(key, "forceVulkan"))
{
options->forceVulkan = yyjson_get_bool(val);
continue;
}
2023-03-26 20:42:18 +08:00
2023-08-17 16:09:41 +08:00
if (ffStrEqualsIgnCase(key, "hideType"))
{
int value;
const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) {
{ "none", FF_GPU_TYPE_UNKNOWN },
{ "integrated", FF_GPU_TYPE_INTEGRATED },
2023-08-17 16:09:41 +08:00
{ "discrete", FF_GPU_TYPE_DISCRETE },
{},
});
if (error)
ffPrintError(FF_GPU_MODULE_NAME, 0, &options->moduleArgs, "Invalid %s value: %s", key, error);
else
options->hideType = (FFGPUType) value;
continue;
2023-03-26 20:42:18 +08:00
}
2023-08-17 16:09:41 +08:00
if (ffPercentParseJsonObject(key, val, &options->percent))
continue;
2023-08-17 16:09:41 +08:00
ffPrintError(FF_GPU_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key);
2023-03-26 20:42:18 +08:00
}
}
2023-09-05 15:49:22 +08:00
2023-10-24 14:41:29 +08:00
void ffGenerateGPUJsonConfig(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
{
__attribute__((__cleanup__(ffDestroyGPUOptions))) FFGPUOptions defaultOptions;
ffInitGPUOptions(&defaultOptions);
ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs);
2023-12-20 14:59:27 +08:00
if (options->driverSpecific != defaultOptions.driverSpecific)
yyjson_mut_obj_add_bool(doc, module, "driverSpecific", options->driverSpecific);
2023-10-30 13:46:51 +08:00
2023-10-24 14:41:29 +08:00
if (options->forceVulkan != defaultOptions.forceVulkan)
yyjson_mut_obj_add_bool(doc, module, "forceVulkan", options->forceVulkan);
if (options->temp != defaultOptions.temp)
yyjson_mut_obj_add_bool(doc, module, "temp", options->temp);
if (options->hideType != defaultOptions.hideType)
{
switch (options->hideType)
{
case FF_GPU_TYPE_UNKNOWN:
yyjson_mut_obj_add_str(doc, module, "hideType", "none");
break;
case FF_GPU_TYPE_INTEGRATED:
yyjson_mut_obj_add_str(doc, module, "hideType", "integrated");
2023-10-24 14:41:29 +08:00
break;
case FF_GPU_TYPE_DISCRETE:
yyjson_mut_obj_add_str(doc, module, "hideType", "discrete");
break;
}
}
ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent);
2023-10-24 14:41:29 +08:00
}
2023-10-23 10:14:22 +08:00
void ffGenerateGPUJsonResult(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
2023-09-05 15:49:22 +08:00
{
FF_LIST_AUTO_DESTROY gpus = ffListCreate(sizeof (FFGPUResult));
const char* error = ffDetectGPU(options, &gpus);
if (error)
{
yyjson_mut_obj_add_str(doc, module, "error", error);
return;
}
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
FF_LIST_FOR_EACH(FFGPUResult, gpu, gpus)
{
yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
if (gpu->coreCount != FF_GPU_CORE_COUNT_UNSET)
yyjson_mut_obj_add_int(doc, obj, "coreCount", gpu->coreCount);
else
yyjson_mut_obj_add_null(doc, obj, "coreCount");
2023-09-13 14:07:14 +08:00
yyjson_mut_val* memoryObj = yyjson_mut_obj_add_obj(doc, obj, "memory");
yyjson_mut_val* dedicatedObj = yyjson_mut_obj_add_obj(doc, memoryObj, "dedicated");
2023-09-05 15:49:22 +08:00
if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET)
yyjson_mut_obj_add_uint(doc, dedicatedObj, "total", gpu->dedicated.total);
else
yyjson_mut_obj_add_null(doc, dedicatedObj, "total");
if (gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET)
yyjson_mut_obj_add_uint(doc, dedicatedObj, "used", gpu->dedicated.used);
else
yyjson_mut_obj_add_null(doc, dedicatedObj, "used");
yyjson_mut_obj_add_strbuf(doc, obj, "driver", &gpu->driver);
yyjson_mut_obj_add_strbuf(doc, obj, "name", &gpu->name);
2023-09-13 14:07:14 +08:00
yyjson_mut_val* sharedObj = yyjson_mut_obj_add_obj(doc, memoryObj, "shared");
2023-09-05 15:49:22 +08:00
if (gpu->shared.total != FF_GPU_VMEM_SIZE_UNSET)
yyjson_mut_obj_add_uint(doc, sharedObj, "total", gpu->shared.total);
else
yyjson_mut_obj_add_null(doc, sharedObj, "total");
if (gpu->shared.used != FF_GPU_VMEM_SIZE_UNSET)
yyjson_mut_obj_add_uint(doc, sharedObj, "used", gpu->shared.used);
else
yyjson_mut_obj_add_null(doc, sharedObj, "used");
2023-10-28 13:12:04 +08:00
if(gpu->temperature == gpu->temperature) //FF_GPU_TEMP_UNSET
yyjson_mut_obj_add_real(doc, obj, "temperature", gpu->temperature);
else
yyjson_mut_obj_add_null(doc, obj, "temperature");
2023-09-05 15:49:22 +08:00
const char* type;
switch (gpu->type)
{
case FF_GPU_TYPE_INTEGRATED: type = "Integrated"; break;
case FF_GPU_TYPE_DISCRETE: type = "Discrete"; break;
default: type = "Unknown"; break;
}
yyjson_mut_obj_add_str(doc, obj, "type", type);
yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &gpu->vendor);
yyjson_mut_obj_add_strbuf(doc, obj, "platformApi", &gpu->platformApi);
if (gpu->frequency == FF_GPU_FREQUENCY_UNSET)
yyjson_mut_obj_add_null(doc, obj, "frequency");
else
yyjson_mut_obj_add_real(doc, obj, "frequency", gpu->frequency);
2023-09-05 15:49:22 +08:00
}
FF_LIST_FOR_EACH(FFGPUResult, gpu, gpus)
{
ffStrbufDestroy(&gpu->vendor);
ffStrbufDestroy(&gpu->name);
ffStrbufDestroy(&gpu->driver);
}
}
2023-10-07 13:40:40 +08:00
void ffPrintGPUHelpFormat(void)
{
ffPrintModuleFormatHelp(FF_GPU_MODULE_NAME, "{1} {2}", FF_GPU_NUM_FORMAT_ARGS, (const char* []) {
"GPU vendor",
"GPU name",
"GPU driver",
"GPU temperature",
"GPU core count",
"GPU type",
"GPU total dedicated memory",
"GPU used dedicated memory",
"GPU total shared memory",
"GPU used shared memory",
"The platform API that GPU supports",
"Current frequency in GHz",
2023-10-07 13:40:40 +08:00
});
}
2023-10-23 13:32:18 +08:00
void ffInitGPUOptions(FFGPUOptions* options)
{
ffOptionInitModuleBaseInfo(
&options->moduleInfo,
FF_GPU_MODULE_NAME,
"Print GPU names, graphic memory size, type, etc",
ffParseGPUCommandOptions,
ffParseGPUJsonObject,
ffPrintGPU,
ffGenerateGPUJsonResult,
ffPrintGPUHelpFormat,
2023-10-24 14:41:29 +08:00
ffGenerateGPUJsonConfig
);
2023-10-23 13:32:18 +08:00
ffOptionInitModuleArg(&options->moduleArgs);
2023-12-20 14:59:27 +08:00
options->driverSpecific = false;
2023-10-23 13:32:18 +08:00
options->forceVulkan = false;
options->temp = false;
options->hideType = FF_GPU_TYPE_UNKNOWN;
options->percent = (FFPercentConfig) { 50, 80 };
2023-10-23 13:32:18 +08:00
}
void ffDestroyGPUOptions(FFGPUOptions* options)
{
ffOptionDestroyModuleArg(&options->moduleArgs);
}