From b1bf33d386f5176d223f857b8a504324a559f81c Mon Sep 17 00:00:00 2001 From: Marc Di Luzio Date: Wed, 30 Jan 2019 21:12:11 +0000 Subject: [PATCH] Add config parameters for GPU clocking --- daemon/daemon_config.c | 52 ++++++++++++++++++++++++++++++++++++++++++ daemon/daemon_config.h | 9 ++++++++ daemon/gamemode-gpu.c | 45 ++++++++++++++++++++++++++++++++---- daemon/gamemode.c | 4 ++-- daemon/gamemode.h | 2 +- example/gamemode.ini | 16 +++++++++++++ 6 files changed, 120 insertions(+), 8 deletions(-) diff --git a/daemon/daemon_config.c b/daemon/daemon_config.c index 3729bfe..c9bd11a 100644 --- a/daemon/daemon_config.c +++ b/daemon/daemon_config.c @@ -75,6 +75,12 @@ struct GameModeConfig { long inhibit_screensaver; long reaper_frequency; + + long apply_gpu_optimisations; + long nv_core_clock_mhz_offset; + long nv_mem_clock_mhz_offset; + long amd_core_clock_percentage; + long amd_mem_clock_percentage; }; /* @@ -173,6 +179,19 @@ static int inih_handler(void *user, const char *section, const char *name, const } else if (strcmp(name, "inhibit_screensaver") == 0) { valid = get_long_value(name, value, &self->inhibit_screensaver); } + } else if (strcmp(section, "gpu") == 0) { + /* GPU subsection */ + if (strcmp(name, "apply_gpu_optimisations") == 0) { + valid = get_long_value(name, value, &self->apply_gpu_optimisations); + } else if (strcmp(name, "nv_core_clock_mhz_offset") == 0) { + 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, "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) { + valid = get_long_value(name, value, &self->amd_mem_clock_percentage); + } } else if (strcmp(section, "custom") == 0) { /* Custom subsection */ if (strcmp(name, "start") == 0) { @@ -234,6 +253,11 @@ static void load_config_files(GameModeConfig *self) self->renice = 4; /* default value of 4 */ self->reaper_frequency = DEFAULT_REAPER_FREQ; self->inhibit_screensaver = 1; /* Defaults to on */ + self->apply_gpu_optimisations = 0; + self->nv_core_clock_mhz_offset = 0; + self->nv_mem_clock_mhz_offset = 0; + self->amd_core_clock_percentage = 0; + self->amd_mem_clock_percentage = 0; /* * Locations to load, in order @@ -461,3 +485,31 @@ void config_get_ioprio_value(GameModeConfig *self, int *value) else *value = atoi(ioprio_value); } + +/* + * Get various config info for gpu optimisations + */ +void config_get_apply_gpu_optimisations(GameModeConfig *self, long *value) +{ + memcpy_locked_config(self, value, &self->apply_gpu_optimisations, sizeof(long)); +} + +void config_get_nv_core_clock_mhz_offset(GameModeConfig *self, long *value) +{ + memcpy_locked_config(self, value, &self->nv_core_clock_mhz_offset, sizeof(long)); +} + +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_amd_core_clock_percentage(GameModeConfig *self, long *value) +{ + memcpy_locked_config(self, value, &self->amd_core_clock_percentage, sizeof(long)); +} + +void config_get_amd_mem_clock_percentage(GameModeConfig *self, long *value) +{ + memcpy_locked_config(self, value, &self->amd_mem_clock_percentage, sizeof(long)); +} diff --git a/daemon/daemon_config.h b/daemon/daemon_config.h index 608401b..0253c28 100644 --- a/daemon/daemon_config.h +++ b/daemon/daemon_config.h @@ -129,3 +129,12 @@ void config_get_renice_value(GameModeConfig *self, long *value); * Get the ioprio value */ void config_get_ioprio_value(GameModeConfig *self, int *value); + +/* + * Get various config info for gpu optimisations + */ +void config_get_apply_gpu_optimisations(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_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 bfd4fa9..5bf86c9 100644 --- a/daemon/gamemode-gpu.c +++ b/daemon/gamemode-gpu.c @@ -36,6 +36,8 @@ POSSIBILITY OF SUCH DAMAGE. #include "helpers.h" #include "logging.h" +#include "daemon_config.h" + // TODO // Gather GPU type and information // Allow configuration file specifying of gpu info @@ -56,13 +58,19 @@ enum GPUVendor { struct GameModeGPUInfo { enum GPUVendor vendor; int device; /* path to device, ie. /sys/class/drm/card#/ */ + + long core; /* Core clock to apply */ + long mem; /* Mem clock to apply */ }; /** * Applies or removes Nvidia optimisations */ -static int apply_gpu_nvidia(bool apply) +static int apply_gpu_nvidia(const GameModeGPUInfo *info, bool apply) { + if (!info) + return 0; + // Running these commands: // nvidia-settings -a '[gpu:0]/GPUMemoryTransferRateOffset[3]=1400' // nvidia-settings -a '[gpu:0]/GPUGraphicsClockOffset[3]=50' @@ -76,8 +84,11 @@ static int apply_gpu_nvidia(bool apply) /** * Applies or removes AMD optimisations */ -static int apply_gpu_amd(bool apply) +static int apply_gpu_amd(const GameModeGPUInfo *info, bool apply) { + if (!info) + return 0; + // We'll want to set both the following: // core: device/pp_sclk_od (0%+ additional) // mem: device/pp_mclk_od (0%+ additional) @@ -92,7 +103,7 @@ static int apply_gpu_amd(bool apply) /** * Attempts to identify the current in use GPU information */ -int game_mode_identify_gpu(GameModeGPUInfo **info) +int game_mode_initialise_gpu(GameModeConfig *config, GameModeGPUInfo **info) { int status = 0; @@ -100,12 +111,32 @@ int game_mode_identify_gpu(GameModeGPUInfo **info) if (!info || *info) FATAL_ERROR("Invalid GameModeGPUInfo passed to %s", __func__); + /* Early out if we have this feature turned off */ + long apply = 0; + config_get_apply_gpu_optimisations(config, &apply); + if (apply == 0) + return 0; + /* Create the context */ GameModeGPUInfo *new_info = malloc(sizeof(GameModeGPUInfo)); memset(new_info, 0, sizeof(GameModeGPUInfo)); // TODO: Fill in the GPU info + /* Load the config based on GPU */ + switch (new_info->vendor) { + case Vendor_NVIDIA: + config_get_nv_core_clock_mhz_offset(config, &new_info->core); + config_get_nv_mem_clock_mhz_offset(config, &new_info->mem); + break; + case Vendor_AMD: + config_get_amd_core_clock_percentage(config, &new_info->core); + config_get_amd_mem_clock_percentage(config, &new_info->mem); + break; + default: + break; + } + /* Give back the new gpu info */ *info = new_info; @@ -125,11 +156,15 @@ void game_mode_free_gpu(GameModeGPUInfo **info) */ int game_mode_apply_gpu(const GameModeGPUInfo *info, bool apply) { + // Null info means don't apply anything + if (!info) + return 0; + switch (info->vendor) { case Vendor_NVIDIA: - return apply_gpu_nvidia(apply); + return apply_gpu_nvidia(info, apply); case Vendor_AMD: - return apply_gpu_amd(apply); + return apply_gpu_amd(info, apply); default: break; } diff --git a/daemon/gamemode.c b/daemon/gamemode.c index f1479dc..2b80057 100644 --- a/daemon/gamemode.c +++ b/daemon/gamemode.c @@ -109,8 +109,8 @@ void game_mode_context_init(GameModeContext *self) self->config = config_create(); config_init(self->config); - /* Grab the current GPU */ - game_mode_identify_gpu(&self->gpu_info); + /* Initialise the current GPU info */ + game_mode_initialise_gpu(self->config, &self->gpu_info); pthread_rwlock_init(&self->rwlock, NULL); pthread_mutex_init(&self->reaper.mutex, NULL); diff --git a/daemon/gamemode.h b/daemon/gamemode.h index 6304e2f..c70c048 100644 --- a/daemon/gamemode.h +++ b/daemon/gamemode.h @@ -141,6 +141,6 @@ int game_mode_run_client_tests(void); * Provides internal APU functions to apply optimisations to gpus */ typedef struct GameModeGPUInfo GameModeGPUInfo; -int game_mode_identify_gpu(GameModeGPUInfo **info); +int game_mode_initialise_gpu(GameModeConfig *config, GameModeGPUInfo **info); void game_mode_free_gpu(GameModeGPUInfo **info); int game_mode_apply_gpu(const GameModeGPUInfo *info, bool apply); diff --git a/example/gamemode.ini b/example/gamemode.ini index f6a73a4..f366e46 100644 --- a/example/gamemode.ini +++ b/example/gamemode.ini @@ -34,6 +34,22 @@ inhibit_screensaver=1 ;blacklist=HalfLife3 ; glxgears +[gpu] +; Here Be Dragons! +; Warning: Use these settings at your own risk +; Any damage to hardware incurred due to this feature is your responsibility and yours alone + +; Setting this to 1 will allow gamemode to attempt to apply GPU optimisations such as overclocks +;apply_gpu_optimisations=0 + +; Nvidia specific settings (these are Mhz offsets from the baseline, ie. 0 applies no change) +;nv_core_clock_mhz_offset=0 +;nv_mem_clock_mhz_offset=0 + +; AMD specific settings (these are percentages applied on top of the baseline, ie. 0 applies no change) +;amd_core_clock_percentage=0 +;amd_mem_clock_percentage=0 + [custom] ; Custom scripts (executed using the shell) when gamemode starts and ends ;start=notify-send "GameMode started"