diff options
author | wm4 <wm4@nowhere> | 2015-10-30 20:26:51 +0100 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2015-10-30 20:26:51 +0100 |
commit | 2b6241a09a136db26834e75aeb3730f00894ee54 (patch) | |
tree | 52b6401c2140d52c6d162fa8d458458ea965767b /video/out | |
parent | 93f748e77f1aeaeac3035552ed49aa33645bdfb0 (diff) |
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:
https://github.com/libretro/RetroArch/blob/df01279cf318e7ec90ace039d60515296e3de908/gfx/drivers/gl.c#L1856
Diffstat (limited to 'video/out')
-rw-r--r-- | video/out/opengl/common.c | 10 | ||||
-rw-r--r-- | video/out/opengl/common.h | 4 | ||||
-rw-r--r-- | video/out/vo_opengl.c | 18 |
3 files changed, 32 insertions, 0 deletions
diff --git a/video/out/opengl/common.c b/video/out/opengl/common.c index f045184373..fae969ee2a 100644 --- a/video/out/opengl/common.c +++ b/video/out/opengl/common.c @@ -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. { diff --git a/video/out/opengl/common.h b/video/out/opengl/common.h index 35d303e96c..3f5ab0ebde 100644 --- a/video/out/opengl/common.h +++ b/video/out/opengl/common.h @@ -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) diff --git a/video/out/vo_opengl.c b/video/out/vo_opengl.c index d55b5f5075..f5a3cdcf73 100644 --- a/video/out/vo_opengl.c +++ b/video/out/vo_opengl.c @@ -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), |