D3D12 GPU Video acceleration in the Windows Subsystem for Linux now available!

Sil Vilerino

Introduction

In DirectX ❤ Linux – DirectX Developer Blog we wrote about DXCore & D3D12 support on WSLg and described OpenGL & OpenCL support by adding a D3D12 backend to Mesa 3D, allowing such 3D and compute workloads to be offloaded to the GPU.

Gstreamer playing an mp4 video in an X11 Windows in WSL using GPU acceleration.
3 Gstreamer playing an mp4 video in an X11 Windows in WSL using GPU acceleration.

To extend the types of workloads that we can accelerate with the GPU in WSLg, we also recently added support for GPU Video Acceleration by building on top of the existing Mesa 3D D3D12 backend and integrating the VAAPI mesa frontend. Several linux media apps use the VAAPI interface to access hardware video acceleration when available, and this can now be leveraged in WSLg.

When decoding, encoding or processing a video, you have the option to do so using the CPU or -when available- offload it to accelerator hardware, usually delegating it to the GPU. Leveraging video hardware acceleration instead of using the CPU usually has several benefits: increased performance, lower power consumption and it frees up those CPU cycles to be available for other tasks in WSL or even in the Windows host, increasing overall performance. The benefits of using the GPU increase as the resolution of the video gets higher.

When running the samples at the end of this post, you can check out in the Windows Task Manager the CPU/GPU usage difference when enabling WSLg hardware video acceleration or when using the CPU. More information about this at: GPUs in the task manager – DirectX Developer Blog.

Scenarios

Customers can now run video workloads such as decode, encode and video processing in WSLg accelerated on the GPU with apps supporting VAAPI, for example: FFmpeg or GStreamer. The following are the VA entrypoints and profiles implemented on top of D3D12.

Profile name

Entrypoint name

Mesa version required

VAProfileH264ConstrainedBaseline VAEntrypointVLD 22.2
VAProfileH264ConstrainedBaseline VAEntrypointEncSlice 22.2
VAProfileH264Main VAEntrypointVLD 22.2
VAProfileH264Main VAEntrypointEncSlice 22.2
VAProfileH264High VAEntrypointVLD 22.2
VAProfileH264High VAEntrypointEncSlice 22.2
VAProfileHEVCMain VAEntrypointVLD 22.3
VAProfileHEVCMain VAEntrypointEncSlice 22.3
VAProfileHEVCMain10 VAEntrypointVLD 22.3
VAProfileHEVCMain10 VAEntrypointEncSlice 22.3
VAProfileVP9Profile0 VAEntrypointVLD 22.3
VAProfileVP9Profile2 VAEntrypointVLD 22.3
VAProfileAV1Profile0 VAEntrypointVLD 22.3
VAProfileNone VAEntrypointVideoProc 22.2

This list is illustrative of a GPU and vendor driver supporting all possible entrypoints/profiles using mesa 22.3. The actual capabilities reported in vaQueryConfigProfiles, vaQueryConfigEntrypoints , vaQueryConfigAttributes, VaQueryVideoProcPipelineCaps and others are dynamically queried from the underlying GPU and might vary between platforms and driver versions. The vainfo utility will list the actual subset of entrypoints/profiles supported by your hardware and applications will adjust to the available features reported.

Installation

Required components

  1. Install Windows Subsystem for Linux – Microsoft Store Apps (version 1.1.0 or newer)
  2. Install a distro like Ubuntu 22.04.1 LTS – Microsoft Store Apps
  3. Enable systemd in WSL.
  4. Follow the table in the hardware platforms support section and install a GPU driver from your vendor’s website with a version higher or equal than specified.

About package manager repositories

The scenarios mentioned in this article are upstreamed to mesa/main and available in mesa 22.2.0 and mesa 22.3.0 stable releases. However, it takes time for the distros to refresh their package repositories to pick up new versions and when you install mesa-va-drivers you may get an older version until they’re updated automatically after some time.

For example, in distros with apt you can check the latest available version in the repositories with the commands:

sudo apt-get update
apt list mesa-va-drivers -a

If the available mesa version in your distro is older than the mesa version required for the profile/entrypoint from the “Scenarios” section table you’d like to try, there are a couple of different options you choose to follow, described below.

Option 1. Build mesa from source code

In this option, you will build and install mesa from the mesa-22.3.0.tar.xz release or newer. If you follow this route, you can skip installing the mesa-va-drivers package in the section “Setting up Video acceleration in WSLg”.

  1. Make sure to include the following meson configuration flags
-Dgallium-drivers=swrast,d3d12 -Dgallium-va=true -Dvideo-codecs=h264dec,h264enc,h265dec,h265enc,vc1dec
  1. Build and install mesa
  2. Set the LIBVA_DRIVERS_PATH environment variable to the directory containing the custom built and installed d3d12_drv_video.so. You may want to add this in your ~/.bashrc file as it’s necessary on every new WSL console session.
  3. Follow the instructions in the section “Setting up Video acceleration in WSLg”.

Option 2. Use a 3rd party repository for the mesa library packages

Adding the 3rd party repository

In Ubuntu 22.04 and newer, you can add this 3rd party repository to make available the bleeding edge/unstable daily mesa packages built from mesa/main with the following commands.

sudo add-apt-repository ppa:oibaf/graphics-drivers
sudo apt-get update && sudo apt-get upgrade

After adding the repository, follow the instructions in the section “Setting up Video acceleration in WSLg”.

Removing the 3rd party repository

In the case you added the ppa:oibaf repository and followed the setup steps in the section “Setting up Video acceleration in WSLg”, and now want to revert back to the previous state, please follow these steps.

sudo apt-get install ppa-purge
sudo ppa-purge ppa:oibaf/graphics-drivers
sudo apt-get update && sudo apt-get upgrade

Setting up Video acceleration in WSLg

Open the WSL console and run the following commands to install the required components. The following steps use the apt package manager, but you may replace it with the appropriate equivalent on your distro.

1.Make sure you have the latest updates installed

sudo apt-get update && sudo apt-get upgrade

2. Install vainfo (and libva dependencies)

sudo apt-get install vainfo

3. *Install mesa libraries *(skip this if built from mesa source code)

sudo apt-get mesa-va-drivers

4. Configure libva environment. You may want to add this in your ~/.bashrc file as it’s necessary on every new WSL console session.

export LIBVA_DRIVER_NAME=d3d12

5. Enumerate libva capabilities for your current hardware

vainfo --display drm --device /dev/dri/card0

The vainfo utility will indicate the libva and mesa versions installed and list the subset of entrypoints and profiles supported by your hardware, for example:

vainfo: VA-API version: 1.15 (libva 2.12.0)
vainfo: Driver version: Mesa Gallium driver 22.2.1 for D3D12
vainfo: Supported profile and entrypoints
VAProfileH264ConstrainedBaseline: VAEntrypointVLD
VAProfileH264ConstrainedBaseline: VAEntrypointEncSlice
VAProfileH264Main               : VAEntrypointVLD
VAProfileH264Main               : VAEntrypointEncSlice
VAProfileH264High               : VAEntrypointVLD
VAProfileH264High               : VAEntrypointEncSlice
VAProfileNone                   : VAEntrypointVideoProc

This list is illustrative of a GPU supporting only a subset of the implemented features on the indicated libva/mesa versions.

Adding the “-a” argument to the vainfo command will give you more detailed support information such as rate control modes, max reference frames, slice modes, etc for each entrypoint/profile available on your hardware.

Examples using GPU Video acceleration

Gstreamer in WSL performing GPU accelerated alpha blend composition and rendering into an X11 window
]16 Gstreamer in WSL performing GPU accelerated alpha blend composition and rendering into an X11 window

You can now install some media apps with VA acceleration and use GPU video acceleration, below are some examples you can try. Please check that the mesa version and the entrypoints required for each example are supported on your platform by checking the vainfo utility.

The Windows Task Manager will show the CPU/GPU usage for each of these samples, and you can compare the results for different samples using CPU only or GPU acceleration.

To begin please follow the steps below to install ffmpeg and/or gstreamer and then you can try some of the command line samples below.

Install ffmpeg and gstreamer

sudo apt-get install ffmpeg
sudo apt-get install gstreamer1.0-plugins-bad gstreamer1.0-tools gstreamer1.0-vaapi

Command line examples

1.Requires mesa 22.2 + H264 VAEntrypointEncSlice. Generate 250 test frames and encode to an H.264 file using the GPU with VAAPI.

gst-launch-1.0 -v videotestsrc num-buffers=250 ! video/x-raw,width=1920,height=1200 ! vaapipostproc ! vaapih264enc ! filesink location=~/wsl_test.h264

2. Requires mesa 22.2 + H264 VAEntrypointVLD. Decode wsl_test.h264 using the GPU with VAAPI and encode using H264 software encoder.

gst-launch-1.0 -v -m filesrc location=~/wsl_test.h264 ! h264parse ! vaapih264dec ! x264enc qp-max=5 tune=zerolatency ! filesink location=~/x264enc_output.h264

3. Requires mesa 22.2 + H264 VAEntrypointVLD + VAEntrypointEncSlice. Decode wsl_test.h264 using the GPU with VAAPI and encode using the GPU VAAPI encoder.

gst-launch-1.0 -v -m filesrc location=~/wsl_test.h264 ! h264parse ! vaapih264dec ! vaapih264enc ! filesink location=~/va264enc_output.h264

4. Requires mesa 22.2 + H264 VAEntrypointVLD + VAEntrypointEncSlice + VaQueryVideoProcPipelineCaps supporting scale + rotation. Decode wsl_test.h264 using the GPU with VAAPI, scale, rotate and encode using the GPU VAAPI encoder.

gst-launch-1.0 -v -m filesrc location=~/wsl_test.h264 ! h264parse ! vaapih264dec ! vaapipostproc width=800 height=600 video-direction=180 ! vaapih264enc ! filesink location=~/va264enc_proc_output.h264

5. Requires mesa 22.3 + H264 VAEntrypointVLD + HEVC VAEntrypointEncSlice + VaQueryVideoProcPipelineCaps supporting scale. Decode wsl_test.h264 using the H264 GPU decoder, scale it using the GPU video processor, and re-encode it using the H265 GPU encoder.

ffmpeg -hwaccel vaapi -hwaccel_output_format vaapi -hwaccel_device /dev/dri/card0 -i ~/wsl_test.h264 -vf 'scale_vaapi=w=640:h=480' -c:v hevc_vaapi ~/scaled_output.h265

6. Requires mesa 22.3 + HEVC VAEntrypointVLD. Given an H265 file, play it in window using the GPU decoder.

gst-launch-1.0 -vf filesrc location=~/scaled_output.h265 ! h265parse ! vaapih265dec ! autovideosink

7. Transcode wsl_test.h264 using only the CPU. This sample is intended for comparison with the next one which uses GPU acceleration.

ffmpeg -i ~/wsl_test.h264 -c:v h264 ~/output_sw.h264

8. Requires mesa 22.2 + H264 VAEntrypointVLD + H264 VAEntrypointEncSlice. Transcode wsl_test.h264 using only the GPU.

ffmpeg -hwaccel vaapi -hwaccel_output_format vaapi -hwaccel_device /dev/dri/card0 -i ~/wsl_test.h264 -c:v h264_vaapi ~/output_hw.h264

Here you can find the related command line documentation for ffmpeg and gstreamer plugins used in the command lines for further reference.

Hardware platforms support

Please see below the list of hardware platforms that currently have support for Video acceleration in WSLg.

Vendor Supported platforms Minimum video driver version
AMD

Radeon RX 5000 series or greater

Ryzen 4000 series or greater

Adrenalin 23.3.1

ETA March 2023

Intel

11th Gen Intel® Core™ processor family (Codename Tiger Lake, Rocket Lake)

12th Gen Intel® Core™ processor family (Codename Alder Lake)

13th Gen Intel® Core™ processor family (Codename Raptor Lake)

Intel® Iris® Xe Dedicated Graphics family (Codename DG1)

Intel® Arc® Graphics family (Codename Alchemist)

31.0.101.4032
NVIDIA

GeForce GTX 10 Series and newer

GeForce RTX 20 Series and newer

Quadro RTX

NVIDIA RTX

526.47