mirror of
https://repo.dec05eba.com/gpu-screen-recorder
synced 2026-05-07 23:20:25 +09:00
Remove deprecated overclocking option
This commit is contained in:
@@ -89,7 +89,6 @@ There are also additional dependencies needed at runtime depending on your GPU v
|
|||||||
* cuda runtime (libcuda.so.1) (libnvidia-compute)
|
* cuda runtime (libcuda.so.1) (libnvidia-compute)
|
||||||
* nvenc (libnvidia-encode)
|
* nvenc (libnvidia-encode)
|
||||||
* nvfbc (libnvidia-fbc1, when recording the screen on x11)
|
* nvfbc (libnvidia-fbc1, when recording the screen on x11)
|
||||||
* xnvctrl (libxnvctrl0, when using the `-oc` option)
|
|
||||||
|
|
||||||
# How to use
|
# 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.\
|
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.\
|
||||||
|
|||||||
@@ -329,9 +329,6 @@ Clear buffer after saving replay (default: no).
|
|||||||
Organize replays in date-based folders (default: no).
|
Organize replays in date-based folders (default: no).
|
||||||
.SS Advanced Options
|
.SS Advanced Options
|
||||||
.TP
|
.TP
|
||||||
.BI \-oc " yes|no"
|
|
||||||
Overclock NVIDIA memory (X11 only). Requires Coolbits=12. Use at own risk.
|
|
||||||
.TP
|
|
||||||
.BI \-p " plugin.so"
|
.BI \-p " plugin.so"
|
||||||
Load plugin (.so file). Can be specified multiple times.
|
Load plugin (.so file). Can be specified multiple times.
|
||||||
.TP
|
.TP
|
||||||
|
|||||||
@@ -97,7 +97,6 @@ typedef struct {
|
|||||||
bool date_folders;
|
bool date_folders;
|
||||||
bool restore_portal_session;
|
bool restore_portal_session;
|
||||||
bool restart_replay_on_save;
|
bool restart_replay_on_save;
|
||||||
bool overclock;
|
|
||||||
bool write_first_frame_ts;
|
bool write_first_frame_ts;
|
||||||
bool is_livestream;
|
bool is_livestream;
|
||||||
bool is_output_piped;
|
bool is_output_piped;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#ifndef GSR_CUDA_H
|
#ifndef GSR_CUDA_H
|
||||||
#define GSR_CUDA_H
|
#define GSR_CUDA_H
|
||||||
|
|
||||||
#include "overclock.h"
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
@@ -75,9 +74,6 @@ typedef struct CUgraphicsResource_st *CUgraphicsResource;
|
|||||||
|
|
||||||
typedef struct gsr_cuda gsr_cuda;
|
typedef struct gsr_cuda gsr_cuda;
|
||||||
struct gsr_cuda {
|
struct gsr_cuda {
|
||||||
gsr_overclock overclock;
|
|
||||||
bool do_overclock;
|
|
||||||
|
|
||||||
void *library;
|
void *library;
|
||||||
CUcontext cu_ctx;
|
CUcontext cu_ctx;
|
||||||
|
|
||||||
@@ -102,7 +98,7 @@ struct gsr_cuda {
|
|||||||
CUresult (*cuGraphicsSubResourceGetMappedArray)(CUarray *pArray, CUgraphicsResource resource, unsigned int arrayIndex, unsigned int mipLevel);
|
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);
|
void gsr_cuda_unload(gsr_cuda *self);
|
||||||
|
|
||||||
#endif /* GSR_CUDA_H */
|
#endif /* GSR_CUDA_H */
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ typedef struct gsr_egl gsr_egl;
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
gsr_egl *egl;
|
gsr_egl *egl;
|
||||||
bool overclock;
|
|
||||||
gsr_color_depth color_depth;
|
gsr_color_depth color_depth;
|
||||||
} gsr_video_encoder_nvenc_params;
|
} gsr_video_encoder_nvenc_params;
|
||||||
|
|
||||||
|
|||||||
@@ -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 */
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
#ifndef GSR_XNVCTRL_H
|
|
||||||
#define GSR_XNVCTRL_H
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#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 */
|
|
||||||
@@ -32,8 +32,6 @@ src = [
|
|||||||
'src/replay_buffer/replay_buffer_disk.c',
|
'src/replay_buffer/replay_buffer_disk.c',
|
||||||
'src/egl.c',
|
'src/egl.c',
|
||||||
'src/cuda.c',
|
'src/cuda.c',
|
||||||
'src/xnvctrl.c',
|
|
||||||
'src/overclock.c',
|
|
||||||
'src/window_texture.c',
|
'src/window_texture.c',
|
||||||
'src/shader.c',
|
'src/shader.c',
|
||||||
'src/color_conversion.c',
|
'src/color_conversion.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";
|
const char *program_name = inside_flatpak ? "flatpak run --command=gpu-screen-recorder com.dec05eba.gpu_screen_recorder" : "gpu-screen-recorder";
|
||||||
printf("usage: %s -w <window_id|monitor|focused|portal|region|v4l2_device_path> [-c <container_format>] [-s WxH] [-region WxH+X+Y] [-f <fps>] [-a <audio_input>] "
|
printf("usage: %s -w <window_id|monitor|focused|portal|region|v4l2_device_path> [-c <container_format>] [-s WxH] [-region WxH+X+Y] [-f <fps>] [-a <audio_input>] "
|
||||||
"[-q <quality>] [-r <replay_buffer_size_sec>] [-replay-storage ram|disk] [-restart-replay-on-save yes|no] "
|
"[-q <quality>] [-r <replay_buffer_size_sec>] [-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 <bitrate>] [-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 <bitrate>] [-fm cfr|vfr|content] "
|
||||||
"[-bm auto|qp|vbr|cbr] [-cr limited|full] [-tune performance|quality] [-df yes|no] [-sc <script_path>] [-p <plugin_path>] "
|
"[-bm auto|qp|vbr|cbr] [-cr limited|full] [-tune performance|quality] [-df yes|no] [-sc <script_path>] [-p <plugin_path>] "
|
||||||
"[-cursor yes|no] [-keyint <value>] [-restore-portal-session yes|no] [-portal-session-token-filepath filepath] [-encoder gpu|cpu] "
|
"[-cursor yes|no] [-keyint <value>] [-restore-portal-session yes|no] [-portal-session-token-filepath filepath] [-encoder gpu|cpu] "
|
||||||
"[-fallback-cpu-encoding yes|no] [-o <output_file>] [-ro <output_directory>] [-ffmpeg-opts <options>] [--list-capture-options [card_path]] "
|
"[-fallback-cpu-encoding yes|no] [-o <output_file>] [-ro <output_directory>] [-ffmpeg-opts <options>] [--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->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->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->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->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->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);
|
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);
|
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) {
|
if(self->audio_codec == GSR_AUDIO_CODEC_FLAC) {
|
||||||
fprintf(stderr, "gsr warning: flac audio codec is temporary disabled, using opus audio codec instead\n");
|
fprintf(stderr, "gsr warning: flac audio codec is temporary disabled, using opus audio codec instead\n");
|
||||||
self->audio_codec = GSR_AUDIO_CODEC_OPUS;
|
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;
|
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) {
|
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"
|
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");
|
"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");
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ bool gsr_get_supported_video_codecs_nvenc(gsr_supported_video_codecs *video_code
|
|||||||
gsr_cuda cuda;
|
gsr_cuda cuda;
|
||||||
memset(&cuda, 0, sizeof(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");
|
fprintf(stderr, "gsr error: gsr_get_supported_video_codecs_nvenc: failed to load cuda\n");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|||||||
17
src/cuda.c
17
src/cuda.c
@@ -5,9 +5,8 @@
|
|||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
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));
|
memset(self, 0, sizeof(gsr_cuda));
|
||||||
self->do_overclock = do_overclock;
|
|
||||||
|
|
||||||
dlerror(); /* clear */
|
dlerror(); /* clear */
|
||||||
void *lib = dlopen("libcuda.so.1", RTLD_LAZY);
|
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;
|
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;
|
self->library = lib;
|
||||||
return true;
|
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) {
|
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->library) {
|
||||||
if(self->cu_ctx) {
|
if(self->cu_ctx) {
|
||||||
self->cuCtxDestroy_v2(self->cu_ctx);
|
self->cuCtxDestroy_v2(self->cu_ctx);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "../../../include/encoder/video/nvenc.h"
|
#include "../../../include/encoder/video/nvenc.h"
|
||||||
#include "../../../include/egl.h"
|
#include "../../../include/egl.h"
|
||||||
#include "../../../include/cuda.h"
|
#include "../../../include/cuda.h"
|
||||||
#include "../../../include/window/window.h"
|
#include "../../../include/utils.h"
|
||||||
|
|
||||||
#include <libavcodec/avcodec.h>
|
#include <libavcodec/avcodec.h>
|
||||||
#include <libavutil/hwcontext_cuda.h>
|
#include <libavutil/hwcontext_cuda.h>
|
||||||
@@ -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) {
|
static bool gsr_video_encoder_nvenc_start(gsr_video_encoder *encoder, AVCodecContext *video_codec_context, AVFrame *frame) {
|
||||||
gsr_video_encoder_nvenc *self = encoder->priv;
|
gsr_video_encoder_nvenc *self = encoder->priv;
|
||||||
|
|
||||||
const bool is_x11 = gsr_window_get_display_server(self->params.egl->window) == GSR_DISPLAY_SERVER_X11;
|
if(!gsr_cuda_load(&self->cuda)) {
|
||||||
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)) {
|
|
||||||
fprintf(stderr, "gsr error: gsr_video_encoder_nvenc_start: failed to load cuda\n");
|
fprintf(stderr, "gsr error: gsr_video_encoder_nvenc_start: failed to load cuda\n");
|
||||||
gsr_video_encoder_nvenc_stop(self, video_codec_context);
|
gsr_video_encoder_nvenc_stop(self, video_codec_context);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
20
src/main.cpp
20
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: {
|
case GSR_GPU_VENDOR_NVIDIA: {
|
||||||
gsr_video_encoder_nvenc_params params;
|
gsr_video_encoder_nvenc_params params;
|
||||||
params.egl = egl;
|
params.egl = egl;
|
||||||
params.overclock = arg_parser.overclock;
|
|
||||||
params.color_depth = color_depth;
|
params.color_depth = color_depth;
|
||||||
video_encoder = gsr_video_encoder_nvenc_create(¶ms);
|
video_encoder = gsr_video_encoder_nvenc_create(¶ms);
|
||||||
break;
|
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");
|
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) {
|
int main(int argc, char **argv) {
|
||||||
setlocale(LC_ALL, "C"); // Sigh... stupid C
|
setlocale(LC_ALL, "C"); // Sigh... stupid C
|
||||||
#ifdef __GLIBC__
|
#ifdef __GLIBC__
|
||||||
@@ -3645,21 +3648,6 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
validate_args_with_capture_sources(arg_parser, capture_sources);
|
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);
|
//av_log_set_level(AV_LOG_TRACE);
|
||||||
|
|
||||||
const Arg *audio_input_arg = args_parser_get_arg(&arg_parser, "-a");
|
const Arg *audio_input_arg = args_parser_get_arg(&arg_parser, "-a");
|
||||||
|
|||||||
279
src/overclock.c
279
src/overclock.c
@@ -1,279 +0,0 @@
|
|||||||
#include "../include/overclock.h"
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
#include "../include/xnvctrl.h"
|
|
||||||
#include "../include/library_loader.h"
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <dlfcn.h>
|
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user