From 142b2fb32d978ceed0e1352bb263581d44d32d59 Mon Sep 17 00:00:00 2001 From: Marc Di Luzio Date: Sun, 3 Feb 2019 18:33:41 +0000 Subject: [PATCH] Also add nv_perf_level for nvidia (needed as a parameter to nvidia-xsettings) --- daemon/daemon_config.c | 9 +++++++++ daemon/daemon_config.h | 1 + daemon/gamemode-gpu.c | 14 +++++++++++++- daemon/gpu-control.c | 4 ++-- daemon/gpu-control.h | 2 ++ daemon/gpuclockctl.c | 18 ++++++++++++------ example/gamemode.ini | 2 ++ 7 files changed, 41 insertions(+), 9 deletions(-) diff --git a/daemon/daemon_config.c b/daemon/daemon_config.c index 371792b..feedde7 100644 --- a/daemon/daemon_config.c +++ b/daemon/daemon_config.c @@ -81,6 +81,7 @@ struct GameModeConfig { long gpu_device; long nv_core_clock_mhz_offset; long nv_mem_clock_mhz_offset; + long nv_perf_level; long amd_core_clock_percentage; long amd_mem_clock_percentage; }; @@ -213,6 +214,8 @@ static int inih_handler(void *user, const char *section, const char *name, const valid = get_long_value(name, value, &self->nv_core_clock_mhz_offset); } else if (strcmp(name, "nv_mem_clock_mhz_offset") == 0) { valid = get_long_value(name, value, &self->nv_mem_clock_mhz_offset); + } else if (strcmp(name, "nv_perf_level") == 0) { + valid = get_long_value(name, value, &self->nv_perf_level); } else if (strcmp(name, "amd_core_clock_percentage") == 0) { valid = get_long_value(name, value, &self->amd_core_clock_percentage); } else if (strcmp(name, "amd_mem_clock_percentage") == 0) { @@ -284,6 +287,7 @@ static void load_config_files(GameModeConfig *self) self->gpu_device = -1; /* 0 is a valid device ID so use -1 to indicate no value */ self->nv_core_clock_mhz_offset = 0; self->nv_mem_clock_mhz_offset = 0; + self->nv_perf_level = -1; self->amd_core_clock_percentage = 0; self->amd_mem_clock_percentage = 0; @@ -543,6 +547,11 @@ void config_get_nv_core_clock_mhz_offset(GameModeConfig *self, long *value) void config_get_nv_mem_clock_mhz_offset(GameModeConfig *self, long *value) { memcpy_locked_config(self, value, &self->nv_mem_clock_mhz_offset, sizeof(long)); + +} +void config_get_nv_perf_level(GameModeConfig *self, long *value) +{ + memcpy_locked_config(self, value, &self->nv_perf_level, sizeof(long)); } void config_get_amd_core_clock_percentage(GameModeConfig *self, long *value) diff --git a/daemon/daemon_config.h b/daemon/daemon_config.h index e4aed7d..f3fcde8 100644 --- a/daemon/daemon_config.h +++ b/daemon/daemon_config.h @@ -138,5 +138,6 @@ void config_get_gpu_vendor(GameModeConfig *self, long *value); void config_get_gpu_device(GameModeConfig *self, long *value); void config_get_nv_core_clock_mhz_offset(GameModeConfig *self, long *value); void config_get_nv_mem_clock_mhz_offset(GameModeConfig *self, long *value); +void config_get_nv_perf_level(GameModeConfig *self, long *value); void config_get_amd_core_clock_percentage(GameModeConfig *self, long *value); void config_get_amd_mem_clock_percentage(GameModeConfig *self, long *value); diff --git a/daemon/gamemode-gpu.c b/daemon/gamemode-gpu.c index 5f5d523..c3b6a7d 100644 --- a/daemon/gamemode-gpu.c +++ b/daemon/gamemode-gpu.c @@ -111,7 +111,7 @@ int game_mode_initialise_gpu(GameModeConfig *config, GameModeGPUInfo **info) const int nv_mem_hard_limit = 2000; if (new_info->core > nv_core_hard_limit || new_info->mem > nv_mem_hard_limit) { LOG_ERROR( - "ERROR NVIDIA Overclock value above safety levels of +%d (core) +%d (mem), will " + "ERROR: NVIDIA Overclock value above safety levels of +%d (core) +%d (mem), will " "not overclock!\n", nv_core_hard_limit, nv_mem_hard_limit); @@ -122,6 +122,15 @@ int game_mode_initialise_gpu(GameModeConfig *config, GameModeGPUInfo **info) return -1; } + /* Sanity check the performance level value as well */ + config_get_nv_perf_level(config, &new_info->nv_perf_level); + if(new_info->nv_perf_level < 0 || new_info->nv_perf_level > 16) + { + LOG_ERROR( "ERROR: NVIDIA Performance level value invalid (%ld), will not apply optimisations!\n", new_info->nv_perf_level ); + free(new_info); + return -1; + } + break; case Vendor_AMD: config_get_amd_core_clock_percentage(config, &new_info->core); @@ -186,6 +195,8 @@ int game_mode_apply_gpu(const GameModeGPUInfo *info, bool apply) snprintf(core, 8, "%ld", info->core); char mem[8]; snprintf(mem, 8, "%ld", info->mem); + char nv_perf_level[4]; + snprintf(nv_perf_level, 4, "%ld", info->nv_perf_level); // TODO: Actually pass right arguments const char *const exec_args[] = { @@ -196,6 +207,7 @@ int game_mode_apply_gpu(const GameModeGPUInfo *info, bool apply) "set", apply ? core : "0", /* For now simply reset to zero */ apply ? mem : "0", /* could in the future store default values for reset */ + info->vendor == Vendor_NVIDIA ? nv_perf_level : NULL, /* Only use this if Nvidia */ NULL, }; diff --git a/daemon/gpu-control.c b/daemon/gpu-control.c index 6b24f65..69b38a4 100644 --- a/daemon/gpu-control.c +++ b/daemon/gpu-control.c @@ -35,11 +35,11 @@ POSSIBILITY OF SUCH DAMAGE. #include "logging.h" // TODO -// Gather GPU type and information automatically // Apply Nvidia GPU settings (CoolBits will be needed) // Apply AMD GPU settings (Will need user changing pwm1_enable) -// Intel? // Provide documentation on optimisations +// Intel? +// Gather GPU type and information automatically if possible // NVIDIA // Running these commands: diff --git a/daemon/gpu-control.h b/daemon/gpu-control.h index 77f2d86..239fffa 100644 --- a/daemon/gpu-control.h +++ b/daemon/gpu-control.h @@ -49,6 +49,8 @@ struct GameModeGPUInfo { long core; /* Core clock to apply */ long mem; /* Mem clock to apply */ + + long nv_perf_level; /* The Nvidia Performance Level to adjust */ }; /** diff --git a/daemon/gpuclockctl.c b/daemon/gpuclockctl.c index aec086c..026bd1b 100644 --- a/daemon/gpuclockctl.c +++ b/daemon/gpuclockctl.c @@ -36,7 +36,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "gpu-control.h" /* Helper to quit with usage */ -static const char *usage_text = "usage: gpuclockctl PCI_ID DEVICE [get] [set CORE MEM]"; +static const char *usage_text = "usage: gpuclockctl PCI_ID DEVICE [get] [set CORE MEM [PERF_LEVEL]]]"; static void print_usage_and_exit(void) { fprintf(stderr, "%s\n", usage_text); @@ -68,12 +68,12 @@ static long get_device(const char *val) } /* Helper to get and verify core and mem value */ -static long get_coremem(const char *val) +static long get_generic_value(const char *val) { char *end; long ret = strtol(val, &end, 10); if (ret < 0 || end == val) { - LOG_ERROR("ERROR: Invalid core or mem value passed (%ld)!\n", ret); + LOG_ERROR("ERROR: Invalid value passed (%ld)!\n", ret); print_usage_and_exit(); } return ret; @@ -95,7 +95,7 @@ int main(int argc, char *argv[]) get_gpu_state(&info); printf("%ld %ld\n", info.core, info.mem); - } else if (argc == 6 && strncmp(argv[3], "set", 3) == 0) { + } else if (argc >=6 && argc <=7 && strncmp(argv[3], "set", 3) == 0) { /* Must be root to set the state */ if (geteuid() != 0) { fprintf(stderr, "gpuclockctl must be run as root to set values\n"); @@ -107,8 +107,11 @@ int main(int argc, char *argv[]) memset(&info, 0, sizeof(info)); info.vendor = get_vendor(argv[1]); info.device = get_device(argv[2]); - info.core = get_coremem(argv[4]); - info.mem = get_coremem(argv[5]); + info.core = get_generic_value(argv[4]); + info.mem = get_generic_value(argv[5]); + + if( info.vendor == Vendor_NVIDIA ) + info.nv_perf_level = get_generic_value(argv[6]); printf("gpuclockctl setting core:%ld mem:%ld on device:%ld with vendor 0x%04x\n", info.core, @@ -116,6 +119,9 @@ int main(int argc, char *argv[]) info.device, (unsigned short)info.vendor); + if( info.vendor == Vendor_NVIDIA ) + printf("on Performance Level %ld\n", info.nv_perf_level); + return set_gpu_state(&info); } else { print_usage_and_exit(); diff --git a/example/gamemode.ini b/example/gamemode.ini index f09de7c..d9fb48e 100644 --- a/example/gamemode.ini +++ b/example/gamemode.ini @@ -52,6 +52,8 @@ inhibit_screensaver=1 ; Requires the coolbits extension activated in nvidia-xconfig ;nv_core_clock_mhz_offset=0 ;nv_mem_clock_mhz_offset=0 +; This corresponds to the performance level to edit in nvidia-xconfig +;nv_perf_level=1 ; AMD specific settings (these are percentages applied on top of the baseline, ie. 0 applies no change) ; Requires the the AMDGPU kernel module