feat(gamemode): Add support for new GPU cards via nv_per_profile_editable in gamemode.ini

- Added a new configuration variable `nv_per_profile_editable` to the `gamemode.ini` file.
  - If set to 1 (default behavior), the code will use per-profile offset behavior.
  - If set to 0, the code will use the AllPerformanceLevels API, which is compatible with newer cards like the GTX5060ti.

- Updated the `gpuclockctl` utility to accept the `nv_per_profile_editable` parameter.
  - If the parameter is not provided, it defaults to 1 and uses the previous API for backward compatibility.

This change allows `gamemode` to support a wider range of GPU cards by providing flexibility in how GPU performance levels are managed.

**Notes:**
- Ensure that the `gamemode.ini` file includes the new `nv_per_profile_editable` setting.
- Verify that the updated `gpuclockctl` utility functions as expected with both default and specified values for `nv_per_profile_editable`.
- clang-formated

Tested on: RTX 5060 ti (driver 575.64.05) on Ubuntu 25.04
This commit is contained in:
mangobiche
2025-08-28 10:54:45 -05:00
parent e5b0a2bf3e
commit 3be7c13f7b
3 changed files with 46 additions and 47 deletions

View File

@@ -48,9 +48,9 @@ struct GameModeGPUInfo {
long vendor;
long device; /* path to device, ie. /sys/class/drm/card#/ */
long nv_core; /* Nvidia core clock */
long nv_mem; /* Nvidia mem clock */
long nv_powermizer_mode; /* NV Powermizer Mode */
long nv_core; /* Nvidia core clock */
long nv_mem; /* Nvidia mem clock */
long nv_powermizer_mode; /* NV Powermizer Mode */
long nv_per_profile_editable; /* Allows per profile editable offsets */
char amd_performance_level[GPU_VALUE_MAX]; /* The AMD performance level set to */

View File

@@ -177,7 +177,8 @@ int game_mode_apply_gpu(const GameModeGPUInfo *info)
info->vendor == Vendor_NVIDIA ? nv_core : info->amd_performance_level,
info->vendor == Vendor_NVIDIA ? nv_mem : NULL, /* Only use this if Nvidia */
info->vendor == Vendor_NVIDIA ? nv_powermizer_mode : NULL, /* Only use this if Nvidia */
info->vendor == Vendor_NVIDIA ? nv_per_profile_editable : NULL, /* Only use this if Nvidia */
info->vendor == Vendor_NVIDIA ? nv_per_profile_editable : NULL, /* Only use this if Nvidia
*/
NULL,
};
@@ -203,11 +204,7 @@ int game_mode_get_gpu(GameModeGPUInfo *info)
// Set up our command line to pass to gpuclockctl
// This doesn't need pkexec as get does not need elevated perms
const char *const exec_args[] = {
LIBEXECDIR "/gpuclockctl",
device,
"get",
profile_editable, //TODO:refactor
NULL,
LIBEXECDIR "/gpuclockctl", device, "get", profile_editable, NULL,
};
char buffer[EXTERNAL_BUFFER_MAX] = { 0 };

View File

@@ -132,8 +132,10 @@ static long get_gpu_index_id_nv(struct GameModeGPUInfo *info)
}
if (nv_device < 0) {
LOG_ERROR("Could not resolve NVIDIA index for DRM card%ld (no NVIDIA cards found up to that index)\n",
info->device);
LOG_ERROR(
"Could not resolve NVIDIA index for DRM card%ld (no NVIDIA cards found up to that "
"index)\n",
info->device);
}
return nv_device;
@@ -206,11 +208,11 @@ static int get_gpu_state_nv(struct GameModeGPUInfo *info)
/* Get the GPUMemoryTransferRateOffset parameter */
snprintf(arg,
NV_ARG_MAX,
NV_ATTRIBUTE_FORMAT NV_PERF_LEVEL_FORMAT,
info->device,
NV_MEM_OFFSET_ATTRIBUTE,
perf_level);
NV_ARG_MAX,
NV_ATTRIBUTE_FORMAT NV_PERF_LEVEL_FORMAT,
info->device,
NV_MEM_OFFSET_ATTRIBUTE,
perf_level);
attr = get_nv_attr(arg); // Should declaration be joined with assigment? :S
if (attr == NULL || attr[0] == '\0') {
@@ -257,10 +259,10 @@ static int get_gpu_state_nv(struct GameModeGPUInfo *info)
/* Get the GPUMemoryTransferRateOffset parameter */
snprintf(arg,
NV_ARG_MAX,
NV_ATTRIBUTE_FORMAT NV_ALL_PERF_LEVELS,
info->device,
NV_MEM_OFFSET_ATTRIBUTE);
NV_ARG_MAX,
NV_ATTRIBUTE_FORMAT NV_ALL_PERF_LEVELS,
info->device,
NV_MEM_OFFSET_ATTRIBUTE);
attr = get_nv_attr(arg); // Should declaration be joined with assigment? :S
if (attr == NULL || attr[0] == '\0') {
@@ -305,12 +307,12 @@ static int set_gpu_state_nv(struct GameModeGPUInfo *info)
/* Set the GPUGraphicsClockOffset parameter */
if (info->nv_core != -1) {
snprintf(arg,
NV_ARG_MAX,
NV_ATTRIBUTE_FORMAT NV_PERF_LEVEL_FORMAT "=%ld",
info->device,
NV_CORE_OFFSET_ATTRIBUTE,
perf_level,
info->nv_core);
NV_ARG_MAX,
NV_ATTRIBUTE_FORMAT NV_PERF_LEVEL_FORMAT "=%ld",
info->device,
NV_CORE_OFFSET_ATTRIBUTE,
perf_level,
info->nv_core);
if (set_nv_attr(arg) != 0) {
status = -1;
}
@@ -319,12 +321,12 @@ static int set_gpu_state_nv(struct GameModeGPUInfo *info)
/* Set the GPUMemoryTransferRateOffset parameter */
if (info->nv_mem != -1) {
snprintf(arg,
NV_ARG_MAX,
NV_ATTRIBUTE_FORMAT NV_PERF_LEVEL_FORMAT "=%ld",
info->device,
NV_MEM_OFFSET_ATTRIBUTE,
perf_level,
info->nv_mem);
NV_ARG_MAX,
NV_ATTRIBUTE_FORMAT NV_PERF_LEVEL_FORMAT "=%ld",
info->device,
NV_MEM_OFFSET_ATTRIBUTE,
perf_level,
info->nv_mem);
if (set_nv_attr(arg) != 0) {
status = -1;
}
@@ -333,11 +335,11 @@ static int set_gpu_state_nv(struct GameModeGPUInfo *info)
/* Set the GPUPowerMizerMode parameter if requested */
if (info->nv_powermizer_mode != -1) {
snprintf(arg,
NV_ARG_MAX,
NV_ATTRIBUTE_FORMAT "=%ld",
info->device,
NV_POWERMIZER_MODE_ATTRIBUTE,
info->nv_powermizer_mode);
NV_ARG_MAX,
NV_ATTRIBUTE_FORMAT "=%ld",
info->device,
NV_POWERMIZER_MODE_ATTRIBUTE,
info->nv_powermizer_mode);
if (set_nv_attr(arg) != 0) {
status = -1;
}
@@ -348,11 +350,11 @@ static int set_gpu_state_nv(struct GameModeGPUInfo *info)
/* Set the GPUGraphicsClockOffset parameter */
if (info->nv_core != -1) {
snprintf(arg,
NV_ARG_MAX,
NV_ATTRIBUTE_FORMAT NV_ALL_PERF_LEVELS "=%ld",
info->device,
NV_CORE_OFFSET_ATTRIBUTE,
info->nv_core);
NV_ARG_MAX,
NV_ATTRIBUTE_FORMAT NV_ALL_PERF_LEVELS "=%ld",
info->device,
NV_CORE_OFFSET_ATTRIBUTE,
info->nv_core);
if (set_nv_attr(arg) != 0) {
status = -1;
}
@@ -361,11 +363,11 @@ static int set_gpu_state_nv(struct GameModeGPUInfo *info)
/* Set the GPUMemoryTransferRateOffset parameter */
if (info->nv_mem != -1) {
snprintf(arg,
NV_ARG_MAX,
NV_ATTRIBUTE_FORMAT NV_ALL_PERF_LEVELS "=%ld",
info->device,
NV_MEM_OFFSET_ATTRIBUTE,
info->nv_mem);
NV_ARG_MAX,
NV_ATTRIBUTE_FORMAT NV_ALL_PERF_LEVELS "=%ld",
info->device,
NV_MEM_OFFSET_ATTRIBUTE,
info->nv_mem);
if (set_nv_attr(arg) != 0) {
status = -1;
}