- systemd-user environment generator and appsandbox-gpu wrapper both append /usr/lib/wsl/lib to LD_LIBRARY_PATH. ldconfig has the .so.1 entries cached, but the 9P mount is read-only so the unversioned symlinks ldconfig wants to create can't be written. dlopen() of unversioned names (libcuda.so, libnvidia-encode.so, libnvcuvid.so) needs the path on LD_LIBRARY_PATH — without it ffmpeg's h264_nvenc / h264_cuvid plugins fail with 'Cannot load libcuda.so.1'. - setup.sh: symlink /usr/lib/wsl/lib/nvidia-smi to /usr/local/bin so the bare command works without env tweaks. Created unconditionally because the symlink target is resolved at exec time — the file appears under the agent's 9P mount on first boot regardless of when the symlink was created.
wsl-mesa — Mesa with d3d12 gallium + dzn Vulkan, prebuilt
Custom Mesa build that exposes Hyper-V GPU-PV (via /dev/dxg) to
userspace OpenGL and Vulkan workloads on a Linux guest, with zero
Microsoft proprietary blobs.
Meson flags:
-D gallium-drivers=llvmpipe,d3d12
-D vulkan-drivers=swrast,microsoft-experimental
-D microsoft-clc=enabled
-D video-codecs=all
-D glvnd=enabled
The two drivers we care about are both pure-open-source: Mesa's
d3d12 gallium driver and the microsoft-experimental Vulkan driver
(aka dzn, Direct3D 12 backend for Vulkan). Both reach the GPU
partition adapter via /dev/dxg ioctls directly — they ship their
own dxcore-equivalent code in src/microsoft/ so we don't need
libdxcore.so/libd3d12.so/libdirectml.so from a WSL2 install.
Layout
tools/wsl-mesa/
├── README.md
├── build/
│ └── build-mesa.sh ← reproduces a build on any 26.04 VM
└── prebuilt/
└── ubuntu-26.04-amd64/
├── wsl-mesa.tar.zst ← /opt/wsl-mesa tarball
└── BUILDINFO ← Mesa version, source commit, LLVM ver
Install on a Linux VM
sudo mkdir -p /opt/wsl-mesa
sudo zstd -d wsl-mesa.tar.zst -c | sudo tar -C / -x
echo /opt/wsl-mesa/lib/x86_64-linux-gnu | sudo tee /etc/ld.so.conf.d/wsl-mesa.conf
sudo ldconfig
# Vulkan ICD search:
sudo install -d /etc/vulkan/icd.d
sudo ln -sf /opt/wsl-mesa/share/vulkan/icd.d/dzn_icd.x86_64.json \
/etc/vulkan/icd.d/dzn_icd.x86_64.json
To opt in per-process instead of system-wide:
export LD_LIBRARY_PATH=/opt/wsl-mesa/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH
export VK_DRIVER_FILES=/opt/wsl-mesa/share/vulkan/icd.d/dzn_icd.x86_64.json
export __GLX_VENDOR_LIBRARY_NAME=mesa
export MESA_LOADER_DRIVER_OVERRIDE=d3d12
Why a separate prefix
Installing to /opt/wsl-mesa instead of /usr keeps Ubuntu's apt
Mesa intact. apt upgrade mesa-* won't clobber our build, and we
won't break apps that need stock Mesa. Switch is via ld.so.conf.d
or per-process env vars.
Versioning
Prebuilt artifacts are keyed on <ubuntu-codename>-<arch> since the
binaries are tied to glibc and libstdc++ ABIs, not kernel versions
(unlike dxgkrnl). One subdir per supported distro tuple.
Rebuilding
Run build/build-mesa.sh on a VM with the target codename installed.
Takes ~30 min on a 6-core machine. The script handles deps, source
fetch, meson configure, ninja build, and install.