VirtualGL

出自 ArchWiki

本文或章节需要改进语言、wiki 语法或风格。请参阅 Help:Style 以供参考。

原因: 页面非常难以阅读,而且这还是在进入编辑标签并尝试理解原始文本之前。(在 Talk:VirtualGL 中讨论)

VirtualGL 将应用程序的OpenGL/GLX 命令重定向到一个单独的 X 服务器(该服务器可以访问 3D 显卡),捕获渲染的图像,然后将它们流式传输到实际处理应用程序的 X 服务器。

主要用例是为远程桌面设置启用服务器端硬件加速 3D 渲染,其中处理应用程序的 X 服务器位于网络的另一端(在 X11 转发的情况下),或者是一个无法访问图形硬件的“虚拟”X 服务器(在 VNC 的情况下)

安装与设置

本文或章节需要扩充。

原因: 请使用模板的第一个参数提供简要说明。 (在 Talk:VirtualGL#移至主命名空间并扩充 中讨论)

使用 pacman 安装 virtualgl 软件包,然后按照 将 Linux 或 Unix 机器配置为 VirtualGL 服务器 进行配置。在 Arch 上,/opt/VirtualGL/bin/vglserver_config 就是 vglserver_config,而 /opt/VirtualGL/bin/glxinfo 就是 vglxinfo

用法

使用 X11 转发

本文或章节需要扩充。

原因: 请使用模板的第一个参数提供简要说明。 (在 Talk:VirtualGL 中讨论)
  server:                                              client:
 ······································               ·················
 : ┌───────────┐ X11 commands         :               : ┌───────────┐ :
 : │application│━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━▶│X server 2)│ :
 : │           │        ┌───────────┐ :               : │           │ :
 : │           │        │X server 1)│ :               : ├┈┈┈┈┈┈┈┈┈╮ │ :
 : │ ╭┈┈┈┈┈┈┈┈┈┤ OpenGL │ ╭┈┈┈┈┈┈┈┈┈┤ : image stream  : │VirtualGL┊ │ :
 : │ ┊VirtualGL│━━━━━━━▶│ ┊VirtualGL│━━━━━━━━━━━━━━━━━━▶│client   ┊ │ :
 : └─┴─────────┘        └─┴─────────┘ :               : └─────────┴─┘ :
 ······································               ·················
  1. “3D” 渲染发生在此处
  2. “2D” 渲染发生在此处

VirtualGL 与 VNC 相比,此设置的优点

  • 无缝窗口
  • 服务器端使用的 CPU 资源稍少
  • 支持立体渲染(用于使用“3D 眼镜”观看)

步骤

1. 准备工作

除了在远程服务器上设置 VirtualGL 如上所述,此用法场景还需要您:

  • 在客户端也安装 virtualgl 软件包(但无需像在服务器端那样设置它,我们只需要此端的 vglconnectvglclient 二进制文件)
  • 设置 带有 X11 转发的 SSH (确认从客户端通过 ssh -X user@server 连接到服务器,并在生成的 shell 中运行 GUI 应用程序可以正常工作)

2. 连接

现在您可以随时在客户端计算机上使用 vglconnect 连接到服务器

$ vglconnect user@server     # X11 traffic encrypted, VGL image stream unencrypted
$ vglconnect -s user@server  # both X11 traffic and VGL image stream encrypted

这会打开一个带有 X11 转发的 SSH 会话,就像 ssh -X 一样,并且还会自动使用正确的参数启动 VirtualGL 客户端(vglclient)作为后台守护程序。此守护程序将处理来自服务器的传入 VirtualGL 图像流,并且即使您关闭 SSH shell 后也会在后台继续运行 - 您可以使用 vglclient -kill 停止它。

3. 运行应用程序

连接后,您可以通过在 SSH shell 中使用 vglrun 启动远程应用程序,为其 OpenGL 部分启用 VirtualGL 渲染,如下面的 运行应用程序 中所述。

您无需将自己限制为 vglconnect 为您打开的 shell;您从客户端上的同一 X 会话打开到同一 user@server 的任何 ssh -Xssh -Y shell 都应该可以工作。 vglrun 将检测到您在 SSH shell 中,并确保 VGL 图像流通过网络发送到属于 SSH 客户端的 IP/主机名(正在运行的 vglclient 实例将在那里拦截并处理它)。

使用 VNC

本文或章节需要扩充。

原因: 请使用模板的第一个参数提供简要说明。 (在 Talk:VirtualGL 中讨论)
  server:                                                              client:
 ······················································               ················
 : ┌───────────┐ X11 commands         ┌─────────────┐ : image stream  : ┌──────────┐ :
 : │application│━━━━━━━━━━━━━━━━━━━━━▶│VNC server 2)│━━━━━━━━━━━━━━━━━━▶│VNC viewer│ :
 : │           │        ┌───────────┐ └─────────────┘ :               : └──────────┘ :
 : │           │        │X server 1)│        ▲        :               :              :
 : │ ╭┈┈┈┈┈┈┈┈┈┤ OpenGL │ ╭┈┈┈┈┈┈┈┈┈┤ images ┃        :               :              :
 : │ ┊VirtualGL│━━━━━━━▶│ ┊VirtualGL│━━━━━━━━┛        :               :              :
 : └─┴─────────┘        └─┴─────────┘                 :               :              :
 ······················································               ················
  1. “3D” 渲染发生在此处
  2. “2D” 渲染发生在此处

VirtualGL 与 X11 转发 相比,此设置的优点

  • 在低带宽/高延迟网络的情况下,可以保持更好的性能
  • 可以将相同的图像流发送到多个客户端(“桌面共享”)
  • 即使网络连接中断,远程应用程序也可以继续运行
  • 更好地支持非 Linux 客户端,因为该架构不依赖于客户端 X 服务器

步骤

在远程服务器上设置 VirtualGL 如上所述,并使用您选择的 VNC 客户端/服务器 实现建立工作远程桌面连接后,无需进一步配置。

在 VNC 会话中(例如,在 VNC 桌面中的终端模拟器中,甚至直接在 ~/.vnc/xstartup 中),只需使用 vglrun 运行选定的应用程序,如下面的 运行应用程序 中所述。

您也可以使用 vglrun 运行整个会话,以便所有 opengl 应用程序默认情况下都能工作。例如,如果您使用 xfce,您可以在 X 启动脚本(~/.vnc/xstartup.xinitrc 或等效脚本)中运行 vglrun startxfce4 而不是 startxfce4,或者如果您使用显示管理器,则可以复制并编辑 /usr/share/xsessions 中的 .desktop 文件。

选择合适的 VNC 软件包

VirtualGL 可以为任何通用的 vncserver 实现(例如 TightVNC、RealVNC、...)提供 3D 渲染。

但是,如果您想真正从中获得良好的性能(例如,使其能够在 VNC 上观看视频或玩 OpenGL 游戏),您可能需要使用专门为此用例优化的 VNC 实现之一

  • turbovncAUR:由与 VirtualGL 相同的团队开发,其明确目标是提供与 VirtualGL 结合的最佳性能。但是,它的 vncserver 实现不支持普通 Xorg 服务器提供的所有功能,因此某些应用程序在其中运行会异常缓慢或根本无法运行。
  • TigerVNC:也是考虑到 VirtualGL 而开发的,并且在使用 VirtualGL 时实现了良好的性能,同时比 TurboVNC 提供更好的 Xorg 兼容性。

使用 Xpra

在您的主机上

  • 准备一个最小的 xinit 资源文件,该文件仅锁定您的 Xorg 服务器的显示器
~/.xinitrc-vgl
/usr/bin/xrdb ~/.Xresources
exec slock
  • 使用准备好的资源文件 startx ~/.xinitrc-vgl 启动 Xorg 服务器。现在,pgrep xorg 应该返回两个 Xorg 实例。
  • 通过 vglrun 命令运行应用程序,指定您的 Xpra 使用的 Xorg 显示器,例如 DISPLAY=:7 vglrun glxspheres64。该应用程序尚不可见。

在您的客户端上

  • 在客户端设置 Xpra 并 附加到它。现在您应该看到上面启动的 glxspheres64 应用程序。
注意
  • 通过网络附加时使用 ssh 连接。不需要 X 转发。此外,在客户端设置 ssh 密钥对,并将 公钥复制到远程主机
  • 无密码的 ssh 密钥对更方便。此外,在后台运行时,xpra attach 不会要求输入密码。

运行应用程序

设置好支持 VirtualGL 的远程桌面连接后,您可以使用 vglrun 运行选定的应用程序,并为其 OpenGL 部分启用 VirtualGL 加速渲染

$ vglrun glxgears

这当然必须在远程计算机上执行(应用程序将在那里运行),即在您的 SSH 或 VNC 会话中。将要使用的 X 服务器由以下两个环境变量确定

DISPLAY 将处理应用程序并渲染其非 OpenGL 部分的 X 服务器。

如果使用 VNC,则指 VNC 服务器。在 SSH 转发的情况下,它是远程计算机上的虚拟 X 服务器编号,SSH 在内部将其映射到客户端上的真实 X 服务器。此变量没有任何 VirtualGL 特有的东西,并且它已经在您的 SSH 或 VNC 会话中设置为正确的值。

VGL_DISPLAY VirtualGL 应将 OpenGL 渲染重定向到的 X 服务器。

参见上面的 安装与设置。如果未设置,则假定值为 :0.0。请注意,点后的数字可用于选择显卡。

还有许多环境变量和命令行参数可用于微调 vglrun - 请参阅用户手册和 vglrun -help 以供参考。 VirtualGL 的行为还取决于其两种主要操作模式中的哪一种处于活动状态(vglrun 将根据执行它的环境自动选择)

在此模式下,渲染的 OpenGL 场景的压缩图像流通过自定义网络协议发送到 vglclient 实例。默认情况下,它使用 90% 质量的 JPEG 压缩,但这可以完全自定义,例如
$ vglrun -q 30 -samp 4x glxgears              # use aggressive compression (to reduce bandwidth demand)
$ VGL_QUAL=30 VGL_SUBSAMP=4x vglrun glxgears  # same as above, using environment variables
还有一个 GUI 对话框,可让您在应用程序启动后立即更改应用程序最常见的 VirtualGL 渲染/压缩选项 vglrun - 只需在应用程序具有键盘焦点时按 Ctrl+Shift+F9 即可打开此对话框。
在此模式下,VirtualGL 通过正常的 X11 协议将原始(未压缩)图像直接馈送到处理应用程序的 X 服务器 - 例如,在同一台机器上运行的 VNC 服务器。 vglrun 的许多命令行选项(例如,与图像流压缩或立体渲染相关的选项)在此处不适用,因为另一端没有运行 vglclient。现在由 VNC 服务器处理所有图像流优化/压缩,因此您应该在那里进行微调。
提示: vglrun 实际上只是一个 shell 脚本,它(临时)设置一些环境变量,然后再运行请求的应用程序 - 最重要的是,它将提供所有 VirtualGL 功能的库添加到 LD_PRELOAD。如果它更适合您的工作流程,您可以自己设置这些变量。以下命令列出了 vglrun 将为您的特定设置设置的所有环境变量
comm -1 -3 <(env | sort) <(vglrun env | grep -v '^\[' | sort)

确认 VirtualGL 渲染已激活

如果您在启动应用程序之前设置了 VGL_LOGO 环境变量,则在通过 VirtualGL 渲染的任何 OpenGL 场景的右下角都会显示一个带有 “VGL” 字样的小徽标

$ VGL_LOGO=1 vglrun glxgears

如果应用程序运行但未显示徽标,则表示 VirtualGL 未能生效(请参阅下面的 #故障排除),并且应用程序可能已回退到软件渲染。

测量性能

许多 OpenGL 程序或游戏可以显示嵌入式 FPS(“每秒帧数”)计数器 - 但是,当使用 VirtualGL 时,这些值不会非常有用,因为它们仅测量在服务器端(通过支持 3D 的 X 服务器)渲染帧的速率,而不是帧实际最终在客户端渲染的速率。

用户手册的“性能测量”章节描述了如何获得 VirtualGL 图像管道各个阶段吞吐量的测量值,以及如何识别瓶颈(尤其是在将 VirtualGL 与 X11 转发结合使用时)。使用 VNC 时,VNC 客户端也应该能够告诉您其渲染帧率。

故障排除

提示: 使用 +v 命令行开关(或环境变量 VGL_VERBOSE=1)运行 vglrun 会使 VirtualGL 打印出有关其尝试初始化应用程序渲染的一些详细信息。 +tr 开关(或变量 VGL_TRACE=1)将使其在实际渲染期间打印出有关拦截的 OpenGL 函数调用的许多实时信息。默认情况下,VirtualGL 将其所有调试输出打印到 shell - 如果您想将其与应用程序自己的 STDERR 输出分开,您可以设置 VGL_LOG=/tmp/virtualgl-$USER.log

vglrun 报错 “无法打开显示器”

如果 vglrun 退出并显示如下错误消息...

[VGL] ERROR: Could not open display :0.

...在 shell 输出中,则表示服务器端本应处理 OpenGL 渲染的支持 3D 的 X 服务器未运行,或者未正确设置为与 VirtualGL 一起使用(请参阅 安装与设置),或者 VGL_DISPLAY 未正确设置(请参阅 运行应用程序)。如果它曾经工作但现在不再工作,则软件包升级可能已覆盖了 vglserver_config 修改的文件,因此请再次运行该脚本,然后重新启动服务器端 X 服务器。

vglrun 似乎完全没有效果

症状

  • 没有 VirtualGL 加速的 3D 渲染 - 程序要么中止,要么回退到软件渲染(如何检查
  • 同时,shell 中没有打印任何与 VirtualGL 相关的错误消息或信息

当某些东西阻止 VirtualGL 被预加载到应用程序的可执行文件中时,可能会发生这种情况。预加载的工作方式是,vglrun 在运行启动应用程序的命令之前,将一些 VirtualGL 库的名称添加到 LD_PRELOAD 环境变量中。现在,当应用程序二进制文件作为此命令的一部分执行时,Linux 内核会加载动态链接器,动态链接器反过来检测 LD_PRELOAD 变量,并在其他任何操作之前将指定的库链接到应用程序二进制文件的内存副本中。如果环境变量未传播到动态链接器,则这显然不起作用,例如在以下情况下

  • 应用程序通过显式取消设置/覆盖 LD_PRELOAD 的脚本启动
解决方案: 编辑脚本以注释掉或修复有问题的行。(您可以将修改后的脚本放在 /usr/local/bin/ 中,以防止在下次软件包升级时还原它。)
  • 应用程序通过多层脚本启动,并且环境变量在途中丢失
解决方案: 修改实际运行应用程序的最终脚本,使其使用 vglrun 运行应用程序。
  • 应用程序通过加载器二进制文件(可能是它本身!)启动,以一种无法传播 LD_PRELOAD 的方式
解决方案: 如果可能,绕过加载器二进制文件,并直接使用 vglrun 启动实际的 OpenGL 应用程序 - 一个示例是 VirtualBox,您需要直接使用 vglrun VBoxManage startvm "虚拟机名称" 启动虚拟机会话,而不是通过 VirtualBox 主程序 GUI。如果是 LD_PRELOAD 在二进制文件中被显式取消设置的问题,则在某些情况下,使用 -ge 命令行开关运行 vglrun 可以防止这种情况。

有关已知需要此类解决方法的一些应用程序的列表,请参阅用户手册中的“应用程序配方”部分。

vglrun 失败并显示 ld.so 错误

如果 VirtualGL 加速的 3D 渲染不起作用(如上一节所述),但此外您还看到如下错误消息...

ERROR: ld.so: object 'libdlfaker.so' from LD_PRELOAD cannot be preloaded: ignored.
ERROR: ld.so: object 'librrfaker.so' from LD_PRELOAD cannot be preloaded: ignored.

...在 shell 输出中,则表示动态链接器正在正确接收将 VirtualGL 库预加载到应用程序中的指令,但某些东西阻止其成功执行此任务。三个可能的原因是

  • 未安装正确架构的 VirtualGL 库
要使用 VirtualGL 运行 32 位应用程序(如 Wine),您需要从 multilib 存储库安装 lib32-virtualgl
  • 应用程序可执行文件已设置 setuid/setgid 标志
您可以使用 ls -l 检查可执行文件的文件权限来确认是否是这种情况:如果设置了 setuid,它将在用户可执行位的位置显示字母 s(例如 -rwsr-xr-x),如果设置了 setgid,则在组可执行位的位置显示字母 s。对于此类应用程序,任何预加载尝试都将失败,除非要预加载的库也设置了 setuid 标志。您可以通过以 root 身份执行以下命令来为有问题的 VirtualGL 库设置此标志
$ chmod u+s /usr/lib/lib{rr,dl}faker.so    # for the native-architecture versions provided by virtualgl
$ chmod u+s /usr/lib32/lib{rr,dl}faker.so  # for the multilib versions provided by lib32-virtualgl
但是,在决定在安全性至关重要的服务器环境执行此操作之前,请确保您完全理解 setuid 的安全隐患。
  • 您可能需要指定 VirtualGL 库的完整路径
打开 /usr/bin/vglrun 并在 LD_PRELOAD 变量中指定库的完整路径。示例
libvglfaker$SUFFIX.so  ->  /usr/lib/libvglfaker$SUFFIX.so

vglrun 失败并显示错误:Could not connect to VGL client.

如果您的 “客户端” 程序与 virtualGL 在同一服务器上运行(例如,如果您将 virtualGL 用于 VNC),请尝试使用 vglrun -c proxy

关于 /etc/opt/VirtualGL/vgl_xauth_key 不存在的错误消息

这意味着您的 virtualGL X 服务器根本没有运行 vglgenkey,或者它正在被另一个 X 服务器再次运行。对我来说,lightdm 在错误的(VNC 远程)X 服务器上运行 vglgenkey,因为 vglserver_config 添加了以下内容

/etc/lightdm/lightdm.conf
...
[Seat:*]
display-setup-script=/usr/bin/vglgenkey

将其更改为

/etc/lightdm/lightdm.conf
...
[Seat:seat0]
display-setup-script=/usr/bin/vglgenkey

因此,它仅在第一个 X 服务器上运行,解决了我的问题。

vglrun 失败并显示错误:VirtualGL attempted to load the real glXCreatePbuffer function and got the fake one instead.

这意味着 VirtualGL 正在尝试从错误的库加载函数。您可以通过将 LD_PRELOAD 设置为库的路径来指定要使用的 OpenGL 库。 /usr/lib/libGL.so 似乎适用于 64 位应用程序。请记住,32 位应用程序(如 Steam 或 Wine)将需要 32 位 OpenGL。如果您需要同时使用 32 位和 64 位库,您可以同时加载它们,使用 LD_PRELOAD="/path/to/libGL.so /path/to/lib32/libGL.so"

所有应用程序都以每秒 1 帧的速度运行

如果您使用较新的 NVIDIA 驱动程序(例如,版本 440),您可能会受到屏幕锁定问题的影响,根据 VirtualGL 邮件列表,这将使帧率降低到大约每秒 1 帧。解决方法之一是在您的 X 服务器配置中将 HardDPMS 设置为 false,而不是降级 NVIDIA 驱动程序(有关详细信息,请参阅 NVIDIA/Troubleshooting#HardDPMS)。

渲染故障、异常的低性能或应用程序错误

OpenGL 具有非常底层和灵活的 API,这意味着不同的 OpenGL 应用程序可能会提出非常不同的渲染技术。 VirtualGL 关于如何重定向渲染以及如何/何时捕获新帧的默认策略在大多数交互式 3D 程序中都运行良好,但对于某些应用程序可能被证明效率低下甚至存在问题。如果您怀疑可能是这种情况,您可以通过在启动应用程序之前设置某些环境变量来调整 VirtualGL 的操作模式 vglrun。例如,您可以尝试设置以下一些 环境变量 (一次尝试一个,并注意它们中的每一个也可能使情况变得更糟!)

VGL_ALLOWINDIRECT=1
VGL_FORCEALPHA=1
VGL_GLFLUSHTRIGGER=0
VGL_READBACK=pbo
VGL_SPOILLAST=0
VGL_SYNC=1  # use VNC with this one, it is very slow with X11 forwarding

一些 OpenGL 应用程序还对其 X 服务器环境或加载的库做出强假设,而 VirtualGL 设置可能无法满足这些假设 - 因此导致这些应用程序失败。环境变量 VGL_DEFAULTFBCONFIGVGL_GLLIBVGL_TRAPX11VGL_X11LIBVGL_XVENDOR 可用于在某些情况下修复此问题。

有关所有受支持环境变量的正确解释,请参阅用户手册中的“高级配置”部分,有关已知需要调整才能与 VirtualGL 良好配合的某些特定应用程序的信息,请参阅“应用程序配方”部分。

Xpra:vglrun 仅使用渲染设备 llvmpipe

您需要运行两个 Xorg 服务器:一个 Xpra 附加到的服务器,例如在显示器 :10 上。以及第二个使用您的显卡进行实际渲染的服务器,例如使用 startx 在显示器 :0 上运行的默认 Xorg 服务器。

参见