4/7/24, 4:16 PM opengl - glXSwapBuffers() blocks until vblank - Stack Overflow
glXSwapBuffers() blocks until vblank
Asked 9 years, 6 months ago Modified 2 years, 5 months ago Viewed 4k times
While trying to make a compositing window manager for X11 using OpenGL as backend, I'm caught in a
nasty situation where glXSwapBuffers() blocks until vblank rendering the compositor irresponsive to X
7 events which causes windows being dragged around to lag behind the cursor by roughly one frame. I've
tried multithreading but it didn't work well, so I decide the only proper solution is to make
glXSwapBuffers() asynchronous. It would be desirable to send drawing commands to GPU and return
immediately without waiting for the operations to actually finish, and AFAIK this is possible under modern
Linux with DRI2. So what should I do?
opengl x11 vsync
Share Improve this question Follow asked Oct 2, 2014 at 14:12
wildptr
107 1 7
2 Answers Sorted by: Highest score (default)
Actually glXSwapBuffers should return immediately. What's blocking however is the very next OpenGL
command that introduces a so called synchronization point. Usually this is the next glClear that follows
8 the call of glXSwapBuffers .
Note that it's actually desireable to somehow synchronize with the V-Blank, otherwise nasty tearing
artifacts happen. But you're right, that in a naive implementation this introduces about one display
refresh interval of latency.
The big problem here is, that double buffered windows redirected to an off-screen surface may still
subjected to the active swap interval (i.e. V-Sync setting); and of course double buffering itself doesn't
make a lot of sense in a composited setting.
So here's what you can do: Use a swap interval extension to set your compositor's swap interval to 0 (no
V-Sync); depending on your system's settings this choice may actually not be honored (user configured
all applications are forced to V-Sync). Unfortunately there are several swap interval extensions and what
works with one display driver doesn't work with another. I suggest you look at the swap interval example
programs of Mesa and the sources of glxgears of Mesa, which contain code that deals with pretty much
every situation you may encounter.
It's also desireable to somehow turn off V-Sync in the clients too. I don't see better way than injecting a
shared object into them, hooking glXSwapBuffers , glXCreateContext and the swap interval extensions
to override them.
Finally you must use one of the available video synchronization GLX extensions to implement a timed
buffer swap in your compositor (i.e. call an "unsynchronized" glXSwapBuffers at just the right moment
when the V-Blank happens). With a direct OpenGL context and a realtime scheduling policy applied to
the compositor process you can do that.
https://stackoverflow.com/questions/26162745/glxswapbuffers-blocks-until-vblank?rq=3 1/3
4/7/24, 4:16 PM opengl - glXSwapBuffers() blocks until vblank - Stack Overflow
Note that all these issues are shortcomings in the existing X11 protocol. But if you think Wayland would
get rid of these issues, think again. While Wayland was originally intended to make "every frame perfect"
and do away with the synchronization issues, in practice I encountered many of the problems, again. In
this blog post the creator of Wayland talks about roundtrips and overhead, but he completely avoids the
point of pipeline synchronization and buffer swap latency. The problems are inherent to the concept of
stacked composition and buffer swap based V-Sync. To really solve the issue there must be some kind
of screen associated V-Sync event that's independent from graphics operations and can be applied an
arbitrary phase offset, so that applications can synchronize their rendering loops with display refresh.
And there should be an additional "framebuffer commit" function that makes the whole composition
chain consider the newly arrived frame. This would allow the compositor to sync applications to a few
100µs before the V-Blank happens, so that composition can happen in that margin between framebuffer
commit and V-Blank.
Share Improve this answer Follow edited Oct 2, 2014 at 21:20 answered Oct 2, 2014 at 18:11
datenwolf
161k 13 188 303
As @datenwork says, I don't think it's glxSwapBuffers that's blocking. But something is. I solved the
issue inspired by this blog post.
2
Specifically, on my platform (Ubuntu 14 + Nvidia driver + Nvidia OpenGL implementation), the following
code works:
PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT =
(PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddress((const GLubyte*)"glXSwapIntervalEXT"); // Set
the glxSwapInterval to 0, ie. disable vsync! khronos.org/opengl/wiki/Swap_Interval
glXSwapIntervalEXT(x11_display, glx_window, 0); // glXSwapIntervalEXT(0);
where x11_display is built as
Display* x11_display = XOpenDisplay(0);
and glx_window is built as
GLXWindow glx_window = glXCreateWindow(x11_display, fb_config, window, 0);
and fb_config is a suitable GLXFBConfig , that I, specifically, get as follows:
int visual, n_fb_configs;
GLXFBConfig* fb_configs = glXGetFBConfigs(x11_display, screen_number, &n_fb_configs);
GLXFBConfig fb_config = fb_configs[2]; // Select 3rd FB config! Many others work!
glXGetFBConfigAttrib(x11_display, fb_config, GLX_VISUAL_ID, &visual); // Query visual?
printf("screen %x fb_configs %d fb_config %llx visual %x\n", screen_number, n_fb_configs,
(ull)fb_config, visual);
Note that I don't get any screen tearing that wasn't alread there with (the largely useless, imo) vsync
enabled.
Also, depending on your GPU driver and OpenGL implementation (Is it Nvidia's? Is it Mesa's?), there's
other glxSwapInteral*(...) functions that you may have to use. Eg. there's a
glXSwapIntervalMESA(...) and a glXSwapIntervalSGI(...) .
https://stackoverflow.com/questions/26162745/glxswapbuffers-blocks-until-vblank?rq=3 2/3
4/7/24, 4:16 PM opengl - glXSwapBuffers() blocks until vblank - Stack Overflow
Rant: As usual with X11 programming, there's very little documentation to hold your hand... Good luck! :)
Bonus. To quote the OpenGL documentation:
Your application's use of swap interval may be overridden by external, driver-specific
configuration. For example, forcing Vsync Off in a driver's control panel will prevent Vsync, even
if swap interval is set to 1 in your application.
Share Improve this answer Follow edited Oct 20, 2021 at 19:48 answered May 8, 2017 at 19:27
Raph Levien étale-cohomology
5,158 26 24 2,226 2 29 36
https://stackoverflow.com/questions/26162745/glxswapbuffers-blocks-until-vblank?rq=3 3/3