Disabling vsync in OpenGL using GLX

Posted: 10th November 2014 by admin in OpenGL, Programming, Tips & Tricks

Recently I hit a strange issue. My code was rendering in 1-2ms with my nvidia board, but 15-16ms with the integrated intel board (sandy bridge), which I found to be a bit strange, as it was a rather simple thing to render. So I’ve commented out all the rendering code, leaving in only glClear. To my surprise, rendering time did not change at all. After some investigation, turned out that although the rendering was fast, once glxSwapBuffers was used, it somehow locked it down to 15-16ms. But to my surprise I’ve found out that not glxSwapBuffers() was the one waiting, but the glClear() itself, as if somehow glxSWapBuffers was setting a flag to make glClear wait. Of course, probably for the vsync.

And even worse, once the timing was strictly around the drawing function, glxSwapBuffers being outside of timed interval, the rendering time was still affected. In affected as not changed at all. It started with 1-2ms then after couple of seconds was making it’s way up to 15-16ms, like something was building up and slowing the code down (inside the driver perhaps) making impossible to count how much time the rendering is actually taking. The nvidia board had no issue of this sort. Given this, I’ve decided to disable vsync and give a go, so I proceeded to find some information about how to disable vsync from code, assuming this is even possible. And sure it is.

Turns out GLX has a way to control it, using one of glXSwapIntervalEXT, glXSwapIntervalMESA or glXSwapIntervalSGI functions:

    
    PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT;
    PFNGLXSWAPINTERVALMESAPROC glXSwapIntervalMESA;
    PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI;

    glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddress( (const GLubyte*)"glXSwapIntervalEXT");

    if (glXSwapIntervalEXT != NULL) {
        glXSwapIntervalEXT(dpy, win, 0);
    } else {
        glXSwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC)glXGetProcAddress( (const GLubyte*)"glXSwapIntervalMESA");
        if ( glXSwapIntervalMESA != NULL ) {
            glXSwapIntervalMESA(0);
        } else {
            glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddress( (const GLubyte*)"glXSwapIntervalSGI");
            if ( glXSwapIntervalSGI != NULL ) {
                glXSwapIntervalSGI(0);
            }
        }
    }

Once this code in place the render timing was back in place again, with 1-2ms render time.