mirror of
https://github.com/FeralInteractive/gamemode.git
synced 2025-06-06 15:47:20 +02:00
Merge pull request #112 from mdiluz/automatic-gpu-info
Clean up NV optimization config
This commit is contained in:
commit
0c08359005
@ -91,7 +91,6 @@ struct GameModeConfig {
|
||||
long gpu_device;
|
||||
long nv_core_clock_mhz_offset;
|
||||
long nv_mem_clock_mhz_offset;
|
||||
long nv_perf_level;
|
||||
long nv_powermizer_mode;
|
||||
char amd_performance_level[CONFIG_VALUE_MAX];
|
||||
|
||||
@ -257,8 +256,6 @@ static int inih_handler(void *user, const char *section, const char *name, const
|
||||
valid = get_long_value(name, value, &self->values.nv_core_clock_mhz_offset);
|
||||
} else if (strcmp(name, "nv_mem_clock_mhz_offset") == 0) {
|
||||
valid = get_long_value(name, value, &self->values.nv_mem_clock_mhz_offset);
|
||||
} else if (strcmp(name, "nv_perf_level") == 0) {
|
||||
valid = get_long_value(name, value, &self->values.nv_perf_level);
|
||||
} else if (strcmp(name, "nv_powermizer_mode") == 0) {
|
||||
valid = get_long_value(name, value, &self->values.nv_powermizer_mode);
|
||||
} else if (strcmp(name, "amd_performance_level") == 0) {
|
||||
@ -332,8 +329,9 @@ static void load_config_files(GameModeConfig *self)
|
||||
self->values.renice = 4; /* default value of 4 */
|
||||
self->values.reaper_frequency = DEFAULT_REAPER_FREQ;
|
||||
self->values.gpu_device = -1; /* 0 is a valid device ID so use -1 to indicate no value */
|
||||
self->values.nv_perf_level = -1;
|
||||
self->values.nv_powermizer_mode = -1;
|
||||
self->values.nv_core_clock_mhz_offset = -1;
|
||||
self->values.nv_mem_clock_mhz_offset = -1;
|
||||
self->values.script_timeout = 10; /* Default to 10 seconds for scripts */
|
||||
|
||||
/*
|
||||
@ -585,7 +583,6 @@ void config_get_apply_gpu_optimisations(GameModeConfig *self, char value[CONFIG_
|
||||
DEFINE_CONFIG_GET(gpu_device)
|
||||
DEFINE_CONFIG_GET(nv_core_clock_mhz_offset)
|
||||
DEFINE_CONFIG_GET(nv_mem_clock_mhz_offset)
|
||||
DEFINE_CONFIG_GET(nv_perf_level)
|
||||
DEFINE_CONFIG_GET(nv_powermizer_mode)
|
||||
|
||||
void config_get_amd_performance_level(GameModeConfig *self, char value[CONFIG_VALUE_MAX])
|
||||
|
@ -142,7 +142,6 @@ void config_get_apply_gpu_optimisations(GameModeConfig *self, char value[CONFIG_
|
||||
long config_get_gpu_device(GameModeConfig *self);
|
||||
long config_get_nv_core_clock_mhz_offset(GameModeConfig *self);
|
||||
long config_get_nv_mem_clock_mhz_offset(GameModeConfig *self);
|
||||
long config_get_nv_perf_level(GameModeConfig *self);
|
||||
long config_get_nv_powermizer_mode(GameModeConfig *self);
|
||||
void config_get_amd_performance_level(GameModeConfig *self, char value[CONFIG_VALUE_MAX]);
|
||||
|
||||
|
@ -47,8 +47,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
int game_mode_initialise_gpu(GameModeConfig *config, GameModeGPUInfo **info)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
/* Verify input, this is programmer error */
|
||||
if (!info || *info)
|
||||
FATAL_ERROR("Invalid GameModeGPUInfo passed to %s", __func__);
|
||||
@ -83,33 +81,9 @@ int game_mode_initialise_gpu(GameModeConfig *config, GameModeGPUInfo **info)
|
||||
}
|
||||
|
||||
/* Fill in GPU vendor */
|
||||
char path[64] = { 0 };
|
||||
if (snprintf(path, 64, "/sys/class/drm/card%ld/device/vendor", new_info->device) < 0) {
|
||||
LOG_ERROR("snprintf failed, will not apply gpu optimisations!\n");
|
||||
return -1;
|
||||
}
|
||||
FILE *vendor = fopen(path, "r");
|
||||
if (!vendor) {
|
||||
LOG_ERROR("Couldn't open vendor file at %s, will not apply gpu optimisations!\n", path);
|
||||
return -1;
|
||||
}
|
||||
char buff[64];
|
||||
if (fgets(buff, 64, vendor) != NULL) {
|
||||
new_info->vendor = strtol(buff, NULL, 0);
|
||||
} else {
|
||||
LOG_ERROR("Coudn't read contents of file %s, will not apply optimisations!\n", path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* verify GPU vendor */
|
||||
new_info->vendor = gamemode_get_gpu_vendor(new_info->device);
|
||||
if (!GPUVendorValid(new_info->vendor)) {
|
||||
LOG_ERROR("Unknown vendor value (0x%04x) found, cannot apply optimisations!\n",
|
||||
(unsigned int)new_info->vendor);
|
||||
LOG_ERROR("Known values are: 0x%04x (NVIDIA) 0x%04x (AMD) 0x%04x (Intel)\n",
|
||||
Vendor_NVIDIA,
|
||||
Vendor_AMD,
|
||||
Vendor_Intel);
|
||||
free(new_info);
|
||||
LOG_ERROR("Found invalid vendor, will not apply optimisations!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -118,7 +92,6 @@ int game_mode_initialise_gpu(GameModeConfig *config, GameModeGPUInfo **info)
|
||||
case Vendor_NVIDIA:
|
||||
new_info->nv_core = config_get_nv_core_clock_mhz_offset(config);
|
||||
new_info->nv_mem = config_get_nv_mem_clock_mhz_offset(config);
|
||||
new_info->nv_perf_level = config_get_nv_perf_level(config);
|
||||
new_info->nv_powermizer_mode = config_get_nv_powermizer_mode(config);
|
||||
|
||||
/* Reject values over some guessed values
|
||||
@ -139,18 +112,6 @@ int game_mode_initialise_gpu(GameModeConfig *config, GameModeGPUInfo **info)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Sanity check the performance level value as well */
|
||||
/* Allow an invalid perf level if we've got the powermizer mode set */
|
||||
if (!(new_info->nv_perf_level == -1 && new_info->nv_powermizer_mode != -1) &&
|
||||
(new_info->nv_perf_level < 0 || new_info->nv_perf_level > 16)) {
|
||||
LOG_ERROR(
|
||||
"NVIDIA Performance level value likely invalid (%ld), will not apply "
|
||||
"optimisations!\n",
|
||||
new_info->nv_perf_level);
|
||||
free(new_info);
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
case Vendor_AMD:
|
||||
config_get_amd_performance_level(config, new_info->amd_performance_level);
|
||||
@ -168,7 +129,7 @@ int game_mode_initialise_gpu(GameModeConfig *config, GameModeGPUInfo **info)
|
||||
|
||||
/* Give back the new gpu info */
|
||||
*info = new_info;
|
||||
return status;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Simply used to free the GPU info object */
|
||||
@ -196,8 +157,6 @@ int game_mode_apply_gpu(const GameModeGPUInfo *info)
|
||||
LOG_MSG("Requesting GPU optimisations on device:%ld\n", info->device);
|
||||
|
||||
/* Generate the input strings */
|
||||
char vendor[7];
|
||||
snprintf(vendor, 7, "0x%04x", (short)info->vendor);
|
||||
char device[4];
|
||||
snprintf(device, 4, "%ld", info->device);
|
||||
|
||||
@ -205,8 +164,6 @@ int game_mode_apply_gpu(const GameModeGPUInfo *info)
|
||||
snprintf(nv_core, 8, "%ld", info->nv_core);
|
||||
char nv_mem[8];
|
||||
snprintf(nv_mem, 8, "%ld", info->nv_mem);
|
||||
char nv_perf_level[4];
|
||||
snprintf(nv_perf_level, 4, "%ld", info->nv_perf_level);
|
||||
char nv_powermizer_mode[4];
|
||||
snprintf(nv_powermizer_mode, 4, "%ld", info->nv_powermizer_mode);
|
||||
|
||||
@ -214,12 +171,10 @@ int game_mode_apply_gpu(const GameModeGPUInfo *info)
|
||||
const char *const exec_args[] = {
|
||||
"/usr/bin/pkexec",
|
||||
LIBEXECDIR "/gpuclockctl",
|
||||
vendor,
|
||||
device,
|
||||
"set",
|
||||
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_perf_level : NULL, /* Only use this if Nvidia */
|
||||
info->vendor == Vendor_NVIDIA ? nv_powermizer_mode : NULL, /* Only use this if Nvidia */
|
||||
NULL,
|
||||
};
|
||||
@ -238,21 +193,15 @@ int game_mode_get_gpu(GameModeGPUInfo *info)
|
||||
return 0;
|
||||
|
||||
/* Generate the input strings */
|
||||
char vendor[7];
|
||||
snprintf(vendor, 7, "0x%04x", (short)info->vendor);
|
||||
char device[4];
|
||||
snprintf(device, 4, "%ld", info->device);
|
||||
char nv_perf_level[4];
|
||||
snprintf(nv_perf_level, 4, "%ld", info->nv_perf_level);
|
||||
|
||||
// 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",
|
||||
vendor,
|
||||
device,
|
||||
"get",
|
||||
info->vendor == Vendor_NVIDIA ? nv_perf_level : NULL, /* Only use this if Nvidia */
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
@ -456,9 +456,13 @@ int run_gpu_optimisation_tests(struct GameModeConfig *config)
|
||||
char original_amd_performance_level[CONFIG_VALUE_MAX];
|
||||
strncpy(original_amd_performance_level, gpuinfo->amd_performance_level, CONFIG_VALUE_MAX);
|
||||
|
||||
/* account for when powermizer is not set */
|
||||
/* account for when settings are not set */
|
||||
if (expected_nv_powermizer_mode == -1)
|
||||
expected_nv_powermizer_mode = original_nv_powermizer_mode;
|
||||
if (expected_core == -1)
|
||||
expected_core = original_nv_core;
|
||||
if (expected_mem == -1)
|
||||
expected_mem = original_nv_mem;
|
||||
|
||||
/* Start gamemode and check the new values */
|
||||
gamemode_request_start();
|
||||
|
72
daemon/gpu-control.c
Normal file
72
daemon/gpu-control.c
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2017-2018, Feral Interactive
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Feral Interactive nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#include "gpu-control.h"
|
||||
#include "logging.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Get the vendor for a device */
|
||||
enum GPUVendor gamemode_get_gpu_vendor(long device)
|
||||
{
|
||||
enum GPUVendor vendor = Vendor_Invalid;
|
||||
|
||||
/* Fill in GPU vendor */
|
||||
char path[64] = { 0 };
|
||||
if (snprintf(path, 64, "/sys/class/drm/card%ld/device/vendor", device) < 0) {
|
||||
LOG_ERROR("snprintf failed, will not apply gpu optimisations!\n");
|
||||
return Vendor_Invalid;
|
||||
}
|
||||
FILE *file = fopen(path, "r");
|
||||
if (!file) {
|
||||
LOG_ERROR("Couldn't open vendor file at %s, will not apply gpu optimisations!\n", path);
|
||||
return Vendor_Invalid;
|
||||
}
|
||||
char buff[64];
|
||||
if (fgets(buff, 64, file) != NULL) {
|
||||
vendor = strtol(buff, NULL, 0);
|
||||
} else {
|
||||
LOG_ERROR("Coudn't read contents of file %s, will not apply optimisations!\n", path);
|
||||
return Vendor_Invalid;
|
||||
}
|
||||
|
||||
/* verify GPU vendor */
|
||||
if (!GPUVendorValid(vendor)) {
|
||||
LOG_ERROR("Unknown vendor value (0x%04x) found, cannot apply optimisations!\n",
|
||||
(unsigned int)vendor);
|
||||
LOG_ERROR("Known values are: 0x%04x (NVIDIA) 0x%04x (AMD) 0x%04x (Intel)\n",
|
||||
Vendor_NVIDIA,
|
||||
Vendor_AMD,
|
||||
Vendor_Intel);
|
||||
return Vendor_Invalid;
|
||||
}
|
||||
|
||||
return vendor;
|
||||
}
|
@ -46,8 +46,7 @@ enum GPUVendor {
|
||||
/* Storage for GPU info*/
|
||||
struct GameModeGPUInfo {
|
||||
long vendor;
|
||||
long device; /* path to device, ie. /sys/class/drm/card#/ */
|
||||
long nv_perf_level; /* The Nvidia Performance Level to adjust */
|
||||
long device; /* path to device, ie. /sys/class/drm/card#/ */
|
||||
|
||||
long nv_core; /* Nvidia core clock */
|
||||
long nv_mem; /* Nvidia mem clock */
|
||||
@ -55,3 +54,6 @@ struct GameModeGPUInfo {
|
||||
|
||||
char amd_performance_level[CONFIG_VALUE_MAX]; /* The AMD performance level set to */
|
||||
};
|
||||
|
||||
/* Get the vendor for a device */
|
||||
enum GPUVendor gamemode_get_gpu_vendor(long device);
|
||||
|
@ -40,6 +40,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
#define NV_CORE_OFFSET_ATTRIBUTE "GPUGraphicsClockOffset"
|
||||
#define NV_MEM_OFFSET_ATTRIBUTE "GPUMemoryTransferRateOffset"
|
||||
#define NV_POWERMIZER_MODE_ATTRIBUTE "GPUPowerMizerMode"
|
||||
#define NV_PERFMODES_ATTRIBUTE "GPUPerfModes"
|
||||
#define NV_PCIDEVICE_ATTRIBUTE "PCIDevice"
|
||||
#define NV_ATTRIBUTE_FORMAT "[gpu:%ld]/%s"
|
||||
#define NV_PERF_LEVEL_FORMAT "[%ld]"
|
||||
|
||||
@ -54,14 +56,59 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/* Helper to quit with usage */
|
||||
static const char *usage_text =
|
||||
"usage: gpuclockctl PCI_ID DEVICE [get] [set CORE MEM [PERF_LEVEL]]]";
|
||||
"usage: gpuclockctl DEVICE {arg}\n\t\tget - return current values\n\t\tset [NV_CORE NV_MEM "
|
||||
"NV_POWERMIZER_MODE | AMD_PERFORMANCE_LEVEL] - set current values";
|
||||
static void print_usage_and_exit(void)
|
||||
{
|
||||
fprintf(stderr, "%s\n", usage_text);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static int get_gpu_state_nv(struct GameModeGPUInfo *info)
|
||||
/* Get the nvidia driver index for the current GPU */
|
||||
static long get_gpu_index_id_nv(struct GameModeGPUInfo *info)
|
||||
{
|
||||
// Default to using the current device number
|
||||
long gpu_index = info->device;
|
||||
|
||||
if (info->vendor != Vendor_NVIDIA)
|
||||
return -1;
|
||||
|
||||
if (!getenv("DISPLAY"))
|
||||
LOG_ERROR("Getting Nvidia parameters requires DISPLAY to be set - will likely fail!\n");
|
||||
long current = 0;
|
||||
do {
|
||||
char arg[128] = { 0 };
|
||||
char buf[EXTERNAL_BUFFER_MAX] = { 0 };
|
||||
char *end;
|
||||
|
||||
/* Get the PCI id parameter */
|
||||
snprintf(arg, 128, NV_ATTRIBUTE_FORMAT, current, NV_PCIDEVICE_ATTRIBUTE);
|
||||
const char *exec_args_core[] = { "/usr/bin/nvidia-settings", "-q", arg, "-t", NULL };
|
||||
if (run_external_process(exec_args_core, buf, -1) != 0) {
|
||||
LOG_ERROR("Failed to get %s! Will be defaulting to nvidia gpu index %ld\n",
|
||||
arg,
|
||||
gpu_index);
|
||||
/* Failure just means we've overrun the device list */
|
||||
break;
|
||||
}
|
||||
|
||||
long pcidevice = strtol(buf, &end, 10);
|
||||
if (end == buf) {
|
||||
LOG_ERROR("Failed to parse output for \"%s\" output was \"%s\"!\n", arg, buf);
|
||||
break;
|
||||
}
|
||||
|
||||
if (info->device == pcidevice) {
|
||||
gpu_index = current;
|
||||
break;
|
||||
}
|
||||
} while (true);
|
||||
|
||||
return gpu_index;
|
||||
}
|
||||
|
||||
/* Get the max nvidia perf level */
|
||||
static long get_max_perf_level_nv(struct GameModeGPUInfo *info)
|
||||
{
|
||||
if (info->vendor != Vendor_NVIDIA)
|
||||
return -1;
|
||||
@ -69,48 +116,80 @@ static int get_gpu_state_nv(struct GameModeGPUInfo *info)
|
||||
if (!getenv("DISPLAY"))
|
||||
LOG_ERROR("Getting Nvidia parameters requires DISPLAY to be set - will likely fail!\n");
|
||||
|
||||
char arg[128] = { 0 };
|
||||
char buf[EXTERNAL_BUFFER_MAX] = { 0 };
|
||||
|
||||
snprintf(arg, 128, NV_ATTRIBUTE_FORMAT, info->device, NV_PERFMODES_ATTRIBUTE);
|
||||
const char *exec_args[] = { "/usr/bin/nvidia-settings", "-q", arg, "-t", NULL };
|
||||
if (run_external_process(exec_args, buf, -1) != 0) {
|
||||
LOG_ERROR("Failed to get %s!\n", arg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *ptr = strrchr(buf, ';');
|
||||
long level = -1;
|
||||
if (!ptr || sscanf(ptr, "; perf=%ld", &level) != 1) {
|
||||
LOG_ERROR(
|
||||
"Output didn't match expected format, couldn't discern highest perf level from "
|
||||
"nvidia-settings!\n");
|
||||
LOG_ERROR("Output:%s\n", buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return level;
|
||||
}
|
||||
|
||||
/* Get the nvidia gpu state */
|
||||
static int get_gpu_state_nv(struct GameModeGPUInfo *info)
|
||||
{
|
||||
if (info->vendor != Vendor_NVIDIA)
|
||||
return -1;
|
||||
|
||||
if (!getenv("DISPLAY"))
|
||||
LOG_ERROR("Getting Nvidia parameters requires DISPLAY to be set - will likely fail!\n");
|
||||
|
||||
long perf_level = get_max_perf_level_nv(info);
|
||||
|
||||
char arg[128] = { 0 };
|
||||
char buf[EXTERNAL_BUFFER_MAX] = { 0 };
|
||||
char *end;
|
||||
|
||||
if (info->nv_perf_level != -1) {
|
||||
/* Get the GPUGraphicsClockOffset parameter */
|
||||
snprintf(arg,
|
||||
128,
|
||||
NV_ATTRIBUTE_FORMAT NV_PERF_LEVEL_FORMAT,
|
||||
info->device,
|
||||
NV_CORE_OFFSET_ATTRIBUTE,
|
||||
info->nv_perf_level);
|
||||
const char *exec_args_core[] = { "/usr/bin/nvidia-settings", "-q", arg, "-t", NULL };
|
||||
if (run_external_process(exec_args_core, buf, -1) != 0) {
|
||||
LOG_ERROR("Failed to get %s!\n", arg);
|
||||
return -1;
|
||||
}
|
||||
/* Get the GPUGraphicsClockOffset parameter */
|
||||
snprintf(arg,
|
||||
128,
|
||||
NV_ATTRIBUTE_FORMAT NV_PERF_LEVEL_FORMAT,
|
||||
info->device,
|
||||
NV_CORE_OFFSET_ATTRIBUTE,
|
||||
perf_level);
|
||||
const char *exec_args_core[] = { "/usr/bin/nvidia-settings", "-q", arg, "-t", NULL };
|
||||
if (run_external_process(exec_args_core, buf, -1) != 0) {
|
||||
LOG_ERROR("Failed to get %s!\n", arg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
info->nv_core = strtol(buf, &end, 10);
|
||||
if (end == buf) {
|
||||
LOG_ERROR("Failed to parse output for \"%s\" output was \"%s\"!\n", arg, buf);
|
||||
return -1;
|
||||
}
|
||||
info->nv_core = strtol(buf, &end, 10);
|
||||
if (end == buf) {
|
||||
LOG_ERROR("Failed to parse output for \"%s\" output was \"%s\"!\n", arg, buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get the GPUMemoryTransferRateOffset parameter */
|
||||
snprintf(arg,
|
||||
128,
|
||||
NV_ATTRIBUTE_FORMAT NV_PERF_LEVEL_FORMAT,
|
||||
info->device,
|
||||
NV_MEM_OFFSET_ATTRIBUTE,
|
||||
info->nv_perf_level);
|
||||
const char *exec_args_mem[] = { "/usr/bin/nvidia-settings", "-q", arg, "-t", NULL };
|
||||
if (run_external_process(exec_args_mem, buf, -1) != 0) {
|
||||
LOG_ERROR("Failed to get %s!\n", arg);
|
||||
return -1;
|
||||
}
|
||||
/* Get the GPUMemoryTransferRateOffset parameter */
|
||||
snprintf(arg,
|
||||
128,
|
||||
NV_ATTRIBUTE_FORMAT NV_PERF_LEVEL_FORMAT,
|
||||
info->device,
|
||||
NV_MEM_OFFSET_ATTRIBUTE,
|
||||
perf_level);
|
||||
const char *exec_args_mem[] = { "/usr/bin/nvidia-settings", "-q", arg, "-t", NULL };
|
||||
if (run_external_process(exec_args_mem, buf, -1) != 0) {
|
||||
LOG_ERROR("Failed to get %s!\n", arg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
info->nv_mem = strtol(buf, &end, 10);
|
||||
if (end == buf) {
|
||||
LOG_ERROR("Failed to parse output for \"%s\" output was \"%s\"!\n", arg, buf);
|
||||
return -1;
|
||||
}
|
||||
info->nv_mem = strtol(buf, &end, 10);
|
||||
if (end == buf) {
|
||||
LOG_ERROR("Failed to parse output for \"%s\" output was \"%s\"!\n", arg, buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get the GPUPowerMizerMode parameter */
|
||||
@ -135,6 +214,8 @@ static int get_gpu_state_nv(struct GameModeGPUInfo *info)
|
||||
*/
|
||||
static int set_gpu_state_nv(struct GameModeGPUInfo *info)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
if (info->vendor != Vendor_NVIDIA)
|
||||
return -1;
|
||||
|
||||
@ -143,35 +224,39 @@ static int set_gpu_state_nv(struct GameModeGPUInfo *info)
|
||||
"Setting Nvidia parameters requires DISPLAY and XAUTHORITY to be set - will likely "
|
||||
"fail!\n");
|
||||
|
||||
long perf_level = get_max_perf_level_nv(info);
|
||||
|
||||
char arg[128] = { 0 };
|
||||
|
||||
if (info->nv_perf_level != -1) {
|
||||
/* Set the GPUGraphicsClockOffset parameter */
|
||||
/* Set the GPUGraphicsClockOffset parameter */
|
||||
if (info->nv_core != -1) {
|
||||
snprintf(arg,
|
||||
128,
|
||||
NV_ATTRIBUTE_FORMAT NV_PERF_LEVEL_FORMAT "=%ld",
|
||||
info->device,
|
||||
NV_CORE_OFFSET_ATTRIBUTE,
|
||||
info->nv_perf_level,
|
||||
perf_level,
|
||||
info->nv_core);
|
||||
const char *exec_args_core[] = { "/usr/bin/nvidia-settings", "-a", arg, NULL };
|
||||
if (run_external_process(exec_args_core, NULL, -1) != 0) {
|
||||
LOG_ERROR("Failed to set %s!\n", arg);
|
||||
return -1;
|
||||
status = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the GPUMemoryTransferRateOffset parameter */
|
||||
/* Set the GPUMemoryTransferRateOffset parameter */
|
||||
if (info->nv_mem != -1) {
|
||||
snprintf(arg,
|
||||
128,
|
||||
NV_ATTRIBUTE_FORMAT NV_PERF_LEVEL_FORMAT "=%ld",
|
||||
info->device,
|
||||
NV_MEM_OFFSET_ATTRIBUTE,
|
||||
info->nv_perf_level,
|
||||
perf_level,
|
||||
info->nv_mem);
|
||||
const char *exec_args_mem[] = { "/usr/bin/nvidia-settings", "-a", arg, NULL };
|
||||
if (run_external_process(exec_args_mem, NULL, -1) != 0) {
|
||||
LOG_ERROR("Failed to set %s!\n", arg);
|
||||
return -1;
|
||||
status = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,11 +271,11 @@ static int set_gpu_state_nv(struct GameModeGPUInfo *info)
|
||||
const char *exec_args_pm[] = { "/usr/bin/nvidia-settings", "-a", arg, NULL };
|
||||
if (run_external_process(exec_args_pm, NULL, -1) != 0) {
|
||||
LOG_ERROR("Failed to set %s!\n", arg);
|
||||
return -1;
|
||||
status = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -284,18 +369,6 @@ static int set_gpu_state_amd(struct GameModeGPUInfo *info)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Helper to get and verify vendor value */
|
||||
static long get_vendor(const char *val)
|
||||
{
|
||||
char *end;
|
||||
long ret = strtol(val, &end, 0);
|
||||
if (!GPUVendorValid(ret) || end == val) {
|
||||
LOG_ERROR("Invalid GPU Vendor passed (0x%04x)!\n", (unsigned short)ret);
|
||||
print_usage_and_exit();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Helper to get and verify device value */
|
||||
static long get_device(const char *val)
|
||||
{
|
||||
@ -325,20 +398,21 @@ static long get_generic_value(const char *val)
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc >= 4 && strncmp(argv[3], "get", 3) == 0) {
|
||||
if (argc == 3 && strncmp(argv[2], "get", 3) == 0) {
|
||||
/* Get and verify the vendor and device */
|
||||
struct GameModeGPUInfo info;
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.vendor = get_vendor(argv[1]);
|
||||
info.device = get_device(argv[2]);
|
||||
info.device = get_device(argv[1]);
|
||||
info.vendor = gamemode_get_gpu_vendor(info.device);
|
||||
|
||||
/* Adjust the device number to the gpu index for Nvidia */
|
||||
if (info.vendor == Vendor_NVIDIA)
|
||||
info.device = get_gpu_index_id_nv(&info);
|
||||
|
||||
/* Fetch the state and print it out */
|
||||
switch (info.vendor) {
|
||||
case Vendor_NVIDIA:
|
||||
info.nv_perf_level = -1;
|
||||
if (argc > 4)
|
||||
info.nv_perf_level = get_generic_value(argv[4]);
|
||||
/* Get nvidia power level */
|
||||
|
||||
if (get_gpu_state_nv(&info) != 0)
|
||||
exit(EXIT_FAILURE);
|
||||
printf("%ld %ld %ld\n", info.nv_core, info.nv_mem, info.nv_powermizer_mode);
|
||||
@ -349,49 +423,49 @@ int main(int argc, char *argv[])
|
||||
printf("%s\n", info.amd_performance_level);
|
||||
break;
|
||||
default:
|
||||
printf("Currently unsupported GPU vendor 0x%04x, doing nothing!\n", (short)info.vendor);
|
||||
LOG_ERROR("Currently unsupported GPU vendor 0x%04x, doing nothing!\n",
|
||||
(short)info.vendor);
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (argc >= 5 && argc <= 8 && strncmp(argv[3], "set", 3) == 0) {
|
||||
} else if (argc >= 4 && argc <= 7 && strncmp(argv[2], "set", 3) == 0) {
|
||||
/* Get and verify the vendor and device */
|
||||
struct GameModeGPUInfo info;
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.vendor = get_vendor(argv[1]);
|
||||
info.device = get_device(argv[2]);
|
||||
info.device = get_device(argv[1]);
|
||||
info.vendor = gamemode_get_gpu_vendor(info.device);
|
||||
|
||||
switch (info.vendor) {
|
||||
case Vendor_NVIDIA:
|
||||
info.nv_core = get_generic_value(argv[4]);
|
||||
info.nv_mem = get_generic_value(argv[5]);
|
||||
info.nv_perf_level = -1;
|
||||
if (argc > 6)
|
||||
info.nv_perf_level = get_generic_value(argv[6]);
|
||||
if (argc < 4) {
|
||||
LOG_ERROR("Must pass at least 4 arguments for nvidia gpu!\n");
|
||||
print_usage_and_exit();
|
||||
}
|
||||
info.nv_core = get_generic_value(argv[3]);
|
||||
info.nv_mem = get_generic_value(argv[4]);
|
||||
|
||||
/* Optional */
|
||||
info.nv_powermizer_mode = -1;
|
||||
if (argc > 7)
|
||||
info.nv_powermizer_mode = get_generic_value(argv[7]);
|
||||
break;
|
||||
case Vendor_AMD:
|
||||
strncpy(info.amd_performance_level, argv[4], CONFIG_VALUE_MAX);
|
||||
break;
|
||||
default:
|
||||
printf("Currently unsupported GPU vendor 0x%04x, doing nothing!\n", (short)info.vendor);
|
||||
break;
|
||||
}
|
||||
if (argc >= 6)
|
||||
info.nv_powermizer_mode = get_generic_value(argv[5]);
|
||||
|
||||
printf("gpuclockctl setting values on device:%ld with vendor 0x%04x",
|
||||
info.device,
|
||||
(unsigned short)info.vendor);
|
||||
|
||||
switch (info.vendor) {
|
||||
case Vendor_NVIDIA:
|
||||
return set_gpu_state_nv(&info);
|
||||
break;
|
||||
case Vendor_AMD:
|
||||
if (argc < 3) {
|
||||
LOG_ERROR("Must pass performance level for AMD gpu!\n");
|
||||
print_usage_and_exit();
|
||||
}
|
||||
strncpy(info.amd_performance_level, argv[3], CONFIG_VALUE_MAX);
|
||||
return set_gpu_state_amd(&info);
|
||||
break;
|
||||
default:
|
||||
printf("Currently unsupported GPU vendor 0x%04x, doing nothing!\n", (short)info.vendor);
|
||||
LOG_ERROR("Currently unsupported GPU vendor 0x%04x, doing nothing!\n",
|
||||
(short)info.vendor);
|
||||
print_usage_and_exit();
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
print_usage_and_exit();
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ common_sources = [
|
||||
'logging.c',
|
||||
'governors-query.c',
|
||||
'external-helper.c',
|
||||
'gpu-control.c',
|
||||
]
|
||||
|
||||
daemon_common = static_library(
|
||||
|
@ -49,12 +49,12 @@ inhibit_screensaver=1
|
||||
; Nvidia specific settings
|
||||
; Requires the coolbits extension activated in nvidia-xconfig
|
||||
; This corresponds to the desired GPUPowerMizerMode
|
||||
; Generally "Adaptive"=0 "Prefer Maximum Performance"=1 and "Auto"=2)
|
||||
; "Adaptive"=0 "Prefer Maximum Performance"=1 and "Auto"=2
|
||||
; See NV_CTRL_GPU_POWER_MIZER_MODE and friends in https://github.com/NVIDIA/nvidia-settings/blob/master/src/libXNVCtrl/NVCtrl.h
|
||||
;nv_powermizer_mode=1
|
||||
|
||||
; This corresponds to the performance level to edit in nvidia-xconfig (usually the highest level - on older cards 1, newer cards can be 4 or higher)
|
||||
;nv_perf_level=1
|
||||
; (these two are Mhz offsets from the baseline, ie. 0 applies no change)
|
||||
; These will modify the core and mem clocks of the highest perf state in the Nvidia PowerMizer
|
||||
; They are measured as Mhz offsets from the baseline, 0 will reset values to default, -1 or unset will not modify values
|
||||
;nv_core_clock_mhz_offset=0
|
||||
;nv_mem_clock_mhz_offset=0
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user