mirror of
https://github.com/mpv-player/mpv
synced 2025-02-17 04:58:06 +00:00
vo_opengl: add vsync-fences option
Yet another relatively useless option that tries to make OpenGL's sync
behavior somewhat sane. The results are not too encouraging. With a
value of 1, vsync jitter is gone on nVidia, but there are frame drops
(less than with glfinish). With 2, I get the usual vsync jitter _and_
frame drops.
There's still some hope that it might prevent too deep queuing with some
GPUs, I guess.
The timeout for the wait call is 1 second. The value is pretty
arbitrary; it should just not be too high to freeze the process (if
the GPU is un-nice), and not too low to trigger the timeout in normal
cases, even if the GPU load is very high. So I guess 1 second is ok
as a timeout.
The idea to use fences this way to control the queue depth was stolen
from RetroArch:
df01279cf3/gfx/drivers/gl.c (L1856)
This commit is contained in:
parent
93f748e77f
commit
2b6241a09a
@ -667,6 +667,15 @@ Available video output drivers are:
|
||||
|
||||
X11/GLX only.
|
||||
|
||||
``vsync-fences=<N>``
|
||||
Synchronize the CPU to the Nth past frame using the ``GL_ARB_sync``
|
||||
extension. A value of 0 disables this behavior (default). A value of
|
||||
1 means it will synchronize to the current frame after rendering it.
|
||||
Like ``glfinish`` and ``waitvsync``, this can lower or ruin performance.
|
||||
Its advantage is that it can span multiple frames, and effectively limit
|
||||
the number of frames the GPU queues ahead (which also has an influence
|
||||
on vsync).
|
||||
|
||||
``dwmflush=<no|windowed|yes>``
|
||||
Calls ``DwmFlush`` after swapping buffers on Windows (default: no).
|
||||
It also sets ``SwapInterval(0)`` to ignore the OpenGL timing. Values
|
||||
|
@ -230,6 +230,16 @@ static const struct gl_functions gl_functions[] = {
|
||||
.extension = "GL_ARB_texture_rg",
|
||||
.provides = MPGL_CAP_TEX_RG,
|
||||
},
|
||||
{
|
||||
.ver_core = 320,
|
||||
.extension = "GL_ARB_sync",
|
||||
.functions = (const struct gl_function[]) {
|
||||
DEF_FN(FenceSync),
|
||||
DEF_FN(ClientWaitSync),
|
||||
DEF_FN(DeleteSync),
|
||||
{0}
|
||||
},
|
||||
},
|
||||
// Swap control, always an OS specific extension
|
||||
// The OSX code loads this manually.
|
||||
{
|
||||
|
@ -244,6 +244,10 @@ struct GL {
|
||||
void (GLAPIENTRY *UniformMatrix3fv)(GLint, GLsizei, GLboolean,
|
||||
const GLfloat *);
|
||||
|
||||
GLsync (GLAPIENTRY *FenceSync)(GLenum, GLbitfield);
|
||||
GLenum (GLAPIENTRY *ClientWaitSync)(GLsync, GLbitfield, GLuint64);
|
||||
void (GLAPIENTRY *DeleteSync)(GLsync sync);
|
||||
|
||||
void (GLAPIENTRY *VDPAUInitNV)(const GLvoid *, const GLvoid *);
|
||||
void (GLAPIENTRY *VDPAUFiniNV)(void);
|
||||
GLvdpauSurfaceNV (GLAPIENTRY *VDPAURegisterOutputSurfaceNV)
|
||||
|
@ -51,6 +51,8 @@
|
||||
#include "opengl/video.h"
|
||||
#include "opengl/lcms.h"
|
||||
|
||||
#define NUM_VSYNC_FENCES 10
|
||||
|
||||
struct gl_priv {
|
||||
struct vo *vo;
|
||||
struct mp_log *log;
|
||||
@ -72,6 +74,7 @@ struct gl_priv {
|
||||
int allow_sw;
|
||||
int swap_interval;
|
||||
int dwm_flush;
|
||||
int opt_vsync_fences;
|
||||
|
||||
char *backend;
|
||||
int es;
|
||||
@ -83,6 +86,9 @@ struct gl_priv {
|
||||
int opt_pattern[2];
|
||||
int last_pattern;
|
||||
int matches, mismatches;
|
||||
|
||||
GLsync vsync_fences[NUM_VSYNC_FENCES];
|
||||
int num_vsync_fences;
|
||||
};
|
||||
|
||||
static void resize(struct gl_priv *p)
|
||||
@ -121,6 +127,12 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
struct gl_priv *p = vo->priv;
|
||||
GL *gl = p->gl;
|
||||
|
||||
if (gl->FenceSync && p->num_vsync_fences < p->opt_vsync_fences) {
|
||||
GLsync fence = gl->FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);;
|
||||
if (fence)
|
||||
p->vsync_fences[p->num_vsync_fences++] = fence;
|
||||
}
|
||||
|
||||
gl_video_render_frame(p->renderer, frame, 0);
|
||||
|
||||
// The playloop calls this last before waiting some time until it decides
|
||||
@ -163,6 +175,11 @@ static void flip_page(struct vo *vo)
|
||||
p->opt_pattern[0] = 0;
|
||||
}
|
||||
}
|
||||
while (p->opt_vsync_fences > 0 && p->num_vsync_fences >= p->opt_vsync_fences) {
|
||||
gl->ClientWaitSync(p->vsync_fences[0], GL_SYNC_FLUSH_COMMANDS_BIT, 1e9);
|
||||
gl->DeleteSync(p->vsync_fences[0]);
|
||||
MP_TARRAY_REMOVE_AT(p->vsync_fences, p->num_vsync_fences, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static int query_format(struct vo *vo, int format)
|
||||
@ -449,6 +466,7 @@ static const struct m_option options[] = {
|
||||
OPT_FLAG("sw", allow_sw, 0),
|
||||
OPT_FLAG("es", es, 0),
|
||||
OPT_INTPAIR("check-pattern", opt_pattern, 0),
|
||||
OPT_INTRANGE("vsync-fences", opt_vsync_fences, 0, 0, NUM_VSYNC_FENCES),
|
||||
|
||||
OPT_SUBSTRUCT("", renderer_opts, gl_video_conf, 0),
|
||||
OPT_SUBSTRUCT("", icc_opts, mp_icc_conf, 0),
|
||||
|
Loading…
Reference in New Issue
Block a user