Browse Source

Add config parameters for GPU clocking

Marc Di Luzio 6 years ago
parent
commit
b1bf33d386
6 changed files with 120 additions and 8 deletions
  1. 52 0
      daemon/daemon_config.c
  2. 9 0
      daemon/daemon_config.h
  3. 40 5
      daemon/gamemode-gpu.c
  4. 2 2
      daemon/gamemode.c
  5. 1 1
      daemon/gamemode.h
  6. 16 0
      example/gamemode.ini

+ 52 - 0
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));
+}

+ 9 - 0
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);

+ 40 - 5
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;
 	}

+ 2 - 2
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);

+ 1 - 1
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);

+ 16 - 0
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"