Skip to content

Instantly share code, notes, and snippets.

@lzlrd
Last active April 27, 2025 17:55
Show Gist options
  • Save lzlrd/0d9b757d2122f551794fd00c7f0752d6 to your computer and use it in GitHub Desktop.
Save lzlrd/0d9b757d2122f551794fd00c7f0752d6 to your computer and use it in GitHub Desktop.
How to get WSLg working with OpenGL, Vulkan, and CUDA on (Official) Arch Linux and Ubuntu WSL Instances.

WSLg with OpenGL, Vulkan, and CUDA on (Official) Arch Linux and Ubuntu WSL Instances

Note: I haven't documented CUDA here. I'm lazy (and haven't tested on Arch). See https://documentation.ubuntu.com/wsl/en/latest/howto/gpu-cuda for that on Ubuntu.

Context

microsoft/wslg#1312:

So I got this working on both Ubuntu, and Arch. First, start with a fresh install (of archlinux from https://gitlab.archlinux.org/archlinux/archlinux-wsl or Ubuntu from wsl --install Ubuntu or https://apps.microsoft.com/detail/9pdxgncfsczv).

Arch

  1. Install mesa and vulkan-dzn.
  2. Run echo "L+ /tmp/.X11-unix - - - - /mnt/wslg/.X11-unix" | sudo tee /etc/tmpfiles.d/wslg.conf. (Thanks to microsoft/wslg#43 (comment) for this.)
  3. Create your user account as per https://wiki.archlinux.org/title/Users_and_groups#User_management and confgure it as the default user for WSL as per https://wiki.archlinux.org/title/Install_Arch_Linux_on_WSL#Set_default_user.
  4. su into the user or open a new terminal tab/window.
  5. Run:
cat << EOF
export GALLIUM_DRIVER=d3d12

for i in "/mnt/wslg/runtime-dir/"*; do
  [ "$XDG_RUNTIME_DIR" = "$HOME" ] && XDG_RUNTIME_DIR="/var/run/user/$UID"
  if [ ! -L "$XDG_RUNTIME_DIR$(basename "$i")" ]; then
    [ -d "$XDG_RUNTIME_DIR$(basename "$i")" ] && rm -r "$XDG_RUNTIME_DIR$(basename "$i")"
    ln -s "$i" "$XDG_RUNTIME_DIR$(basename "$i")"
  fi
done
EOF | sudo tee /etc/profile.d/wslg.sh`
  1. Restart WSL with wsl --shutdown from CMD/PowerShell and you should see the following (given you install the relevant packages):
$ glxinfo | grep Device
    Device: D3D12 (NVIDIA GeForce RTX 4080 SUPER) (0xffffffff)

$ vulkaninfo | grep "GPU id"
WARNING: dzn is not a conformant Vulkan implementation, testing use only.
                GPU id = 0 (Microsoft Direct3D12 (NVIDIA GeForce RTX 4080 SUPER))
                GPU id = 1 (llvmpipe (LLVM 19.1.7, 256 bits))
                GPU id = 0 (Microsoft Direct3D12 (NVIDIA GeForce RTX 4080 SUPER))
                GPU id = 1 (llvmpipe (LLVM 19.1.7, 256 bits))
                GPU id = 0 (Microsoft Direct3D12 (NVIDIA GeForce RTX 4080 SUPER))
                GPU id = 1 (llvmpipe (LLVM 19.1.7, 256 bits))
GPU id : 0 (Microsoft Direct3D12 (NVIDIA GeForce RTX 4080 SUPER)):
GPU id : 1 (llvmpipe (LLVM 19.1.7, 256 bits)):

Ubuntu

  1. OpenGL should already be working. We'll add Vulkan support.
  2. Go to https://ppa.launchpadcontent.net/kisak/kisak-mesa/ubuntu/pool/main/m/mesa/.
  3. Look for mesa-vulkan-drivers_*.deb.
  4. You'll see ...<LETTER>_<ARCH>.deb. The letter corresponds to your Ubuntu version codename. In your case, "n" for Noble.
  5. Copy the link for the right package, https://ppa.launchpadcontent.net/kisak/kisak-mesa/ubuntu/pool/main/m/mesa/mesa-vulkan-drivers_25.0.1~kisak1~n_amd64.deb in your case.
  6. Run wget https://ppa.launchpadcontent.net/kisak/kisak-mesa/ubuntu/pool/main/m/mesa/mesa-vulkan-drivers_25.0.1~kisak1~n_amd64.deb anywhere you have write access to on the Ubuntu WSL instance.
  7. Run sudo apt install <PACKAGE> (in your case, sudo apt install mesa-vulkan-drivers_25.0.1~kisak1~n_amd64.deb.
  8. Run:
cat << EOF
export GALLIUM_DRIVER=d3d12

for i in "/mnt/wslg/runtime-dir/"*; do
  [ "$XDG_RUNTIME_DIR" = "$HOME" ] && XDG_RUNTIME_DIR="/var/run/user/$UID"
  if [ ! -L "$XDG_RUNTIME_DIR$(basename "$i")" ]; then
    [ -d "$XDG_RUNTIME_DIR$(basename "$i")" ] && rm -r "$XDG_RUNTIME_DIR$(basename "$i")"
    ln -s "$i" "$XDG_RUNTIME_DIR$(basename "$i")"
  fi
done
EOF | sudo tee /etc/profile.d/wslg.sh`
  1. You should see the following (given you install mesa-utils and vulkan-tools):
$ glxinfo | grep Device
WARNING: dzn is not a conformant Vulkan implementation, testing use only.
WARNING: Some incorrect rendering might occur because the selected Vulkan device (Microsoft Direct3D12 (NVIDIA GeForce RTX 4080 SUPER)) doesn't support base Zink requirements: feats.features.logicOp have_EXT_custom_border_color have_EXT_line_rasterization
    Device: D3D12 (NVIDIA GeForce RTX 4080 SUPER) (0xffffffff)

$ vulkaninfo | grep "GPU id"
WARNING: dzn is not a conformant Vulkan implementation, testing use only.
                GPU id = 0 (Microsoft Direct3D12 (NVIDIA GeForce RTX 4080 SUPER))
                GPU id = 1 (llvmpipe (LLVM 19.1.7, 256 bits))
                GPU id = 0 (Microsoft Direct3D12 (NVIDIA GeForce RTX 4080 SUPER))
                GPU id = 1 (llvmpipe (LLVM 19.1.7, 256 bits))
                GPU id = 0 (Microsoft Direct3D12 (NVIDIA GeForce RTX 4080 SUPER))
                GPU id = 1 (llvmpipe (LLVM 19.1.7, 256 bits))
GPU id : 0 (Microsoft Direct3D12 (NVIDIA GeForce RTX 4080 SUPER)):
GPU id : 1 (llvmpipe (LLVM 19.1.7, 256 bits)):

The reason we're using just the Vulkan driver from Kisak's repo. is that the mesa package causes llvmpipe to be used instead of D3D12. Maybe overring GALLIUM_DRIVER would work - I didn't try.

@lzlrd
Copy link
Author

lzlrd commented Mar 21, 2025

image

@lzlrd
Copy link
Author

lzlrd commented Mar 21, 2025

image

@lzlrd
Copy link
Author

lzlrd commented Mar 21, 2025

Updated the script to include adding [ -f "/etc/wsl.conf" ] && [ ! -L "/run/user/$UID/wayland-0" ] && ln -s "/mnt/wslg/runtime-dir/wayland-0" "/run/user/$UID/wayland-0" to your bash startup script. Unfortunately all forms of user-tmpfiles.d doesn't seem to work on WSL (likely due to how WSL logs in the default user) so we have to resort to this.

@ChuXiaoyuu
Copy link

Hello, I am using WSL, ubuntu24.04, with Geforce RTX5070Ti,cuda=12.8, I have configured according to the method you provided, but still cannot use GPU in OpenGL :(

$ glxinfo -B
name of display: :0
display: :0 screen: 0
direct rendering: Yes
Extended renderer info (GLX_MESA_query_renderer):
Vendor: Mesa (0xffffffff)
Device: llvmpipe (LLVM 17.0.6, 256 bits) (0xffffffff)
Version: 24.3.4
Accelerated: no
Video memory: 23726MB
Unified memory: yes
Preferred profile: core (0x1)
Max core profile version: 4.5
Max compat profile version: 4.5
Max GLES1 profile version: 1.1
Max GLES[23] profile version: 3.2
Memory info (GL_ATI_meminfo):
VBO free memory - total: 31 MB, largest block: 31 MB
VBO free aux. memory - total: 22905 MB, largest block: 22905 MB
Texture free memory - total: 31 MB, largest block: 31 MB
Texture free aux. memory - total: 22905 MB, largest block: 22905 MB
Renderbuffer free memory - total: 31 MB, largest block: 31 MB
Renderbuffer free aux. memory - total: 22905 MB, largest block: 22905 MB
Memory info (GL_NVX_gpu_memory_info):
Dedicated video memory: 4293168161 MB
Total available memory: 4293191887 MB
Currently available dedicated video memory: 31 MB
OpenGL vendor string: Mesa
OpenGL renderer string: llvmpipe (LLVM 17.0.6, 256 bits)
OpenGL core profile version string: 4.5 (Core Profile) Mesa 24.3.4 - kisak-mesa PPA
OpenGL core profile shading language version string: 4.50
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile

@lzlrd
Copy link
Author

lzlrd commented Mar 24, 2025

@ChuXiaoyuu, I've updated the guide. Can you try on a fresh distro to see if it works? OpenGL should work out of the box on Ubuntu.

EDIT: Updated once again to get around a bug where Pulse sub-folders are sometimes created (what are you doing Microsoft).

@ChuXiaoyuu
Copy link

@ChuXiaoyuu, I've updated the guide. Can you try on a fresh distro to see if it works?

Thank u for your reply! I followed your guide about Ubuntu, and I can add Vulkan support now, but OpenGL is still using the llvmpipe

$ glxinfo | grep Device
Device: llvmpipe (LLVM 17.0.6, 256 bits) (0xffffffff)

$ vulkaninfo | grep "GPU id"
WARNING: dzn is not a conformant Vulkan implementation, testing use only.
WARNING: dzn is not a conformant Vulkan implementation, testing use only.
GPU id = 0 (Microsoft Direct3D12 (NVIDIA GeForce RTX 5070 Ti))
GPU id = 1 (Microsoft Direct3D12 (Intel(R) Graphics))
GPU id = 2 (llvmpipe (LLVM 17.0.6, 256 bits))
GPU id = 0 (Microsoft Direct3D12 (NVIDIA GeForce RTX 5070 Ti))
GPU id = 1 (Microsoft Direct3D12 (Intel(R) Graphics))
GPU id = 2 (llvmpipe (LLVM 17.0.6, 256 bits))
GPU id = 0 (Microsoft Direct3D12 (NVIDIA GeForce RTX 5070 Ti))
GPU id = 1 (Microsoft Direct3D12 (Intel(R) Graphics))
GPU id = 2 (llvmpipe (LLVM 17.0.6, 256 bits))
GPU id : 0 (Microsoft Direct3D12 (NVIDIA GeForce RTX 5070 Ti)):
GPU id : 1 (Microsoft Direct3D12 (Intel(R) Graphics)):
GPU id : 2 (llvmpipe (LLVM 17.0.6, 256 bits)):
GPU id : 0 (Microsoft Direct3D12 (NVIDIA GeForce RTX 5070 Ti)):
GPU id : 1 (Microsoft Direct3D12 (Intel(R) Graphics)):
GPU id : 2 (llvmpipe (LLVM 17.0.6, 256 bits)):

@lzlrd
Copy link
Author

lzlrd commented Mar 26, 2025

@ChuXiaoyuu, I wonder if it's to do with Optimus...

Try running GALLIUM_DRIVER=d3d12 glxinfo | grep Device.

Though glxinfo should complain about dzn on Ubuntu as zink is supported (and will make Vulkan calls which brings up the dzn error). Did you install a custom mesa package (you should only install mesa-vulkan-drivers from the PPA, not mesa).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment