diff --git a/daemon/gamemode-gpu.c b/daemon/gamemode-gpu.c index 5bf86c9..386666f 100644 --- a/daemon/gamemode-gpu.c +++ b/daemon/gamemode-gpu.c @@ -37,69 +37,16 @@ POSSIBILITY OF SUCH DAMAGE. #include "logging.h" #include "daemon_config.h" +#include "gpu-query.h" // TODO // Gather GPU type and information -// Allow configuration file specifying of gpu info +// Allow override of vendor and device // Apply Nvidia GPU settings (CoolBits will be needed) // Apply AMD GPU settings (Will need user changing pwm1_enable) // Intel? // Provide documentation on optimisations -/* Enums for GPU vendors */ -enum GPUVendor { - Vendor_Invalid = 0, - Vendor_NVIDIA = 0x10de, - Vendor_AMD = 0x1002, - Vendor_Intel = 0x8086 -}; - -/* Storage for static GPU info gathered at start */ -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(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' - if (apply) { - } else { - } - - return 0; -} - -/** - * Applies or removes AMD optimisations - */ -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) - // Guide from https://www.maketecheasier.com/overclock-amd-gpu-linux/ - if (apply) { - } else { - } - - return 0; -} - /** * Attempts to identify the current in use GPU information */ @@ -121,7 +68,7 @@ int game_mode_initialise_gpu(GameModeConfig *config, GameModeGPUInfo **info) GameModeGPUInfo *new_info = malloc(sizeof(GameModeGPUInfo)); memset(new_info, 0, sizeof(GameModeGPUInfo)); - // TODO: Fill in the GPU info + // TODO: Fill in the GPU vendor and device /* Load the config based on GPU */ switch (new_info->vendor) { @@ -160,15 +107,7 @@ int game_mode_apply_gpu(const GameModeGPUInfo *info, bool apply) if (!info) return 0; - switch (info->vendor) { - case Vendor_NVIDIA: - return apply_gpu_nvidia(info, apply); - case Vendor_AMD: - return apply_gpu_amd(info, apply); - default: - break; - } + /* TODO Call gpuclockctl set */ - /* Unsupported GPU vendor, do nothing */ return 0; } diff --git a/daemon/gpu-query.c b/daemon/gpu-query.c new file mode 100644 index 0000000..7bf515c --- /dev/null +++ b/daemon/gpu-query.c @@ -0,0 +1,64 @@ +/* + +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. + + */ + +#define _GNU_SOURCE + +#include "gpu-query.h" +#include "logging.h" + +// NVIDIA +// Running these commands: +// nvidia-settings -a '[gpu:0]/GPUMemoryTransferRateOffset[3]=1400' +// nvidia-settings -a '[gpu:0]/GPUGraphicsClockOffset[3]=50' + +// AMD +// We'll want to set both the following: +// core: device/pp_sclk_od (0%+ additional) +// mem: device/pp_mclk_od (0%+ additional) +// Guide from https://www.maketecheasier.com/overclock-amd-gpu-linux/ + +/** + * Get the gpu state + * Populates the struct with the GPU info on the system + */ +int get_gpu_state( struct GameModeGPUInfo* info ) +{ + return 0; +} + +/** + * Set the gpu state based on input parameters + * Only works when run as root + */ +int set_gpu_state( struct GameModeGPUInfo* info ) +{ + return 0; +} diff --git a/daemon/gpu-query.h b/daemon/gpu-query.h new file mode 100644 index 0000000..cab5214 --- /dev/null +++ b/daemon/gpu-query.h @@ -0,0 +1,61 @@ +/* + +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. + + */ + +#pragma once + +/* Enums for GPU vendors */ +enum GPUVendor { + Vendor_Invalid = 0, + Vendor_NVIDIA = 0x10de, + Vendor_AMD = 0x1002, + Vendor_Intel = 0x8086 +}; + +/* Storage for GPU info*/ +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 */ +}; + +/** + * Get the gpu state + * Populates the struct with the GPU info on the system + */ +int get_gpu_state( struct GameModeGPUInfo* info ); + +/** + * Set the gpu state based on input parameters + * Only works when run as root + */ +int set_gpu_state( struct GameModeGPUInfo* info ); diff --git a/daemon/gpuclockctl.c b/daemon/gpuclockctl.c new file mode 100644 index 0000000..f954815 --- /dev/null +++ b/daemon/gpuclockctl.c @@ -0,0 +1,76 @@ +/* + +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. + + */ + +#define _GNU_SOURCE + +#include "logging.h" + +#include "gpu-query.h" + +/** + * Main entry point, dispatch to the appropriate helper + */ +int main(int argc, char *argv[]) +{ + if (argc == 4 && strncmp(argv[1], "get", 3) == 0) { + const char *vendor = argv[1]; + const char *device = argv[2]; + + struct GameModeGPUInfo info; + /* TODO Populate with vendor and device */ + + get_gpu_state(&info); + + printf("%d %d\n", info.core, info.mem); + + } else if (argc == 6 && strncmp(argv[3], "set", 3) == 0) { + const char *vendor = argv[1]; + const char *device = argv[2]; + const char *core = argv[4]; + const char *mem = argv[5]; + + /* Must be root to set the state */ + if (geteuid() != 0) { + fprintf(stderr, "This program must be run as root\n"); + return EXIT_FAILURE; + } + + struct GameModeGPUInfo info; + /* TODO Populate with vendor, device and clocks */ + + return set_gpu_state(&info); + } else { + fprintf(stderr, "usage: gpuclockctl PCI_ID DEVICE [get] [set CORE MEM]\n"); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/daemon/meson.build b/daemon/meson.build index f5b054a..9b79453 100644 --- a/daemon/meson.build +++ b/daemon/meson.build @@ -2,6 +2,7 @@ common_sources = [ 'logging.c', 'governors-query.c', + 'gpu-query.c', ] daemon_common = static_library( @@ -62,3 +63,18 @@ cpugovctl = executable( install: true, install_dir: path_libexecdir, ) + +# Small target util to get and set gpu clocks values +gpuclockctl_sources = [ + 'gpuclockctl.c', +] + +gpuclockctl = executable( + 'gpuclockctl', + sources: gpuclockctl_sources, + dependencies: [ + link_daemon_common, + ], + install: true, + install_dir: path_libexecdir, +) diff --git a/data/com.feralinteractive.GameMode.policy.in b/data/com.feralinteractive.GameMode.policy.in index 8165162..b0dce0d 100644 --- a/data/com.feralinteractive.GameMode.policy.in +++ b/data/com.feralinteractive.GameMode.policy.in @@ -23,4 +23,15 @@ @LIBEXECDIR@/cpugovctl + + Modify the GPU clock statesr + Authentication is required to modify the GPU clock states + + no + no + yes + + @LIBEXECDIR@/gpuclockctl + +