Merge pull request #112 from mdiluz/automatic-gpu-info

Clean up NV optimization config
This commit is contained in:
Alex Smith 2019-03-11 17:14:41 +00:00 committed by GitHub
commit 0c08359005
9 changed files with 256 additions and 158 deletions

View File

@ -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])

View File

@ -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]);

View File

@ -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,
};

View File

@ -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
View 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;
}

View File

@ -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);

View File

@ -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();
}

View File

@ -3,6 +3,7 @@ common_sources = [
'logging.c',
'governors-query.c',
'external-helper.c',
'gpu-control.c',
]
daemon_common = static_library(

View File

@ -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