[cairo] [patch] boilerplate/gl: use glFlush instead of glFinish

Matt Sealey neko at bakuhatsu.net
Fri Jan 3 08:24:19 PST 2014


On Thu, Aug 29, 2013 at 3:41 PM, Henry (Yu) Song - SISA
<henry.song at samsung.com> wrote:
> From 73c77248ed95b3f9f6a777d86c368e464f3b49bb Mon Sep 17 00:00:00 2001
> From: Henry Song <henry.song at samsung.com>
> Date: Thu, 29 Aug 2013 13:35:11 -0700
> Subject: [PATCH] boilerplate/gl: use glFlush instead of glFinish for
>  synchronization
>
> Use glFlush () is a proper way to indicate a surface/frame finish
> instead of a glFinish. Applications very rarely use glFinish ().
> For offscreen, a glFlush () should be used to indicate finish drawings
> onto a surface.  For onscreen, an eglSwapBuffers/glXSwapBuffers should
> be used (internal, it calls glFlush).
>
> Using glFlush () computes performance more accurately folllowing app
> usage model.

That entire commit message is contrary to the OpenGL specification;
glFlush() can return at any time, it is a hint to the graphics driver
to empty/flush/commit buffers, command streams and so on - but it does
not guarantee that these commands and buffers are 'complete' and in
fact can return immediately. If you perform any actions which use a
different GPU or the CPU on those buffers, there is no guarantee at
the glFlush() call return that the rendered data is even in your
target surface. Just that the GPU has been told that it should get
there.

What you get with glFlush() vs. glFinish() is 9 billion frames which
seem perfect and the '9 billion and one'th frame will not be fully
rendered offscreen before the next actor wants to use it. You don't
notice this most of the time in a microbenchmark or so, and the
effects would be essentially hidden until you implement it on a system
where there is a lot more going on.

The only correct way to perform a synchronization event - which is
what the functions below are doing - is glFinish().

The 'official' and most effective performance solution to the lack of
guarantee of glFlush vs. the performance penalty of glFinish is
extensions such as fences (i.e. GL_NV_fence) to ensure completion of
rendering without the penalty of a full flush or finish. Fences are,
by that extension spec, mostly the same functionality at much lower
overhead (although, at the expense of having to micromanage fences)

http://www.opengl.org/registry/specs/NV/fence.txt

The overview of the extension exactly describes your issue and why
using glFlush instead of glFinish is not correct behavior :)

> --- a/boilerplate/cairo-boilerplate-glx.c
> +++ b/boilerplate/cairo-boilerplate-glx.c
> @@ -353,7 +353,7 @@ _cairo_boilerplate_gl_synchronize (void *closure)
>      if (cairo_device_acquire (gltc->device))
>         return;
>
> -    glFinish ();
> +    glFlush ();


More information about the cairo mailing list