1
0
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:
wm4 2015-10-30 20:26:51 +01:00
parent 93f748e77f
commit 2b6241a09a
4 changed files with 41 additions and 0 deletions

View File

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

View File

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

View File

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

View File

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