diff --git a/README.md b/README.md index ad937b3..9e2a789 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,6 @@ There are also additional dependencies needed at runtime depending on your GPU v * cuda runtime (libcuda.so.1) (libnvidia-compute) * nvenc (libnvidia-encode) * nvfbc (libnvidia-fbc1, when recording the screen on x11) -* xnvctrl (libxnvctrl0, when using the `-oc` option) # How to use Run `gpu-screen-recorder --help` to see all options and run `man gpu-screen-recorder` to see more detailed explanations for the options and also examples.\ diff --git a/gpu-screen-recorder.1 b/gpu-screen-recorder.1 index 075daf6..c69dc0f 100644 --- a/gpu-screen-recorder.1 +++ b/gpu-screen-recorder.1 @@ -329,9 +329,6 @@ Clear buffer after saving replay (default: no). Organize replays in date-based folders (default: no). .SS Advanced Options .TP -.BI \-oc " yes|no" -Overclock NVIDIA memory (X11 only). Requires Coolbits=12. Use at own risk. -.TP .BI \-p " plugin.so" Load plugin (.so file). Can be specified multiple times. .TP diff --git a/include/args_parser.h b/include/args_parser.h index 98fb30c..75d8bfa 100644 --- a/include/args_parser.h +++ b/include/args_parser.h @@ -97,7 +97,6 @@ typedef struct { bool date_folders; bool restore_portal_session; bool restart_replay_on_save; - bool overclock; bool write_first_frame_ts; bool is_livestream; bool is_output_piped; diff --git a/include/cuda.h b/include/cuda.h index fd1f9f9..fb47b12 100644 --- a/include/cuda.h +++ b/include/cuda.h @@ -1,7 +1,6 @@ #ifndef GSR_CUDA_H #define GSR_CUDA_H -#include "overclock.h" #include #include @@ -75,9 +74,6 @@ typedef struct CUgraphicsResource_st *CUgraphicsResource; typedef struct gsr_cuda gsr_cuda; struct gsr_cuda { - gsr_overclock overclock; - bool do_overclock; - void *library; CUcontext cu_ctx; @@ -102,7 +98,7 @@ struct gsr_cuda { CUresult (*cuGraphicsSubResourceGetMappedArray)(CUarray *pArray, CUgraphicsResource resource, unsigned int arrayIndex, unsigned int mipLevel); }; -bool gsr_cuda_load(gsr_cuda *self, Display *display, bool overclock); +bool gsr_cuda_load(gsr_cuda *self); void gsr_cuda_unload(gsr_cuda *self); #endif /* GSR_CUDA_H */ diff --git a/include/encoder/video/nvenc.h b/include/encoder/video/nvenc.h index d4a906b..f6af2fc 100644 --- a/include/encoder/video/nvenc.h +++ b/include/encoder/video/nvenc.h @@ -7,7 +7,6 @@ typedef struct gsr_egl gsr_egl; typedef struct { gsr_egl *egl; - bool overclock; gsr_color_depth color_depth; } gsr_video_encoder_nvenc_params; diff --git a/include/overclock.h b/include/overclock.h deleted file mode 100644 index d6ff901..0000000 --- a/include/overclock.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef GSR_OVERCLOCK_H -#define GSR_OVERCLOCK_H - -#include "xnvctrl.h" - -typedef struct { - gsr_xnvctrl xnvctrl; - int num_performance_levels; -} gsr_overclock; - -bool gsr_overclock_load(gsr_overclock *self, Display *display); -void gsr_overclock_unload(gsr_overclock *self); - -bool gsr_overclock_start(gsr_overclock *self); -void gsr_overclock_stop(gsr_overclock *self); - -#endif /* GSR_OVERCLOCK_H */ diff --git a/include/xnvctrl.h b/include/xnvctrl.h deleted file mode 100644 index 33fc442..0000000 --- a/include/xnvctrl.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef GSR_XNVCTRL_H -#define GSR_XNVCTRL_H - -#include -#include - -#define NV_CTRL_GPU_NVCLOCK_OFFSET 409 -#define NV_CTRL_GPU_MEM_TRANSFER_RATE_OFFSET 410 -#define NV_CTRL_GPU_NVCLOCK_OFFSET_ALL_PERFORMANCE_LEVELS 424 -#define NV_CTRL_GPU_MEM_TRANSFER_RATE_OFFSET_ALL_PERFORMANCE_LEVELS 425 - -#define NV_CTRL_TARGET_TYPE_GPU 1 - -#define NV_CTRL_STRING_PERFORMANCE_MODES 29 - -typedef struct _XDisplay Display; - -typedef struct { - int type; - union { - struct { - int64_t min; - int64_t max; - } range; - struct { - unsigned int ints; - } bits; - } u; - unsigned int permissions; -} NVCTRLAttributeValidValuesRec; - -typedef struct { - Display *display; - void *library; - - int (*XNVCTRLQueryExtension)(Display *dpy, int *event_basep, int *error_basep); - int (*XNVCTRLSetTargetAttributeAndGetStatus)(Display *dpy, int target_type, int target_id, unsigned int display_mask, unsigned int attribute, int value); - int (*XNVCTRLQueryValidTargetAttributeValues)(Display *dpy, int target_type, int target_id, unsigned int display_mask, unsigned int attribute, NVCTRLAttributeValidValuesRec *values); - int (*XNVCTRLQueryTargetStringAttribute)(Display *dpy, int target_type, int target_id, unsigned int display_mask, unsigned int attribute, char **ptr); -} gsr_xnvctrl; - -bool gsr_xnvctrl_load(gsr_xnvctrl *self, Display *display); -void gsr_xnvctrl_unload(gsr_xnvctrl *self); - -#endif /* GSR_XNVCTRL_H */ diff --git a/meson.build b/meson.build index 3f3bc3f..da08c26 100644 --- a/meson.build +++ b/meson.build @@ -32,8 +32,6 @@ src = [ 'src/replay_buffer/replay_buffer_disk.c', 'src/egl.c', 'src/cuda.c', - 'src/xnvctrl.c', - 'src/overclock.c', 'src/window_texture.c', 'src/shader.c', 'src/color_conversion.c', diff --git a/src/args_parser.c b/src/args_parser.c index a785172..eddbb6f 100644 --- a/src/args_parser.c +++ b/src/args_parser.c @@ -199,7 +199,7 @@ static void usage_header(void) { const char *program_name = inside_flatpak ? "flatpak run --command=gpu-screen-recorder com.dec05eba.gpu_screen_recorder" : "gpu-screen-recorder"; printf("usage: %s -w [-c ] [-s WxH] [-region WxH+X+Y] [-f ] [-a ] " "[-q ] [-r ] [-replay-storage ram|disk] [-restart-replay-on-save yes|no] " - "[-k h264|hevc|av1|vp8|vp9|hevc_hdr|av1_hdr|hevc_10bit|av1_10bit] [-ac aac|opus|flac] [-ab ] [-oc yes|no] [-fm cfr|vfr|content] " + "[-k h264|hevc|av1|vp8|vp9|hevc_hdr|av1_hdr|hevc_10bit|av1_10bit] [-ac aac|opus|flac] [-ab ] [-fm cfr|vfr|content] " "[-bm auto|qp|vbr|cbr] [-cr limited|full] [-tune performance|quality] [-df yes|no] [-sc ] [-p ] " "[-cursor yes|no] [-keyint ] [-restore-portal-session yes|no] [-portal-session-token-filepath filepath] [-encoder gpu|cpu] " "[-fallback-cpu-encoding yes|no] [-o ] [-ro ] [-ffmpeg-opts ] [--list-capture-options [card_path]] " @@ -261,7 +261,7 @@ static bool args_parser_set_values(args_parser *self) { self->date_folders = args_get_boolean_by_key(self->args, NUM_ARGS, "-df", false); self->restore_portal_session = args_get_boolean_by_key(self->args, NUM_ARGS, "-restore-portal-session", false); self->restart_replay_on_save = args_get_boolean_by_key(self->args, NUM_ARGS, "-restart-replay-on-save", false); - self->overclock = args_get_boolean_by_key(self->args, NUM_ARGS, "-oc", false); + const bool overclock = args_get_boolean_by_key(self->args, NUM_ARGS, "-oc", false); self->fallback_cpu_encoding = args_get_boolean_by_key(self->args, NUM_ARGS, "-fallback-cpu-encoding", false); self->write_first_frame_ts = args_get_boolean_by_key(self->args, NUM_ARGS, "-write-first-frame-ts", false); self->low_power = args_get_boolean_by_key(self->args, NUM_ARGS, "-low-power", false); @@ -271,6 +271,10 @@ static bool args_parser_set_values(args_parser *self) { self->keyint = args_get_double_by_key(self->args, NUM_ARGS, "-keyint", 2.0); + if(overclock) { + fprintf(stderr, "gsr info: the overclock option (-oc) is deprecated and no longer has any effect as it's no longer needed (on GPUs that are 12 years old or younger)\n"); + } + if(self->audio_codec == GSR_AUDIO_CODEC_FLAC) { fprintf(stderr, "gsr warning: flac audio codec is temporary disabled, using opus audio codec instead\n"); self->audio_codec = GSR_AUDIO_CODEC_OPUS; @@ -690,16 +694,6 @@ bool args_parser_validate_with_gl_info(args_parser *self, gsr_egl *egl) { self->bitrate_mode = GSR_BITRATE_MODE_QP; } - if(egl->gpu_info.vendor != GSR_GPU_VENDOR_NVIDIA && self->overclock) { - fprintf(stderr, "gsr info: overclock option has no effect on amd/intel, ignoring option\n"); - self->overclock = false; - } - - if(egl->gpu_info.vendor == GSR_GPU_VENDOR_NVIDIA && self->overclock && wayland) { - fprintf(stderr, "gsr info: overclocking is not possible on nvidia on wayland, ignoring option\n"); - self->overclock = false; - } - if(egl->gpu_info.is_steam_deck) { fprintf(stderr, "gsr warning: steam deck has multiple driver issues. One of them has been reported here: https://github.com/ValveSoftware/SteamOS/issues/1609\n" "If you have issues with GPU Screen Recorder on steam deck that you don't have on a desktop computer then report the issue to Valve and/or AMD.\n"); diff --git a/src/codec_query/nvenc.c b/src/codec_query/nvenc.c index 5e52807..37c25ba 100644 --- a/src/codec_query/nvenc.c +++ b/src/codec_query/nvenc.c @@ -197,7 +197,7 @@ bool gsr_get_supported_video_codecs_nvenc(gsr_supported_video_codecs *video_code gsr_cuda cuda; memset(&cuda, 0, sizeof(cuda)); - if(!gsr_cuda_load(&cuda, NULL, false)) { + if(!gsr_cuda_load(&cuda)) { fprintf(stderr, "gsr error: gsr_get_supported_video_codecs_nvenc: failed to load cuda\n"); goto done; } diff --git a/src/cuda.c b/src/cuda.c index 00683cf..bfafbcd 100644 --- a/src/cuda.c +++ b/src/cuda.c @@ -5,9 +5,8 @@ #include #include -bool gsr_cuda_load(gsr_cuda *self, Display *display, bool do_overclock) { +bool gsr_cuda_load(gsr_cuda *self) { memset(self, 0, sizeof(gsr_cuda)); - self->do_overclock = do_overclock; dlerror(); /* clear */ void *lib = dlopen("libcuda.so.1", RTLD_LAZY); @@ -83,15 +82,6 @@ bool gsr_cuda_load(gsr_cuda *self, Display *display, bool do_overclock) { goto fail; } - if(self->do_overclock && display) { - if(gsr_overclock_load(&self->overclock, display)) - gsr_overclock_start(&self->overclock); - else - fprintf(stderr, "gsr warning: gsr_cuda_load: failed to load xnvctrl, failed to overclock memory transfer rate\n"); - } else if(self->do_overclock && !display) { - fprintf(stderr, "gsr warning: gsr_cuda_load: overclocking enabled but no X server is running. Overclocking has been disabled\n"); - } - self->library = lib; return true; @@ -102,11 +92,6 @@ bool gsr_cuda_load(gsr_cuda *self, Display *display, bool do_overclock) { } void gsr_cuda_unload(gsr_cuda *self) { - if(self->do_overclock && self->overclock.xnvctrl.library) { - gsr_overclock_stop(&self->overclock); - gsr_overclock_unload(&self->overclock); - } - if(self->library) { if(self->cu_ctx) { self->cuCtxDestroy_v2(self->cu_ctx); diff --git a/src/encoder/video/nvenc.c b/src/encoder/video/nvenc.c index 0318a17..dd877c5 100644 --- a/src/encoder/video/nvenc.c +++ b/src/encoder/video/nvenc.c @@ -1,7 +1,7 @@ #include "../../../include/encoder/video/nvenc.h" #include "../../../include/egl.h" #include "../../../include/cuda.h" -#include "../../../include/window/window.h" +#include "../../../include/utils.h" #include #include @@ -116,10 +116,7 @@ static void gsr_video_encoder_nvenc_stop(gsr_video_encoder_nvenc *self, AVCodecC static bool gsr_video_encoder_nvenc_start(gsr_video_encoder *encoder, AVCodecContext *video_codec_context, AVFrame *frame) { gsr_video_encoder_nvenc *self = encoder->priv; - const bool is_x11 = gsr_window_get_display_server(self->params.egl->window) == GSR_DISPLAY_SERVER_X11; - const bool overclock = is_x11 ? self->params.overclock : false; - Display *display = is_x11 ? gsr_window_get_display(self->params.egl->window) : NULL; - if(!gsr_cuda_load(&self->cuda, display, overclock)) { + if(!gsr_cuda_load(&self->cuda)) { fprintf(stderr, "gsr error: gsr_video_encoder_nvenc_start: failed to load cuda\n"); gsr_video_encoder_nvenc_stop(self, video_codec_context); return false; diff --git a/src/main.cpp b/src/main.cpp index 9abc6be..b6471eb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1551,7 +1551,6 @@ static gsr_video_encoder* create_video_encoder(gsr_egl *egl, const args_parser & case GSR_GPU_VENDOR_NVIDIA: { gsr_video_encoder_nvenc_params params; params.egl = egl; - params.overclock = arg_parser.overclock; params.color_depth = color_depth; video_encoder = gsr_video_encoder_nvenc_create(¶ms); break; @@ -3571,6 +3570,10 @@ static void validate_args_with_capture_sources(args_parser &arg_parser, const st fprintf(stderr, "gsr info: option '-w portal' was used without '-restore-portal-session yes'. The previous screencast session will be ignored\n"); } +static void install_cuda_no_stable_perf_limit() { + +} + int main(int argc, char **argv) { setlocale(LC_ALL, "C"); // Sigh... stupid C #ifdef __GLIBC__ @@ -3645,21 +3648,6 @@ int main(int argc, char **argv) { } validate_args_with_capture_sources(arg_parser, capture_sources); - // TODO: Remove, this isn't true - if(arg_parser.overclock) { - int driver_major_version = 0; - int driver_minor_version = 0; - if(get_nvidia_driver_version(&driver_major_version, &driver_minor_version) && (driver_major_version > 580 || (driver_major_version == 580 && driver_minor_version >= 105))) { - fprintf(stderr, "gsr info: overclocking was set but has been forcefully disabled since your gpu supports CUDA_DISABLE_PERF_BOOST to workaround driver issue (overclocking is not needed)\n"); - arg_parser.overclock = false; - } - } - - if(arg_parser.overclock && video_codec_is_vulkan(arg_parser.video_codec)) { - fprintf(stderr, "gsr info: overclocking was set but has been forcefully disabled since you're using vulkan video encoder which doesn't suffer from cuda p2 power level issues\n"); - arg_parser.overclock = false; - } - //av_log_set_level(AV_LOG_TRACE); const Arg *audio_input_arg = args_parser_get_arg(&arg_parser, "-a"); diff --git a/src/overclock.c b/src/overclock.c deleted file mode 100644 index f9375d5..0000000 --- a/src/overclock.c +++ /dev/null @@ -1,279 +0,0 @@ -#include "../include/overclock.h" -#include -#include -#include -#include - -// HACK!!!: When a program uses cuda (including nvenc) then the nvidia driver drops to max performance level - 1 (memory transfer rate is dropped and possibly graphics clock). -// Nvidia does this because in some very extreme cases of cuda there can be memory corruption when running at max memory transfer rate. -// So to get around this we overclock memory transfer rate (maybe this should also be done for graphics clock?) to the best performance level while GPU Screen Recorder is running. - -static int min_int(int a, int b) { - return a < b ? a : b; -} - -// Fields are 0 if not set -typedef struct { - int perf; - - int nv_clock; - int nv_clock_min; - int nv_clock_max; - - int mem_clock; - int mem_clock_min; - int mem_clock_max; - - int mem_transfer_rate; - int mem_transfer_rate_min; - int mem_transfer_rate_max; -} NVCTRLPerformanceLevel; - -#define MAX_PERFORMANCE_LEVELS 12 -typedef struct { - NVCTRLPerformanceLevel performance_level[MAX_PERFORMANCE_LEVELS]; - int num_performance_levels; -} NVCTRLPerformanceLevelQuery; - -typedef void (*split_callback)(const char *str, size_t size, void *userdata); -static void split_by_delimiter(const char *str, size_t size, char delimiter, split_callback callback, void *userdata) { - const char *it = str; - while(it < str + size) { - const char *prev_it = it; - it = memchr(it, delimiter, (str + size) - it); - if(!it) - it = str + size; - - callback(prev_it, it - prev_it, userdata); - it += 1; // skip delimiter - } -} - -typedef enum { - NVCTRL_GPU_NVCLOCK, - NVCTRL_ATTRIB_GPU_MEM_TRANSFER_RATE, -} NvCTRLAttributeType; - -static unsigned int attribute_type_to_attribute_param(NvCTRLAttributeType attribute_type) { - switch(attribute_type) { - case NVCTRL_GPU_NVCLOCK: - return NV_CTRL_GPU_NVCLOCK_OFFSET; - case NVCTRL_ATTRIB_GPU_MEM_TRANSFER_RATE: - return NV_CTRL_GPU_MEM_TRANSFER_RATE_OFFSET; - } - return 0; -} - -static unsigned int attribute_type_to_attribute_param_all_levels(NvCTRLAttributeType attribute_type) { - switch(attribute_type) { - case NVCTRL_GPU_NVCLOCK: - return NV_CTRL_GPU_NVCLOCK_OFFSET_ALL_PERFORMANCE_LEVELS; - case NVCTRL_ATTRIB_GPU_MEM_TRANSFER_RATE: - return NV_CTRL_GPU_MEM_TRANSFER_RATE_OFFSET_ALL_PERFORMANCE_LEVELS; - } - return 0; -} - -// Returns 0 on error -static int xnvctrl_get_attribute_max_value(gsr_xnvctrl *xnvctrl, int num_performance_levels, NvCTRLAttributeType attribute_type) { - NVCTRLAttributeValidValuesRec valid; - if(xnvctrl->XNVCTRLQueryValidTargetAttributeValues(xnvctrl->display, NV_CTRL_TARGET_TYPE_GPU, 0, 0, attribute_type_to_attribute_param_all_levels(attribute_type), &valid)) { - return valid.u.range.max; - } - - if(num_performance_levels > 0 && xnvctrl->XNVCTRLQueryValidTargetAttributeValues(xnvctrl->display, NV_CTRL_TARGET_TYPE_GPU, 0, num_performance_levels - 1, attribute_type_to_attribute_param(attribute_type), &valid)) { - return valid.u.range.max; - } - - return 0; -} - -static bool xnvctrl_set_attribute_offset(gsr_xnvctrl *xnvctrl, int num_performance_levels, int offset, NvCTRLAttributeType attribute_type) { - bool success = false; - - // NV_CTRL_GPU_MEM_TRANSFER_RATE_OFFSET_ALL_PERFORMANCE_LEVELS works (or at least used to?) without Xorg running as root - // so we try that first. NV_CTRL_GPU_MEM_TRANSFER_RATE_OFFSET_ALL_PERFORMANCE_LEVELS also only works with GTX 1000+. - // TODO: Reverse engineer NVIDIA Xorg driver so we can set this always without root access. - if(xnvctrl->XNVCTRLSetTargetAttributeAndGetStatus(xnvctrl->display, NV_CTRL_TARGET_TYPE_GPU, 0, 0, attribute_type_to_attribute_param_all_levels(attribute_type), offset)) - success = true; - - for(int i = 0; i < num_performance_levels; ++i) { - success |= xnvctrl->XNVCTRLSetTargetAttributeAndGetStatus(xnvctrl->display, NV_CTRL_TARGET_TYPE_GPU, 0, i, attribute_type_to_attribute_param(attribute_type), offset); - } - - return success; -} - -static void strip(const char **str, int *size) { - const char *str_d = *str; - int s_d = *size; - - const char *start = str_d; - const char *end = start + s_d; - - while(str_d < end) { - char c = *str_d; - if(c != ' ' && c != '\t' && c != '\n') - break; - ++str_d; - } - - int start_offset = str_d - start; - while(s_d > start_offset) { - char c = start[s_d]; - if(c != ' ' && c != '\t' && c != '\n') - break; - --s_d; - } - - *str = str_d; - *size = s_d; -} - -static void attribute_callback(const char *str, size_t size, void *userdata) { - if(size > 255 - 1) - return; - - int size_i = size; - strip(&str, &size_i); - - char attribute[255]; - memcpy(attribute, str, size_i); - attribute[size_i] = '\0'; - - const char *sep = strchr(attribute, '='); - if(!sep) - return; - - const char *attribute_name = attribute; - size_t attribute_name_len = sep - attribute_name; - const char *attribute_value_str = sep + 1; - - int attribute_value = 0; - if(sscanf(attribute_value_str, "%d", &attribute_value) != 1) - return; - - NVCTRLPerformanceLevel *performance_level = userdata; - if(attribute_name_len == 4 && memcmp(attribute_name, "perf", 4) == 0) - performance_level->perf = attribute_value; - else if(attribute_name_len == 7 && memcmp(attribute_name, "nvclock", 7) == 0) - performance_level->nv_clock = attribute_value; - else if(attribute_name_len == 10 && memcmp(attribute_name, "nvclockmin", 10) == 0) - performance_level->nv_clock_min = attribute_value; - else if(attribute_name_len == 10 && memcmp(attribute_name, "nvclockmax", 10) == 0) - performance_level->nv_clock_max = attribute_value; - else if(attribute_name_len == 8 && memcmp(attribute_name, "memclock", 8) == 0) - performance_level->mem_clock = attribute_value; - else if(attribute_name_len == 11 && memcmp(attribute_name, "memclockmin", 11) == 0) - performance_level->mem_clock_min = attribute_value; - else if(attribute_name_len == 11 && memcmp(attribute_name, "memclockmax", 11) == 0) - performance_level->mem_clock_max = attribute_value; - else if(attribute_name_len == 15 && memcmp(attribute_name, "memTransferRate", 15) == 0) - performance_level->mem_transfer_rate = attribute_value; - else if(attribute_name_len == 18 && memcmp(attribute_name, "memTransferRatemin", 18) == 0) - performance_level->mem_transfer_rate_min = attribute_value; - else if(attribute_name_len == 18 && memcmp(attribute_name, "memTransferRatemax", 18) == 0) - performance_level->mem_transfer_rate_max = attribute_value; -} - -static void attribute_line_callback(const char *str, size_t size, void *userdata) { - NVCTRLPerformanceLevelQuery *query = userdata; - if(query->num_performance_levels >= MAX_PERFORMANCE_LEVELS) - return; - - NVCTRLPerformanceLevel *current_performance_level = &query->performance_level[query->num_performance_levels]; - memset(current_performance_level, 0, sizeof(NVCTRLPerformanceLevel)); - ++query->num_performance_levels; - split_by_delimiter(str, size, ',', attribute_callback, current_performance_level); -} - -static bool xnvctrl_get_performance_levels(gsr_xnvctrl *xnvctrl, NVCTRLPerformanceLevelQuery *query) { - bool success = false; - memset(query, 0, sizeof(NVCTRLPerformanceLevelQuery)); - - char *attributes = NULL; - if(!xnvctrl->XNVCTRLQueryTargetStringAttribute(xnvctrl->display, NV_CTRL_TARGET_TYPE_GPU, 0, 0, NV_CTRL_STRING_PERFORMANCE_MODES, &attributes)) { - success = false; - goto done; - } - - split_by_delimiter(attributes, strlen(attributes), ';', attribute_line_callback, query); - success = true; - - done: - if(attributes) - XFree(attributes); - - return success; -} - -static int compare_mem_transfer_rate_max_asc(const void *a, const void *b) { - const NVCTRLPerformanceLevel *perf_a = a; - const NVCTRLPerformanceLevel *perf_b = b; - return perf_a->mem_transfer_rate_max - perf_b->mem_transfer_rate_max; -} - -bool gsr_overclock_load(gsr_overclock *self, Display *display) { - memset(self, 0, sizeof(gsr_overclock)); - self->num_performance_levels = 0; - - return gsr_xnvctrl_load(&self->xnvctrl, display); -} - -void gsr_overclock_unload(gsr_overclock *self) { - gsr_xnvctrl_unload(&self->xnvctrl); -} - -bool gsr_overclock_start(gsr_overclock *self) { - int basep = 0; - int errorp = 0; - if(!self->xnvctrl.XNVCTRLQueryExtension(self->xnvctrl.display, &basep, &errorp)) { - fprintf(stderr, "gsr warning: gsr_overclock_start: xnvctrl is not supported on your system, failed to overclock memory transfer rate\n"); - return false; - } - - NVCTRLPerformanceLevelQuery query; - if(!xnvctrl_get_performance_levels(&self->xnvctrl, &query) || query.num_performance_levels == 0) { - fprintf(stderr, "gsr warning: gsr_overclock_start: failed to get performance levels for overclocking\n"); - return false; - } - self->num_performance_levels = query.num_performance_levels; - - qsort(query.performance_level, query.num_performance_levels, sizeof(NVCTRLPerformanceLevel), compare_mem_transfer_rate_max_asc); - - int target_transfer_rate_offset = xnvctrl_get_attribute_max_value(&self->xnvctrl, query.num_performance_levels, NVCTRL_ATTRIB_GPU_MEM_TRANSFER_RATE); - if(query.num_performance_levels > 1) { - const int transfer_rate_max_diff = query.performance_level[query.num_performance_levels - 1].mem_transfer_rate_max - query.performance_level[query.num_performance_levels - 2].mem_transfer_rate_max; - target_transfer_rate_offset = min_int(target_transfer_rate_offset, transfer_rate_max_diff); - if(target_transfer_rate_offset >= 0 && xnvctrl_set_attribute_offset(&self->xnvctrl, self->num_performance_levels, target_transfer_rate_offset, NVCTRL_ATTRIB_GPU_MEM_TRANSFER_RATE)) { - fprintf(stderr, "gsr info: gsr_overclock_start: successfully set memory transfer rate offset to %d\n", target_transfer_rate_offset); - } else { - fprintf(stderr, "gsr info: gsr_overclock_start: failed to overclock memory transfer rate offset to %d\n", target_transfer_rate_offset); - } - } - - // TODO: Sort by nv_clock_max - - // TODO: Enable. Crashes on my system (gtx 1080) so it's disabled for now. Seems to crash even if graphics clock is increasd by 1, let alone 1200 - /* - int target_nv_clock_offset = xnvctrl_get_attribute_max_value(&self->xnvctrl, query.num_performance_levels, NVCTRL_GPU_NVCLOCK); - if(query.num_performance_levels > 1) { - const int nv_clock_max_diff = query.performance_level[query.num_performance_levels - 1].nv_clock_max - query.performance_level[query.num_performance_levels - 2].nv_clock_max; - target_nv_clock_offset = min_int(target_nv_clock_offset, nv_clock_max_diff); - if(target_nv_clock_offset >= 0 && xnvctrl_set_attribute_offset(&self->xnvctrl, self->num_performance_levels, target_nv_clock_offset, NVCTRL_GPU_NVCLOCK)) { - fprintf(stderr, "gsr info: gsr_overclock_start: successfully set nv clock offset to %d\n", target_nv_clock_offset); - } else { - fprintf(stderr, "gsr info: gsr_overclock_start: failed to overclock nv clock offset to %d\n", target_nv_clock_offset); - } - } - */ - - XSync(self->xnvctrl.display, False); - return true; -} - -void gsr_overclock_stop(gsr_overclock *self) { - xnvctrl_set_attribute_offset(&self->xnvctrl, self->num_performance_levels, 0, NVCTRL_ATTRIB_GPU_MEM_TRANSFER_RATE); - //xnvctrl_set_attribute_offset(&self->xnvctrl, self->num_performance_levels, 0, NVCTRL_GPU_NVCLOCK); - XSync(self->xnvctrl.display, False); -} diff --git a/src/xnvctrl.c b/src/xnvctrl.c deleted file mode 100644 index af46493..0000000 --- a/src/xnvctrl.c +++ /dev/null @@ -1,46 +0,0 @@ -#include "../include/xnvctrl.h" -#include "../include/library_loader.h" -#include -#include -#include - -bool gsr_xnvctrl_load(gsr_xnvctrl *self, Display *display) { - memset(self, 0, sizeof(gsr_xnvctrl)); - self->display = display; - - dlerror(); /* clear */ - void *lib = dlopen("libXNVCtrl.so.0", RTLD_LAZY); - if(!lib) { - fprintf(stderr, "gsr error: gsr_xnvctrl_load failed: failed to load libXNVCtrl.so.0, error: %s\n", dlerror()); - return false; - } - - const dlsym_assign required_dlsym[] = { - { (void**)&self->XNVCTRLQueryExtension, "XNVCTRLQueryExtension" }, - { (void**)&self->XNVCTRLSetTargetAttributeAndGetStatus, "XNVCTRLSetTargetAttributeAndGetStatus" }, - { (void**)&self->XNVCTRLQueryValidTargetAttributeValues, "XNVCTRLQueryValidTargetAttributeValues" }, - { (void**)&self->XNVCTRLQueryTargetStringAttribute, "XNVCTRLQueryTargetStringAttribute" }, - - { NULL, NULL } - }; - - if(!dlsym_load_list(lib, required_dlsym)) { - fprintf(stderr, "gsr error: gsr_xnvctrl_load failed: missing required symbols in libXNVCtrl.so.0\n"); - goto fail; - } - - self->library = lib; - return true; - - fail: - dlclose(lib); - memset(self, 0, sizeof(gsr_xnvctrl)); - return false; -} - -void gsr_xnvctrl_unload(gsr_xnvctrl *self) { - if(self->library) { - dlclose(self->library); - memset(self, 0, sizeof(gsr_xnvctrl)); - } -}