在WSLg中使用GPU加速视频处理和编解码!
微软最近为WSLg提供了基于D3D12的GPU视频处理和编解码加速!官方在博客 D3D12 GPU Video acceleration in the Windows Subsystem for Linux now available! 给出了相关教程。已经迫不及待想要尝试了!
项目介绍
在build 2020微软就宣布为WSL2带来GPU硬件加速,在Linux中实现了完整的D3D12 API,并且简化DXGI为DXCORE,使得UMD和KMD可以交互。DirectX ❤ Linux有更详细的介绍,我们以后再研究。WSLg中的硬件加速首先被用于3D渲染和计算,而现在又应用在视频处理。微软为Mesa添加了D3D12后端,使用VAAPI作为前端。理论上使用VAAPI的app都可以在WSLg中享受到硬件加速(FFMPEG/gstreamer狂喜)。
如何使用
硬件要求
没有找到官方的说明。参考博客里给的表格。
- Intel: TGL,RKL,ADL,RPL,DG1,DG2
- AMD: RX 5000+,Ryzen 4000+
- Nvidia: GTX10,GTX20,Quadro RTX,RTX
需要的环境
- WSL 1.1.0+。该版本在本文截稿时还是pre-release的状态,因此需要安装WSL preview,而WSL preview又需要preview的Windows,我不得不加入了已经退出很多年的Windows Insider,再次成为微软的小白鼠。我选择的是相对稳定的Beta通道。
- 安装一个Linux发行版,比如ubuntu 22.04 LTS。我使用的是已经安装的Ubuntu 20.04.
- 在WSL中开启systemd。官方也给出了参考教程。Systemd support is now available in WSL!
相关依赖
接下来需要安装Mesa,并且需要Mesa 22.2.0+。先查看当前使用的发行版提供的最新的Mesa版本。
1
2
3
sudo apt-get update
apt list mesa-va-drivers -a
Listing... Done
对应输出:
1
2
3
Listing... Done
mesa-va-drivers/focal-updates,focal-security,now 21.2.6-0ubuntu0.1~20.04.2 amd64 [installed]
mesa-va-drivers/focal 20.0.4-2ubuntu1 amd64
emm,只支持到Mesa 21.2.6。看来我们要自己编译Mesa了。注意,Ubuntu 22.04以上可以选择第三方编译好的Mesa:
1
2
3
sudo add-apt-repository ppa:oibaf/graphics-drivers
sudo apt-get update && sudo apt-get upgrade
sudo apt-get mesa-va-drivers
如果是Ubuntu 20.04,我们只能自己编译Mesa,先下载源码并解压(建议使用代理):
1
2
wget https://archive.mesa3d.org/mesa-22.3.0.tar.xz
tar -xvf mesa-22.3.0.tar.xz
然后编译Mesa:
1
2
sudo apt install meson
meson build -Dgallium-drivers=swrast,d3d12 -Dgallium-va=true -Dvideo-codecs=h264dec,h264enc,h265dec,h265enc,vc1dec
遇到开门错:
1
2
3
4
5
Dependency DirectX-Headers from subproject subprojects/DirectX-Headers found: YES 1.606.4
Run-time dependency vdpau found: NO (tried pkgconfig and cmake)
Program glslangValidator found: NO
meson.build:693:2: ERROR: Program(s) ['glslangValidator'] not found or not executable
看来还有依赖不全。直接然后再次meson build:
1
sudo apt-get install glslang-tools
啊啊啊又有新的错:
1
meson.build:804:2: ERROR: Dependency "libva" not found, tried pkgconfig and cmake
这个我熟,libva没装:
1
sudo apt install libva-dev
再次报错。hhh对libva版本还有要求:
1
meson.build:804:2: ERROR: Invalid version of dependency, need 'libva' ['>= 1.8.0'] found '1.7.0'.
受不了了,直接编一个libva吧:
1
2
3
4
sudo apt install autoconf libtool
git clone https://github.com/intel/libva.git
cd libva & ./autogen.sh --prefix=/usr --libdir=/usr/lib/x86_64-linux-gnu
make & sudo make install
然而vainfo还是报了链接错误:
1
vainfo: symbol lookup error: /lib/x86_64-linux-gnu/libva-x11.so.2: undefined symbol: va_fool_postp
va_fool_postp在libva 2.15就已经被remove了,我们把libva reset到2.15重新编译安装就好。这里我还遇到了多个版本的libva.so安装在/lib/x86_64-linux-gnu/下,建议直接(不要怕):
1
rm -rf /lib/x86_64-linux-gnu/libva.so*
然后再安装libva。接下来再尝试编译Mesa,错误依旧没完:
1
meson.build:999:2: ERROR: Problem encountered: Python (3.x) mako module >= 0.8.0 required to build mesa.
python的依赖不全。直接进行一个安装:
1
2
sudo apt install python3-pip
pip3 install mako
这下Mesa可以build了吧?哈哈哈并不可以:
1
meson.build:1700:4: ERROR: Invalid version of dependency, need 'libdrm_amdgpu' ['>=2.4.110'] found '2.4.107'.
行,那我们还是自己编一个libdrm:
1
2
3
git clone https://gitlab.freedesktop.org/mesa/drm.git
cd drm & meson build
ninja build && sudo ninja -C build install
然后build Mesa又双叒叕报错了:
1
meson.build:1794:2: ERROR: Subproject directory not found and llvm.wrap file not found
再进行一个llvm-config的安装:
1
sudo apt install llvm-11
怎么还是找不到llvm-config啊?搜索一翻,发现
1
which llvm-config
没有输出,但是
1
which llvm-config-11
有结果:
1
/usr/bin/llvm-config-11
无语。尝试alias设置别名,未果。我几乎快要放弃了,又想去用master branch上的Mesa编译试试:
1
2
git clone https://gitlab.freedesktop.org/mesa/mesa.git
cd mesa && meson build -Dgallium-drivers=swrast,d3d12 -Dgallium-va=enabled -Dvideo-codecs=h264dec,h264enc,h265dec,h265enc,vc1dec
这里要升级meson版本,并且编译参数有所不同。欸嘿,这下子它总算找到llvm-config了。又遇到几个依赖没装:
1
sudo apt install libelf-dev byacc bison flex wayland-protocols
之后又卡在了wayland-protocols这一步:
1
2
3
4
Dependency wayland-protocols found: NO found 1.20 but need: '>= 1.24'
Run-time dependency wayland-protocols found: NO (tried cmake)
meson.build:1883:2: ERROR: Dependency lookup for wayland-protocols with method 'pkgconfig' failed: Invalid version, need 'wayland-protocols' ['>= 1.24'] found '1.20'.
大不了我们再build一个wayland-protocols。。。然后又发现需要更新wayland的某些component。。。我已经几乎快要忘了原来的目的是什么。。。坚持一下。。。
1
2
3
4
git clone https://gitlab.freedesktop.org/wayland/wayland.git
cd wayland && meson build && ninja -C build && sudo ninja -C build install
git clone https://gitlab.freedesktop.org/wayland/wayland-protocols.git
cd wayland-protocols && meson build && ninja -C build && sudo ninja -C build install
此处遇到了好几个依赖,直接apt安装即可。
1
sudo apt install libxml2-dev graphviz doxygen xsltproc xmlto
终于我们可以继续build Mesa了。。。嗯,需要安装亿些依赖:
1
sudo apt install libxcb-glx0-dev libxcb-shm0-dev libx11-xcb-dev libxcb-dri2-0-dev libxcb-dri3-dev libxcb-present-dev libxshmfence-dev
!!!终于配置成功了。愉快的编译时间:
1
ninja -C build && sudo ninja -C build install
我的12600k花了两分钟也就,这还是在WSL里,本来还准备喝个咖啡去。。。
然后vainfo看下driver binary能不能work:
1
2
export LIBVA_DRIVER_NAME=d3d12
vainfo --display drm --device /dev/dri/card0
又是当头一棒:
1
2
3
4
5
libva info: VA-API version 1.15.0
libva info: User environment variable requested driver 'd3d12'
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/d3d12_drv_video.so
libva info: va_openDriver() returns -1
vaInitialize failed with error code -1 (unknown libva error),exit
.so没安装都。。。瞄了一眼安装log的最后一行:
1
installing /home/jianhuyy/mesa/mesa/build/src/gallium/targets/va/libgallium_drv_video.so to /usr/local/lib/x86_64-linux-gnu/dri/d3d12_drv_video.so
因为没有设安装路径,安装到了/usr/local/lib/x86_64-linux-gnu/dri/下面。直接copy过去:
1
sudo cp /usr/local/lib/x86_64-linux-gnu/dri/* /usr/lib/x86_64-linux-gnu/dri/
vainfo不报错了,但是:
1
2
3
4
5
6
7
8
9
libva info: VA-API version 1.15.0
libva info: User environment variable requested driver 'd3d12'
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/d3d12_drv_video.so
libva info: Found init function __vaDriverInit_1_15
libva info: va_openDriver() returns 0
vainfo: VA-API version: 1.15 (libva 2.6.0)
vainfo: Driver version: Mesa Gallium driver 23.1.0-devel for D3D12 (Intel(R) UHD Graphics 770)
vainfo: Supported profile and entrypoints
VAProfileNone : VAEntrypointVideoProc
只有video processing的capability report出来了,codec全部阵亡。。。这合理吗?
合理的,Windows显卡驱动需要更新。我用的driver是Windows自动给我安装的,我甚至不想去官网下,因为官网的driver package包含了一个非常难用的Arc Control,which与NV的GeForce Experience类似。但是我这个核显给我整个给独显的控制面板干什么,核显也配叫锐炫吗?这个Arc Control甚至不能自动更新驱动。。。很不情愿地把驱动更新到官网最新的4091(原本是3616),我们终于能看到codec capabilities被report出来了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
libva info: VA-API version 1.15.0
libva info: User environment variable requested driver 'd3d12'
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/d3d12_drv_video.so
libva info: Found init function __vaDriverInit_1_15
libva info: va_openDriver() returns 0
vainfo: VA-API version: 1.15 (libva 2.6.0)
vainfo: Driver version: Mesa Gallium driver 23.1.0-devel for D3D12 (Intel(R) UHD Graphics 770)
vainfo: Supported profile and entrypoints
VAProfileH264ConstrainedBaseline: VAEntrypointVLD
VAProfileH264ConstrainedBaseline: VAEntrypointEncSlice
VAProfileH264Main : VAEntrypointVLD
VAProfileH264Main : VAEntrypointEncSlice
VAProfileH264High : VAEntrypointVLD
VAProfileH264High : VAEntrypointEncSlice
VAProfileHEVCMain : VAEntrypointVLD
VAProfileHEVCMain : VAEntrypointEncSlice
VAProfileHEVCMain10 : VAEntrypointVLD
VAProfileHEVCMain10 : VAEntrypointEncSlice
VAProfileVP9Profile0 : VAEntrypointVLD
VAProfileVP9Profile2 : VAEntrypointVLD
VAProfileAV1Profile0 : VAEntrypointVLD
VAProfileNone : VAEntrypointVideoProc
H264/HEVC/VP9/AV1全都支持了。看来VP相比于codec先enable了WSL。。。按照微软官方博客的表格,各个codec不是一个Mesa版本支持的。
终于可以使用了
整个环境的配置实在太过艰辛,花了一个下午一个晚上才搞定,而且测试还需要找一段码流,我们就下一篇文章再讲吧!那是不可能的。我们随手找了一个AVC的码流,用FFMPEG测试下转码:
1
2
3
sudo apt-get install ffmpeg
sudo apt-get install gstreamer1.0-plugins-bad gstreamer1.0-tools gstreamer1.0-vaapi
先试下CPU转码:
1
2
ffmpeg -i ~/dota2.mp4 -c:v h264 ~/output_sw.h264
此时一个名为VmmemWSL的进程直接让CPU满载。
再看下核显转码:
1
2
ffmpeg -hwaccel vaapi -hwaccel_output_format vaapi -hwaccel_device /dev/dri/card0 -i ~/dota2.mp4 -c:v h264_vaapi ~/output_hw.h264
可以看到decode engine的workload,调用进程为“虚拟机工作进程”。WSLg中你甚至可以直接播放视频:
1
ffplay dota2.mp4
WSLg会直接弹出播放视频的GUI,奇怪的是taskmgr显示workload在3D上。
总结
尽管历经周折,我们还是成功完成了在WSLg中调用GPU进行视频加速。几点小小的感想:
- 再次鞭挞CPP,人生苦短,别用CPP。高贵的语法特性,配合X一样的包管理,学起来那叫一个酸爽。还好这次耐心足够,不然多半是半途而废体验不到这个项目了。
- WSL是越来越有意思了。过去用VMware装一个虚拟机还需要一通操作,体验比原生系统差太多。现在WSL无缝集成到Windows,打开商店即可安装,无需繁琐的配置,十分方便。配合VSC开发体验极佳,现在硬件加速功能也逐渐完善,尽管WSL2退回到了虚拟机,但完全感觉不到它的存在,打开一个terminal就能直接使用。WSLg支持了GUI,以前尝试过在WSL1中跑虚拟仿真软件Gazebo,还需要设置xserver才能跑界面,并且整个GUI都是用CPU渲染的。。。WSLg微软直接帮你做好了。
- 再次体验了Arc Control,尽管界面挺好看的,但是它开机会弹出UAC,我还是决定不留情面将它卸载。。。
后面可能会研究一下微软用了什么科技实现这个项目。