用Wayland玩游戏

2022/02/15 translation 共 5660 字,约 17 分钟

原文: Gaming on Wayland | Xaver’s blog (zamundaaa.github.io)

大部分人认为Wayland并不适合用来游戏,因为使用它时你不能关闭你的窗口合成器。

这篇文章将挑战这一假设,看看Wayland上的玩游戏的现状如何,特别是KWin,KDE的窗口合成器。

1. 延迟

由于合成和强制VSync的原因,比起X(X Window),Wayland上的游戏经常会出现延迟增加的情况,这就是所谓的 “输入延迟”。在讨论Wayland上的延迟到底是好是坏之前,有必要对这些东西的实际含义做一些解释。

在游戏中, “输入延迟 “是指从产生某种输入事件(如按下鼠标或键盘按钮)到在显示器上看到所产生的游戏事件所需的时间。这种 “输入 “延迟可以分成多个部分,例如:

  • 实际输入延迟:按下按钮 -> 计算机注册

  • 输入路由延迟:计算机注册 -> 输入被转发给游戏

  • 渲染时间:游戏获得输入 -> 游戏对输入作出反应,并用它渲染一个新帧

  • 呈现时间:渲染一帧 -> 显示服务器向显示器发送数据

  • 显示反应时间:显示器收到的数据–>实际的像素点改变颜色

影响 X 和 Wayland 的表现的是输入路由延迟和呈现时间。输入路由延迟通常是微不足道的,但呈现时间就不是了。要理解如何以及为什么,你首先要知道图像是如何从GPU到显示器的。

显示器如何工作

让我们先假设一个非常简化的假想案例。显示器刚刚被打开,还没有什么被显示。GPU向显示器发送一些图像,从左上角的像素开始,一行一行地发送它们。随着数据的传输,显示器逐一更新其物理像素,直到处理完成所有的像素,然后再从头开始。显示器在给定时间段内处理所有像素的频率被称为刷新率;例如,一个60Hz的显示器每秒刷新60次,因此每帧需要大约1000ms/60=16.66ms。

为了进一步简化,我们假设计算机只为整个屏幕发送一种单一的(随机的)颜色。为了说明这一点,我渲染了一个刷新率很低的模拟显示器,左边的像素显示应该呈现的颜色,右边的空间显示实际的显示效果。

现在产生的静态图像相当无聊,我们想逐帧改变它,使它看起来像事物在移动——在这种情况下,我们只是改变颜色。最简单的方法是在计算机渲染完一个新帧时改变图像数据。这种方法可行,但不是最好的,尤其是当应用程序的速度比显示器快时(在本例中,大约是3倍)。

当我们在一个显示刷新周期中更新像素数据时,最终会同时显示多个不同版本的图像,这就产生了视觉断裂。这种中断被称为撕裂,它可以通过垂直同步来防止,简称VSync。通过VSync,GPU只在所谓的垂直消隐间隔(vblank)内改变它所发送的图像数据,这是右下和左上像素之间的时间。

在这段时间里,显示器实际上没有更新任何像素,它只是在等待。你可能想知道为什么它要等待?这主要是CRT时代的遗留问题–这些老式显示器需要等待决定电子束方向的磁场改变。现在vblank可以减少很多,但它仍然遗留了下来,既用于VSync,也用于传输元数据,如颜色信息或内容类型。

然而,由于我们只在特定的时间点上更新图像,而不是在两者之间,这可能会大大增加一帧图像被渲染和你看到它之间的时间。如果应用程序的更新速度比显示器慢,那么这也会导致卡顿,因为内容到达显示器的时间每帧都不一样。如果应用程序的更新速度较快,那么帧就会被跳过,也会造成卡顿,尽管通常不太明显。为了解决这个问题,应用程序在可能的情况下还会将其渲染与显示器同步–显示器每更新一次,他们就只渲染一帧。这也从根本上减少了资源的使用和电力消耗。

还有一项技术与此相关,叫做可变刷新率(VRR)或自适应同步,尽管它以其实现方式FreeSync(来自AMD)和GSync(来自NVidia)而闻名。在VSync中,总是由GPU来适应显示器,但在自适应同步中,部分角色是相反的:GPU可以告诉显示器使vblank更长。

每当一个应用程序比显示器的最大刷新率慢时,显示器将等待下一帧,然后再更新像素,因此你不会看到任何卡顿,不会引入撕裂。此外,在这种状态下,它的延迟非常低,因为每一帧都是在游戏完成渲染后显示的。并非所有的显示器都有这种功能上,因为要使它很好地工作很困难。在许多具有不同刷新率的显示器中,亮度变化很大,所以如果刷新率跳动,你会看到显示器不断闪烁。

显示服务器

什么是X和Wayland,为什么它们很重要?

应用程序通常不直接呈现在显示器上,那是显示服务器的工作。显示服务器负责合成,也就是把应用程序提供的图像合成到最终显示的图像中,然后把合成的图像放到屏幕上。为了与显示服务器通信,应用程序使用几种协议中的一种;在Linux和BSD上最广泛使用的是X11和较新的Wayland。

对于X11来说,主要的实现被称为X.org服务器,通常被称为 “X”。X处理许多事情,如输入、窗口焦点、基本合成、显示图像、为应用程序分配图形内存以及很多。但它不会处理所有的事情,有两个程序可以扩展X的功能。

有一个有效的强制性窗口管理器,它负责处理堆叠顺序(哪个窗口在哪个上面)、焦点变化和基本的窗口移动和大小调整。另一个扩展是可选的,即X11合成器,它可以做比X服务器本身更高级的合成,如透明、模糊和其他各种可能的效果。这两个程序通常被合并成一个,同时进行窗口管理和合成。

在Wayland上,显示服务器被称为Wayland compositor,其中有几个广泛使用的实现,例如KWin(KDE)、Mutter(GNOME)和Sway。从本质上讲,Wayland合成器负责X服务器、窗口管理器和X11合成器共同完成的所有工作。为了让X11应用程序在Wayland上仍能正常运行,还有一个名为Xwayland的兼容层,目前大多数游戏都是用Wayland来运行的。

请注意,这个解释遗漏了很多东西,并简化了其他东西,这是一个用几句话没法解释清楚的复杂情况……而且有很多地方我的知识是有限的,特别是关于X。

X上的合成和游戏的不足之处

在X上,当一个应用程序提交一个新的图像给用户时,它会进入X11合成器(如果此时有一个激活的话),合成器使用该图像来合成最终的图像并输出。由于X11协议的限制,当一个应用程序进行VSync时,它的图像正好在当前帧中来不及显示的时候进入合成器–它被延迟了一个额外的刷新周期。在游戏中启用VSync后,延迟的增加是让X的合成使一些人感到迟钝的重要原因之一。

还有一个很大的原因,即X11的另一个限制:对多显示器的处理。你拥有的所有显示器都被放在X的一个屏幕上,这意味着合成器只能同时为所有输出呈现一个大图像。其结果是合成器不能同时为所有输出同步渲染,导致卡顿,并将刷新率限制在最慢的显示器上–而且使多显示器的自适应同步成为不可能。这个问题有解决方法,但没有一个解决方法能同时消除所有问题。

Wayland

Wayland有什么不同之处?几乎所有你能想到的都有。如果要详细解释所有的东西,会远远超出这篇文章的范围和我自己的认识,所以我只说与游戏相关的部分。

  • 在合成和游戏VSync中增加的一帧延迟不适用于Wayland
  • 由于一些更好的设计决定,Wayland比X更有效一些,这可以使性能有所提高。但不要指望有什么奇迹,其效果非常小。
  • 对屏幕的绘制方式没有限制。诸如用不同的刷新率渲染多个屏幕、用可变的刷新率、用多线程和几乎所有的图形API都是可能的,这就允许有更多的功能。例如,Gamescope使用Vulkan和异步计算来使合成尽可能快地可靠进行。
  • 对于事物是否需要被绘制到屏幕上,也没有任何限制。一个完整的基于VR/AR的 “桌面 “环境,你可以把窗口放在任何你想放的地方,这并不是不可能的,而且可以远远超过像xrdesktop这样的应用程序所能做到的(它已经超级棒了,如果你有一个VR头盔,可以看看)。
  • 在原生Wayland应用程序能做的事情上有很多限制。例如,像alt+tab这样的全局快捷键总是被保证有效,无论游戏做什么–合成器实际上对一切都有最终决定权。
  • 应用程序的内容可以通过显示硬件直接放在屏幕上(这被称为 “直接扫描”。你可能也听说过与X有关的术语 “unrediction “用于同样的事情)。这消除了不必要的复制,并提供了一些很好的效率和延迟优势–甚至在窗口模式下,如果合成器和硬件支持它的话。
  • 所有应用程序的HDR和色彩校正。这仍然需要很长的时间才能实现,但它终于出现了。像Windows AutoHDR这样试图将SDR游戏内容 “升级 “为HDR的东西也在可能的范围内。
  • 更有效的屏幕录制
  • 强大的多GPU支持。详细说明会有点多,但要点是它是高效、可靠的,并允许(至少在原则上)在飞行中切换GPU。

这在理论上是很好的,但我们现在的实际情况如何?

KWin

从5.23版本开始,kwin_wayland支持

  • 以不同的刷新率渲染多个屏幕

  • 动态调整当前的渲染负载,以减少延迟

  • 自适应同步/FreeSync/(一旦NVidia在Wayland上支持它)GSync

  • 全屏应用的直接扫描输出

一些与游戏有关的东西将在未来添加。

  • 对VR头盔的支持,将在5.24中出现。基本上SteamVR和Monado会 “正常工作”。
  • dmabuf反馈,也将在5.24中出现。它应该使直接扫描在大多数情况下与大多数应用程序一起工作
  • 允许禁用VSync,对于应用程序,如果可行的话,也可以禁用全局。请注意,这只是在Latency第一部分中提到的 “允许撕裂 “的部分;如果你关闭了游戏的 “VSync “设置,Wayland不会也不能限制其帧率。
  • 在可能的情况下,直接扫描出窗口操作
  • 更好的多GPU支持。虽然你可以通过环境变量选择KWin将使用的GPU,但这并不完全是用户友好的。我正在努力实现一个选择用于合成的GPU的GUI–这样你就可以改变它而不需要再次登录,而且你也可以完全从系统中断开GPU,这应该有助于VFIO的使用情况
  • 分层显示。这是一种特殊类型的显示器,不是使用一个而是多个显示控制器–它们连接到GPU上的多个内部端口(但可能仍然使用一根电缆)–以支持非常高的分辨率和刷新率。一旦完成对平铺显示器的支持,同样的功能也将用于使类似于AMD EyeFinity的东西成为可能,这样你就可以使一切表现得像你的多个显示器是一个单一的。

2. 延迟:测量

现在,所有的解释都结束了,让我们来看看它到底是怎样的吧!这是我的想法。由于缺乏适当的工具,我自己用两个微控制器和一个亮度传感器做了一个延迟测量工具。一个微控制器作为实际的测量工具,触发鼠标点击并等待屏幕的反应,另一个作为记录器。这样就可以进行相对无痛的测试。测试设置本身是

  • Ryzen 5800X + rx 6800 XT,计算能力不是一个限制因素–这是邮箱和即时模式的最佳情况。
  • 三星Odyssee C49RG94SSR,120Hz(8.3毫秒刷新周期),启用FreeSync。
  • 亮度传感器被设置为测量屏幕的中间位置
  • 最新的Manjaro稳定版Linux 5.15与Mesa 22.0(开发)。
  • 未打补丁的KWin git master,延迟设置为默认值,并且没有为Vulkan应用程序工作的直接扫描。这应该是5.23版本的代表(至少在我的GPU上),没有相关的代码路径变化
  • 我不久前写的一个使用Vulkan和glfw的应用程序,经过修改,每当鼠标被按下时,屏幕都是白色的。

由于我的黑客拼凑的测量工具除了一些逻辑检查外还没有验证过正确性,请注意这些数字只能用于近似的比较,而不能准确判断系统的绝对延迟。它们也不一定代表你的系统或特定游戏的正常延迟。

以下表格中的所有数值都是以毫秒为单位。不要纠结于一毫秒的差异,即使有一千个测量值,仍然会有一些噪音。

X with compositingfifo*mailbox
median5937
99th percentile6746
X without compositingfifomailboximmediateFreeSync
median41381924
99th percentile49452632
Waylandfifo**mailboximmediate***FreeSync
median49362024
99th percentile56443331
Xwaylandfifo**mailboximmediate***FreeSync
median49382025
99th percentile57463333

呈现模式有

  • fifo。”先入先出”。fps有限制+VSync - 这就是游戏中大多数 “VSync “设置的作用。
  • 信箱:没有帧数限制+VSync
  • 即时:没有帧数限制,没有VSync。在没有合成器的X上,这将导致屏幕撕裂,在有合成器的X或Wayland上,这与邮箱相同(因此被排除在外)。
  • FreeSync:通过GOverlay/mangohud将邮箱的帧率人为地限制在115,这样显示器就能一直与游戏同步。

*正如已经解释过的,一帧的延迟是可以保证的。第二个额外的帧我不能很好地解释,但我没有多加研究,X11既不是我的专业领域,我也不认为有理由改变它

**由于增加了缓冲区的膨胀(展示的队列大了一帧),使用fifo的延迟比未组合的X要高一帧。

***KWin修补了一个非常简单但糟糕的漏洞,这使测试成为可能。

结论

就像常发生的那样,这要归结为限制和交换的问题 (requirements and trade offs) 。一般来说,Wayland在延迟方面已经做得很好了– 如果你想要像流畅的多显示器操作、多显示器的FreeSync或者不想为了更好的游戏而被迫禁用合成器等功能,它可能已经为你准备好了!

如果你需要绝对最低的延迟,并且不关心屏幕撕裂,那么没有合成器的X,禁用VSync是更适合你的。一旦在你选择的合成器中实现了禁用VSync的可能性,并且在即时模式下测得的延迟波动性增加(第99个百分点)得到解决,你可以重新评估。

我个人将继续使用Wayland,并将全局帧率限制设定为115–这样电脑的噪音和热量就会减少,而延迟则非常低,我不会注意到它。

文档信息

Search

    Table of Contents