配置好能够使用 GPU 的容器之后,突然想到是否可以使用高性能 GPU 来进行 Steam Link 呢。
使用远程 GPU 来启用 Xorg Server
X11 Forward
Xorg 是 C/S 架构的,原生支持通过网络来进行转发。然而,X11 Forward 实际上是使用本地硬件资源进行渲染的。当在自己的电脑上运行 X11 转发的 Steam ,另一台电脑上登陆的 Steam 则会立即显示「远程畅玩可用」。这时候使用的仍然是本地资源,并不是我们期望的。因此,要想让使用远程 GPU 进行渲染,那么就必须在远程启用 Xserver。
Remote Xserver
首先需要配置合适的 xorg.conf
。和通常的配置文件并无太多不同。
- 设备模块。
1 2 3 4 5 6
Section "Device" Identifier "Card0" Driver "nvidia" BusID "PCI:175:0:0" Option "AllowEmptyInitialConfiguration" EndSection
- 屏幕模块。自定义屏幕的 DPI ,否则就会使用默认的超小 DPI。
1 2 3 4 5 6 7 8 9 10 11 12 13
Section "Screen" Identifier "Screen0" Device "Card0" Monitor "Monitor0" DefaultDepth 24 Option "AllowEmptyInitialConfiguration" Option "HardDPMS" "false" SubSection "Display" Depth 24 Virtual 2560 1440 Option "DPI" "144x144" EndSubSection EndSection
然而发现在非特权模式下,容器内部始终无法启动 Xserver,似乎必须拿到 /dev/tty0 的读写权限才行。于是为了保持非特权模式的容器,最终选择在宿主机启动 Xerver,然后将其转发到内部网络中,再将容器内部的 DISPLAY 变量设置为外部宿主机启动的 Xserver 处。
可以使用 socat
将 unix socket 转为 TCP(或者直接在 LXC 配置中挂载进容器):
|
|
启动 Xserver 之后,可以看到 nvidia-smi
已经有了 Xorg 这个程序在跑了。
之后,就可以使用外部的 GPU 来渲染容器上跑的 GUI 程序了。简单的测试如 xclock
。
Indirect GLX 以及跑 32 位 的 Steam
然而,如果跑 GLX 程序,如 glxgears
时,则会报错。需要做的改动有两点:
- 在
xorg.conf
File 模块处添加 Nvidia 的 Xorg modules 的路径:1 2 3 4
Section "ServerFlags" Option "AllowIndirectGLX" "on" Option "IndirectGLX" "on" EndSection
- 在
xorg.conf
ServerFlags 处启用 Indirect GLX:1 2 3 4
Section "Files" ModulePath "/usr/lib/xorg/modules" ModulePath "/usr/lib/x86_64-linux-gnu/nvidia/xorg" EndSection
这下就可以运行 glxgears
,glxinfo
等程序了。那么是不是 Steam 也可以跑了呢?答案是否定的。Steam 一直以来都是 32 位的,而最新版的驱动都没有再支持 32 位的 GLX。Debian stable 上当时的 libglx-nvidia0:i386
包的版本是 418.152,与实际安装的驱动版本 455.23.05 差了很多。正当想放弃时,突然想显卡其实已经被驱动起来了,那么在容器内部也就没有必要执着于使用最新的驱动(无非只是一堆文件而已)。这样看来,容器化甚至成了一个好处,可以使得容器内选择性使用兼容的低版本库函数。
于是将容器内部的 libglx-nvidia0
包及其依赖统一替换为了有 i386 版本的低版本。终于可以将 32 位版本的 GLX 程序跑起来啦。
Ready for Steam Link?
最后需要做的一步是组网。Steam Link 要求两台设备必须在一个局域网之内。熟悉起见使用了 Wireguard 。 然而最后虽然已经确定在一个网段内了,还是无法正常使用 Steam Link ,原因出在无法连接一个公网端口上面,感觉有可能是需要两台设备有同样的公网出口来和 Steam 建立连接。
最终是还是失败了 😢 。
(本文纯属技术实验性质)