How to troubleshoot OpenGL on Ubuntu under Windows 10 (WSL)

While I hate to be "that guy" who posts an answer to his own question, I went through more than a little pain to get things working, and I'd like to save the next guy the same amount of trouble. So, here is

What actually ended up working

For reasons I do not understand, my system worked when I ran contrary to the (quite sensible) recommendation from @allquixotic.

1) Disable LIBGL_ALWAYS_INDIRECT

This wound up being really difficult, simply because I had to find where it was set.

  • In the folder \etc\profile.d was a file wsl-integration.sh.
  • The above file was actually a symlink; the actual file was /usr/share/wslu/wsl-integration.sh
  • In that file the variable LIBGL_ALWAYS_INDIRECT was set, so I commented out that line.

2) Do not use the -wgl command line argument (or its GUI equivalent) for VcXsrv

Since I was launching VcXsrv from a GUI client, this meant leaving the second option box, titles "Native opengl", unchecked.

Only once I had both those changes made (and did a fresh reboot to make sure no old settings for VcXsrv had persisted) then the gears in glxgears were turning at a normal rate, and I could reorient them using the arrow keys, just like they're supposed to work.


Actually trying to solve your problem

  1. Before you run Robot OS programs that need to be hardware accelerated, like glxgears, run export LIBGL_ALWAYS_INDIRECT=1.
  2. When starting VcXsrv (or any X server on Windows), pass the -wgl command line argument into the server as a command line argument.
  3. If that doesn't work, try using the paid version of Xming instead of VcXsrv.
  4. If that still doesn't work, you're mostly out of luck. read below to see why.

Explanation of under the hood

Within a Windows Subsystem for Linux (WSL) or Hyper-V guest, hardware-accelerated OpenGL is only possible through indirect rendering.

GLX is a protocol extension for the X11 client-server protocol. The X11 client-server protocol is the network protocol used for communication between clients (programs that create X windows) and servers (programs that render those windows onto a screen, whether physical or virtual).

On desktop Linux, GLX is the standard mechanism for accessing OpenGL. From a client program, it's basically a two-step process: (1) talk to GLX, then (2) talk to OpenGL. The second step varies depending on whether you're using indirect or direct rendering (i.e., indirect or direct GLX.)

  • Indirect rendering:

    • Supports only up to OpenGL version 1.4 (no GLSL, etc.)
    • Requires the environment variable LIBGL_ALWAYS_INDIRECT=1 for most programs to use it, otherwise they default to direct rendering.
    • Sends all OpenGL commands to the X server using the GLX protocol.
    • The X server backend uses the OpenGL implementation local to the X server to complete the rendering to the window.
    • Is network-transparent, meaning it works over network connections and UNIX domain sockets as well as locally.
  • Direct rendering:

    • Supports whatever version of OpenGL the graphics driver supports, which could be up to OpenGL 4.x or higher if OpenGL ever releases a new version.
    • Requires the environment variable LIBGL_ALWAYS_INDIRECT to be unset.
    • Sends all OpenGL commands using dynamic loading to the symbols available in libGL.so (with the appropriate version on the end, like libGL.so.1, etc.) -- these are native function calls.
    • The X server does not directly "see" the OpenGL rendering commands. All it sees is a rectangular region that it sets aside in the frame buffer for the graphics driver to render into. It doesn't know what is rendered, only where.
    • Is not network-transparent, meaning it only works locally on the same computer.

There is an implementation of OpenGL that supports GLX direct rendering but -- unbeknownst to the X server -- pipes the OpenGL calls over the network to a hardware accelerated remote. This product is called VirtualGL. But VirtualGL does not have a Windows server component, so there's no way to use VirtualGL with a Windows host. If you were running a Linux host and a Linux guest in virtualization, you could use VirtualGL from the guest to the host to get direct rendering in the guest using the host's graphics card.

I don't know what "Robot OS" is, but if it only requires OpenGL commands from version 1.4 or older, it should work if you run an X server on your Windows host using the -wgl command. The X server needs to support this flag. I've never gotten it to work with VcXsrv myself, but I know the paid version of Xming works.

There are several X servers that run on Windows. I've tested most of them except for the really expensive commercial implementations. In my opinion, the best for OpenGL is the paid version of Xming. The free version is rather out of date and not as good.

However, there does not exist -- cannot exist -- an implementation of a Windows X server that will support more than OpenGL 1.4 in indirect rendering mode (from a WSL or Hyper-V client) because the GLX protocol itself does not specify OpenGL calls above version 1.4.

So, if Robot OS requires more than OpenGL 1.4, there is no way whatsoever to run it in WSL or Hyper-V and get hardware accelerated rendering on a Windows X server. You'd have to use something like VMware Workstation.


Ran into the same issue and figured out that glxgears is likely just overwhelming VcXsrv with draw requests so fast it never gets around to rendering anything.

Details and a modded version of glxgears with a framerate limiting option here:

https://github.com/tobecodex/glxgears

Using this version I can easily get > 800 fps for gears on a Surface Book 2.

I'm going to guess the lack of a true VSYNC rate on modern displays causes glxgears to spam the server as fast as it possibly can which kills VcXsrv.

I noticed that MeshLab and similar ran just fine and that Xming doesn't have this problem (also doesn't have HW acceleration though).

So in answer to your question: Don't worry about it. Gazebo will probably run just fine. The problem only exists for glxgears and probably apps of a similar vintage.

BTW, I found that: export LIBGL_ALWAYS_INDIRECT and -wgl in any combination have little effect for me. Might be worth playing with these again since the results will almost certainly be different to the ones you saw for glxgears.