两年前,我在游戏 PC 上改用 Linux。人们一直告诉我,在 FPS、帧节奏和输入延迟方面,它的表现比 Windows 更好,当我尝试时,它确实感觉好多了。
互联网上有很多关于优化 Linux 游戏的建议:
我玩竞技 FPS 游戏,因此低延迟、一致的帧时间和高 FPS 对我来说很重要。在 Linux 上,有无数的设置需要调整(magic env vars、gamescope、gamemode,甚至更多 DXVK forks 等等)。
但一直困扰我的是,我没有可靠的方法来验证某些东西是否真的降低了系统延迟,或者它只是万金油、安慰剂效应,或者实际上更糟而我没有意识到。
这个想法很简单:将带有某种光传感器的设备绑在显示器上,并通过 USB 将其连接到 PC 以模拟鼠标点击。单击时,测量单击与光传感器检测到屏幕上的变化之间的时间。
通过这种方式,您可以测量端到端系统延迟。
© NVIDIA 有一张图片很好地总结了这一点。
虽然现在有一些这样的开源设备可用,例如 m2p-latency 或 Open-Source-LDAT ,但当我开始这个业余项目时,只有 OSLTT ,并且对硬件一无所知,我很高兴研究它的原理图并松散地将我的设计建立在它的基础上。
但本月刚刚完成我的项目,我最终也整合了其他两个项目的很多想法。
穿孔板上的 QT Py RP2040、跨阻放大器和 BPW34 光电二极管。
外壳有“翅膀”,因此我可以使用松紧带将其绑在显示器上。
长话短说,我学到了很多关于微控制器、焊接、Arduino 固件开发、集成时间、跨阻放大器、KiCad(仅一点点)和外壳设计的知识。
这是我的发现:
我想测试三种不同的东西。
很多人仍然使用 X11 而不是 Wayland,因为据说 Wayland 的输入延迟要严重得多。刚搜了一下,就有很多人抱怨 Wayland“感觉不舒服”。
可变刷新率/G-Sync/FreeSync/无论你怎么称呼它。也备受热议。
从现在开始称为 dxvk-low-latency 或 low-latency。这个 fork 的维护者 netborg 投入了大量精力来开发这个框架节奏器,它最近被集成到官方的 proton-cachyos 包中,通过环境变量 PROTON_DXVK_LOWLATENCY=1 启用。这个分支的承诺是我想要再次尝试桌面 Linux 的决定因素之一。
像 dxvk-low-latency 这样的帧调速器带来的最大优势是吸收帧时间波动并防止渲染队列堆积。使用我使用的测试方法(静态游戏场景,请参阅下文了解更多信息),没有可观察到的帧时间波动,因为所有测试都产生纯粹受 CPU 限制的场景。但这主要并不能反映真实的游戏会话,其中帧时间可能会由于游戏内或游戏外发生的情况(例如使用资源的其他进程)而波动。
因此,为了展示工作中的起搏器,我添加了两个无上限的测试用例。
我通过本机 Wayland ( PROTON_ENABLE_WAYLAND=1 ) 运行了所有 Wayland 测试用例,因为我已经意识到 XWayland 会引入延迟。但为了比较,我添加了两个 XWayland 测试用例(仅在 VRR 关闭的情况下)。
测试期间仅连接一台显示器。
使用默认的 CachyOS 内核调度程序。
Wayland 上的翻转模式(或“直接扫描输出”)与 Blit 模式(合成):没有任何设置。合成器自行决定是否合成帧或使用直接扫描输出。要确保游戏在翻转模式下运行:打开“KWin 调试控制台”(它是一个 GUI 工具),然后在“效果”选项卡中启用 showcompositing 。然后确保游戏完全聚焦,并且是全屏模式下屏幕上唯一的内容。如果游戏边缘没有可见的红色边框,则说明游戏处于翻转模式。
为了使比较公平,根据场景使用了优化的 dxvk.conf:
在所有情况下,都设置了 d3d11.cachedDynamicResources = "c"。
我使用的游戏是 Diabotical,一款 DirectX 11 游戏,通过 Heroic 和 Proton 推出。
有一个隐藏命令可以在短时间内隐藏 UI。将该命令绑定到左键单击 ( /bind mouse_left testlatency ) 并设置一个显示大白框的 HUD,我能够在单击时产生较大的亮度差异。
每个上限测试用例在测试期间都保持其帧速率上限稳定,并且游戏始终保持 CPU 限制。
数据看起来很干净:没有测试用例产生狂野的异常值,并且每个用例都产生钟形分布,p5 和 p95 之间大约 2 到 3 毫秒宽。
跳出三件事:
这是最快的情况:
那么,X11 的延迟是否比 Wayland 低呢?是的,但还不足以解释为什么 Wayland 通常被认为比 X11 差得多。
X11 在每种情况下都获胜,但只有 0.14 到 0.22 毫秒的差异。分布非常相似:
VRR 对所有配对的影响最大:启用它比禁用它快 0.26 到 0.45 毫秒。
它还使分布变得平坦:在 VRR 情况下,p95-p5 分布为 2.1 至 2.2 毫秒,而没有 VRR 情况下为 2.6 至 3.0 毫秒。
这与 VRR 的工作方式一致:帧在准备好时扫描出来,而不是等待下一个扫描输出槽。
在上限测试用例中,差异很小但一致,并且与 X11 与 Wayland 的差异大致相同。 Wayland 和 X11 之间的差异平均为 0.18 毫秒,而使用 dxvk-low-latency 平均快 0.20 毫秒。
在无上限的测试用例中,我们可以了解 dxvk-low-latency 的真正优势所在:平滑不均匀的帧节奏并防止渲染队列堆积。起搏器通过确保 GPU 永远不会被充分利用来实现这一点,因此游戏始终接近 GPU 限制,但绝不会完全受到限制。这可以在测试运行中观察到,使用 dxvk-low-latency 时 GPU 利用率为 95-97%,不使用 dxvk-low-latency 时 GPU 利用率为 100%。这以 FPS 的形式提供,价格低廉。
到目前为止,所有 Wayland 测试都通过 PROTON_ENABLE_WAYLAND=1(或 Heroic Launcher 中的“启用 Wine-Wayland(实验)”切换开关)本地运行游戏。关闭它会让游戏通过 XWayland 运行,这就是它变得糟糕的地方。
如果没有 dxvk-low-latency,XWayland 的测量会增加 3.13 毫秒的延迟。这比我测量到的所有其他影响加起来还多。拖累平均成绩的也不是偶尔的坏帧;而是偶尔出现的坏帧。整个分布变化:
值得注意的是,在 XWayland 测试中添加 dxvk-low-latency 可以将延迟降低 2.11 毫秒,这是所有场景中的最大收益。
这些结果是在最佳情况下产生的(稳定的 FPS,上限,CPU 限制),当然特定于我的硬件和所选的软件堆栈。
在其他设置上,绝对数字看起来会有所不同,但每个测试用例的收益和损失应该大致转移。在刷新率较低的显示器上,VRR 和低延迟起搏器带来的收益可能会更大。
它增加了 3.13 毫秒的延迟,超过所有其他效果的总和。
虽然只有 0.14 到 0.22 毫秒。鉴于正在努力优化 KWin ,这一差距可能很快就会缩小。谁知道呢,其他 Wayland 合成器可能已经更好了。
VRR 在每次配对中都更快(0.26 至 0.45 毫秒),并且还使延迟分布变得平坦。
在有上限的场景中,0.10 到 0.29 毫秒是一个不错的提升,但分叉的真正强度在无上限的测试用例中显示出来,它比默认的 dxvk 提高了 0.84 毫秒。此外,在无法避免 XWayland 的场景下,它恢复了整整 2.1 毫秒。
不考虑 XWayland,与默认设置(在现代 Linux 系统上,我假设是普通 Wayland)相比,应用每个优化(X11、VRR、低延迟)将中位数降低了 0.72 ms。这听起来不是很多,但原始延迟并不能说明全部情况,因为 VRR 还可以减少延迟抖动,而 dxvk-low-latency 的pacer 非常适合平滑发生帧时间下降和 GPU 受限情况的现实场景。
David Ramiro 也构建了他的 m2p 延迟,并在他的文章“构建输入延迟计(因为‘Wayland Feels Off’不是一个指标”)中比较了 X11 与 Wayland,得出了类似的结论:Native Wayland 与原生 X11 相当(均在约 7 毫秒左右),而 XWayland 在他的测试中将延迟大约增加了一倍。
Farnoy 在他的 Linux 延迟测量和合成器调优中使用 Open-Source-LDAT 进行了广泛的测试,并得出了应该避免使用 XWayland 的结论。
我的附带任务 Themaister 使用 VK_EXT_present_timing 测量输入延迟描述了一种无需任何外部硬件即可测量延迟的不同方法,即通过 /dev/uinput 注入输入并检测 GPU 上产生的图像变化。这并不测量端到端系统延迟,而是从等式中删除 USB 和显示延迟,将范围缩小到仅测量 PC 延迟。该项目可以在 GitHub 上找到。