5

I have installed Ubuntu on Windows 10 using Windows Subsystem for Linux (WSL). I'm attempting to get OpenGL graphics to work. My ultimate objective is to be able to run the Gazebo simulator for Robot OS (ROS), which requires OpenGL. As a first step, I'm trying to ensure that OpenGL graphics are working like they're supposed to.

According to this tutorial and many others, to run ROS and Gazebo I should install VcXsrv and run the X server with the "Native OpenGL" option disabled, so I'm doing that.

My immediate problem is that OpenGL doesn't appear to be working quite right. I have installed the Mesa utils and when I run glxgears I do see the graphics window, but the animation is extremely slow. I'd estimate that the gears are turning at about 1 revolution per minute. I can reorient the gears using the arrow keys, but again the update is extremely slow. (Every now and then there is a visible "jump", if that matters.)

For a comparison, I tried running glxgears on Ubuntu running in a VirtualBox machine. To my surprise, it animates much faster; the gears make a full rotation about once every 4 seconds, compared to once every (maybe 60 seconds but I lost patience) when running under Windows with WSL. This is a big surprise since I'd expect the VirtualBox to be much slower.

On Windows with WSL, glxgears claims that it is running very fast -- between 800 and 1700 FPS. In VirtualBox glxgears reports about 900-1000FPS.

Version info on glxgears and OpenGL:

xxxx@DESKTOP-8U2MCOG:~$ glxgears -info
GL_RENDERER   = Software Rasterizer
GL_VERSION    = 1.4 (2.1 Mesa 19.2.0-devel (git-cdf42f5eaa))
GL_VENDOR     = Mesa Project
GL_EXTENSIONS = GL_ARB_depth_texture GL_ARB_fragment_program GL_ARB_fragment_program_shadow GL_ARB_occlusion_query GL_ARB_texture_env_dot3 GL_ARB_transpose_matrix GL_EXT_draw_range_elements GL_EXT_multi_draw_arrays GL_NV_depth_clamp GL_NV_fog_distance GL_NV_point_sprite GL_SUN_multi_draw_arrays
VisualID 183, 0xb7
20311 frames in 5.0 seconds = 4062.197 FPS

Why is glxgears running so slow in WSL? If it should rightly be able to run faster, then how do I make that happen?

UPDATE

Based on the answer from @allquixotic below I made another attempt to run with the wgl option, which I did by leaving that second checkbox "Native opengl" checked. I had tried this before, but it turns out I needed to do this after a reboot for it to take effect. When I run glxgears with this setup, I get a slightly different readout on the console:

xxxx@DESKTOP-8U2MCOG:~$ glxgears
Running synchronized to the vertical refresh.  The framerate should be
approximately the same as the monitor refresh rate.
23633 frames in 7.5 seconds = 3147.913 FPS
10395 frames in 6.8 seconds = 1529.523 FPS
10395 frames in 6.9 seconds = 1512.829 FPS

Now I'm pretty sure my monitor doesn't run at a vertical scan rate of 1500Hz! So I think this might be an indicator of what's really going on; some weirdness with the indirect rendering system. Also I notice that when I CTRL+C to end the program, the GL Window keeps running and animating for a good 10-11 seconds after I've terminated the program -- and that's if I've only run the program for 3-4 seconds. So I'd have to guess that there are a ton of messages getting queued up, or something like that...?

2
  • Focus on a single question. Because of how Superuser works, posts with more than one question are not allowed. To understand better it may be useful to read our Help section. Sep 30 '19 at 1:24
  • @music2myear yeah despite Q1-Q2-Q3 above I was making an effort to focus on a single question. Or, more accurately, I am working on a single problem (glxgears runs super slow in Ubuntu under Win10), and the list of questions represents my best way to take this vague problem and focus it into specific questions. As you can tell I found it tricky to focus this problem enough; if you have some suggestions on how to better focus the question I'm asking I'd be happy to have the input.
    – Mr. Snrub
    Sep 30 '19 at 2:08
14

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.

3
  • 1
    Thanks!! Disable LIBGL_ALWAYS_INDIRECT did the trick for me! To be faster, I just added a line in my .bashrc that says export LIBGL_ALWAYS_INDIRECT=0, and the results are the same as commenting out that line in wsl-integration.sh.
    – Tropilio
    Apr 15 '20 at 9:36
  • 1
    BTW, I am a bit confused... if LIBGL_ALWAYS_INDIRECT is set to 0 and we are not using native windows opengl (wgl), then who's doing the rendering now?! Also, it's a bit scary that now when I run glxgears, my notebook becomes really loud. Not fan noise, but really "electronic" noise, if it makes any sense...
    – Tropilio
    Apr 15 '20 at 9:55
  • 2
    If you run glxinfo, it will most likely tell you that your graphics device is llvmpipe (mesa3d.org/llvmpipe.html). Llvmpipe is a software renderer so the OpenGL is now rendered on the linux with your CPU. Jun 9 '20 at 1:52
7

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.

2
  • Thanks for this. Re item 1, LIBGL_ALWAYS_INDIRECT is already set. Re item 2, the second checkbox in the GUI launcher is "Native opengl Use the native windows opengl library (wgl)". The tutorial linked above says to leave this box unchecked, but I get the same slow behavior with this box checked or unchecked. So it's looking like 3 or 4 :-( BTW, the explanation about "indirect rendering" makes perfect sense, but I'm still wondering why it would be that slow, and also why it thinks it's doing thousands of frames per second.
    – Mr. Snrub
    Sep 30 '19 at 2:13
  • 1
    Following Mr. Snrub's answer, the solution turned out to be exactly the opposite of what you are suggesting: export LIBGL_ALWAYS_INDIRECT = 0 and NOT passing the -wgl flag to VcXsrv.
    – Tropilio
    Apr 15 '20 at 9:58
3

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.