也许是该谈谈全新的 Linux 显示驱动模型的时候了

随着越来越多新的图形应用编程接口(API)的出现(譬如Vulkan、D3D12、Metal),Steam OS(译者注:一个基于Debian的Linux发行版,关注于提供大屏幕的游戏体验)也在猛烈地推动着Linux上的游戏开发。甚至我自己也感觉到在Linux系统上涉及图像处理的开发工作正变得越来越多。

也许是该谈谈全新的 Linux 显示驱动模型的时候了

但在一台装着Ubuntu14.04的电脑上,就图像处理相关内容工作了一段时间后,我发现,Linux上有关图像处理的架构设计简直就是一场灾难。

让我们来看看问题都出在哪儿

  1. 由于工作性质原因,我的整个系统经常会长时间地挂起没有反应,这是我在Windows系统上很少遇见的,在Windows系统上顶多会导致TDR,即所谓的超时检测并可以快速地恢复(译者注:有关超时检测和快速恢复,可以参考本文后续章节有关TDR的描述)。为此我不得不经常按复位键。
  2. 同样是OpenGL驱动程序,在Linux上的实现,其性能表现就比Windows上的要差。如果你使用的是高于4.3的GL版本,由于该版本支持AZDO功能(译者注:Approaching Zero Driver Overhead,一种OpenGL的新技术,可以大大减少驱动在图形计算中所占的CPU消耗比重),所以表现还算不错并且性能上和Windows的驱动表现差不多(有时还优于Windows),但我仍然会碰到诸如系统挂起,纹理渲染异常或者内存耗尽等问题,而这些问题在Windows上是看不到的。
  3. 糟糕的视窗系统X11。(译者注:X11是X Windows的第11个版本)
  4. 在一些X11的替代系统上使用OpenGL需要libGL库,但这个库却依然要依赖X系统。
  5. 当前的一些合成桌面系统Compositors(译者注:X Window协议定义的的组成模块之一)的实现运行起来耗电量惊人,譬如Compiz(译者注:compiz是基于 OpenGL的一种Compositor,可以提供类似于Vista和Mac OS的3D桌面效果),当然这主要也还是由于X系统自身的问题。
  6. 在Linux系统上实现垂直同步V-Sync功能简直就是一场噩梦(译者注:垂直同步最早由DirectX引入到Windows操作系统当中,其作用主要是让显卡的运算和显示器刷新率一致以得到稳定的输出画面质量。)。甚至打开该功能后,显示上仍然会看到图形撕裂的效果,除非你不使用合成桌面。
  7. 垂直同步功能在一些机器上不能正常工作,譬如Optimus。
  8. Linux在一个系统上只支持一个图形处理器(GPU,Graphics Processing Unit,译者注:即我们通常说的显卡),即使系统上有多个GPU。而Windows可以同时支持多个。
  9. 缺乏安全性。我可以通过图形库的驱动申请大量的内存,我还可以在帧缓冲区里读到任何其他已经死亡的进程曾经写入的内容。

这些问题在Android系统上也同样存在。首先在Android上想要实现GPU的虚拟化也是不可能的。其次通过GLES(译者注:OpenGL for Embedded Systems,OpenGL的一个子集,适用于嵌入式系统的图形库)进行连接的进程之间在窗口创建,恢复和销毁的接口调用顺序上的实现非常混乱。(例如,我们经常会看到两个连续的onDestroy调用跟在两个连续的onCreate调用后面,而按照规定应该是形如onCreate->onDestroy->onCreate->onDestroy这样的顺序;再比如,我们还会看到OnRestore调用发生在onCreate之前。此类糟糕的问题造成的影响在一些定制版本的Android系统上可能还会被放大)

让我们来看看WDDM做得如何

(译者注:WDDM 即 Windows Display Driver Model,Windows显示驱动模型)

  1. 内核和中间件的开发商可以严格地控制驻留内存的分配。显卡只能使用虚拟内存,而虚拟内存可能被换页,这也意味着显卡对物理内存不拥有完全支配权,虽然这妨碍了显卡应用的灵活性,却加强了跨进程虚拟化实现时对进程的保护,安全性也更强了(譬如系统在分配新内存给进程之前可以严格清零;对显卡进行读写的行为受到严格的规范)。
  2. 拓扑结构设计合理,正确枚举了所有的“适配器”(GPU)和“显示器”(例如,显示器A可以支持N个模式,并通过DVI接口连接到适配器B)
  3. 基于设计精良的窗口系统,合成桌面系统软件可以正确地实现垂直同步功能。
  4. 基于跨GPU通讯的标准化协议,适配器A可以将渲染后的数据内容复制到适配器B的帧缓冲中,然后由适配器B输出到和其连接的显示器上。利用这种特性,我可以这么玩,譬如我将一台显示器连接在我的Radeon HD 7770显卡上,另一台显示器连在我的Intel HD 4400集成显卡上,然后我拖动一个窗口,让两个显示器各显示这个窗口的一半,使用了垂直同步刷新功能后我们可以看到窗口的渲染依然很流畅,就和在一个显示器上刷新一样。我甚至可以将所有的监视器都接在Radeon显卡上,只使用Intel的显卡对图形进行渲染,然后发送给Radeon显卡显示。哇,是不是很有趣,测试的效果简直太棒了。
  5. 正确处理显卡的热插拔。在前面的第一个例子里,我可以在设备管理器中禁用Radeon卡,此时只有连接到Intel网卡的显示器会正常显示。如果我有进程正使用Intel的网卡在执行图形渲染的操作,禁用Radeon卡不会对其有任何影响;如果我同时也有进程在使用Radeon卡执行图形渲染,则在禁用Radeon卡的过程中进程会得到一个device_removed事件通知,我可以依据这个事件通知,要么切换到Intel网卡上继续工作,要么退出(或者干脆直接让进程崩溃)。这对于显卡处理就像我们可以热插拔USB连接一样。你是不是又要为此感到惊叹了呢。
  6. 超时检测和恢复Timeout Detection and Recovery(TDR)。诚然,这是一种极端条件下才需要考虑的功能。或者说我们至少有保底的一招,可以在一旦情况非常糟糕时挽救一下。这个功能是如此的有用!想想看,当出现问题时,用户只会发现屏幕最多2秒钟内没有响应,刷新一下后,就又可以继续工作了,而不用考虑去按那该死的复位键。理想情况下,GPU应该把发生的各种异常都报告给CPU进行处理;然后由CPU结束GPU上运行的任务,包括CPU侧相关的进程(当然我们也可以通过任务管理器实时监控每个进程,并通过该进程监控GPU侧的任务,必要时可以随时终止它们)。应该说TDR主要是用来对付一旦出现真正硬件故障的情况。但现在的图像处理硬件和软件都还没有健壮到万无一失,所以我们还是需要TDR这个功能的。对于Linux,实现TDR绝非简单地重新启动X11服务。一次TDR大致相当于在Linux上运行modprobe -rf gpumodule && modprobe gpumodule(译者注:shell命令,相当于先强制卸载,然后再加载GPU驱动模块)同时还要保证不影响当前运行的非终端关联进程(即在X11窗口桌面会话中的大多数进程)。

新的图形应用编程接口

我对驱动开发不是很了解,我也确信AMD,Intel和NVIDIA的驱动开发专家针对WDDM肯定也会有不少抱怨。但是,在图像显示方面,Linux上的缺点实在太明显。看在上帝的份上,一旦我在合成桌面上打开了垂直同步刷新功能,就几乎无法平滑流畅地播放flash视频。(我指的是在大部分主流的Linux发行版上)。甚至在VLC多媒体播放器上也不能完全实现流畅播放。

随着新的图形应用编程接口(特别是Vulkan)逐渐推出,看起来情况会有所好转,特别是听说Vulkan将会解决大部分在类UNIX系统上我们目前遇到的问题(包括稳定性,性能,缺陷,硬件问题)。对此我真的感到很兴奋。

根据我的了解,在跨GPU通讯问题上,Vulkan目前的处理策略(就像D3D12一样),应该只能算得上是一种临时的变通方法。该方法已经可以让Linux同时支持多个GPU,但目前的性能对游戏软件来说还是远远不够的。而且我们要意识到,由于在操作系统内核层面还没有一个统一的模型支持跨设备通信,寄希望于不同厂家的驱动能够在一起正确地合作实在是一个奢望。

窃以为,如果Linux想要在目前的Vulkan所取得的成绩上继续有所作为,要想在严格意义上更好地支持桌面应用和游戏的话,从驱动层面出发,还是有很多事情可以做的,譬如建立一个可以和WDDM媲美的LDDM(译者注:Linux Display Driver Model,Linux显示驱动模型)。这可不是一件容易的事情。它需要来自Linux内核开发者的主动支持(我的意思是指 Trovalds和他的团队,你懂的),Android端则需要Google的帮助,还要有编写良好的Vulka驱动程序,以及比X系统更好的视窗系统(像Wayland那样的)。这的确涉及到太多的协调和巨大的工作量。

我在这里并不想很正式地讨论有关Linux如何作为一个游戏平台或桌面平台的问题。我之所以发这个帖子,主要的原因是我发现我在Linux上正在从事越来越多有关图像应用的开发工作(拜GL 4.3所赐),而且我也听其他人说和我有同感。随着Vulkan的到来,以及Valve引擎的推动,Linux这个操作系统也正在成为一个主流的游戏平台。

正如我所要指出的,在Vulkan出现之后,Linux的下一个挑战将是要解决如下问题:一个设计优良的显示驱动模型和一个更好的视窗系统。

原文评论摘选

bumblebee 
September 5, 2015 at 18:27

没错,Linux不是Windows,这世界上只有一个Windows和一个Windows的合成桌面系统软件。可世界上不是只有一个Linux。这世界上只有一个Linux内核,但有很多桌面环境,很多合成桌面系统和很多窗口管理器。所以直接将Windows和那些基于Linux内核的操作系统进行对比是没有意义的,因为这不是简单的一对一而是一对多。

所以,在那些基于同一个Linux内核的操作系统上,和Windows只有一个自己的图像系统不同,它们有各自的图像处理系统。很明显这比不上Windows可以集中精力逐步优化一个单一的系统。抱歉我这么说并不是想责备哪一家公司或者哪一个组织。

如果你希望让它变得更‘好’,那所做的绝不会是简单地‘修缮’一下,你将不得不更换整个图形系统中很大的一部分。这反过来将破坏现有的几乎所有东西,没有人会接受这种改变。这就是问题所在:您要么牵头取得社区的支持,包括主流发布版本的支持,要么足够有钱,可以从财力上承担这些改变所需要的一切。

并不是说这个问题解决不了,但问题是没有切实可行的解决办法,所以现在就是这么个尴尬的境地,空有想法和期望,却无法改变现实。

David Airlie 
September 5, 2015 at 19:21

从一个内核代码的维护人员角度来看,所有的这些问题都需要时间和投入来解决,而且大部分事情已经在着手进行中。

如果你曾经用过Windows Vista,就应该记得当时的WDDM简直是一场灾难,那时的Windows一样无法支持同时连接两个来自不同厂家的显卡,他们花费了很大的精力试图改善这个问题,这种状况一直延续到Windows8才有所改进。同时我们要知道Windows只有一个单纯的生态系统(这一点和Apple一样),他们只有一种视窗系统及其配套的合成桌面系统。可是Linux的用户空间的碎片化那是相当的严重,你需要花更多的时间来修复来自各种各样的桌面系统,譬如KDE/ GNOME/等的缺陷,这些都是很明显的问题,但一般情况下人们不太意识到。

还记得NVIDIA曾经在相当长的一段时间里力图整体性改造系统所以坚持采用自己的代码替换了将近90%的内核栈吗,结果又怎么样呢?当然现在情况正变得越来越好。

目前Linux上和图像处理相关的项目所取得的进展状况如下:

  • glvnd在试图拆分OpenGL的接口,使其不依赖于X。
  • wayland提供了一套很好的协议标准设计,但人们仍然只把它看作是X server的替代品,而不是X11的替代品(译者注,X Window作为一套协议标准,其中的定义包括了X Server和X Client),当前唯一能胜任wayland要求的合成桌面系统只有mutter,而mutter还在发展中并不成熟。

内核支持GPU重置(译者注,应该和TDR有关)已有多年,但想要得到GPU厂家的充分测试是一件困难的事情,而且NVIDIA的驱动程序是不开源的,所以有问题也只有他们自己才能解决。

适配器损失adapter loss是一件麻烦的事情,X11的设计导致解决这个问题很棘手,当前的OpenGL作为API在这点上表现也很糟糕,Direct3D从一开始就内置适配器损失处理机制可以帮助应用程序解决这个问题。

因此,我们并不是真的需要为此重新设计内核栈,当前内核的驱动模型针对其需求已经足够好,Windows的WDDM也是一样。我们需要的是投入更多的人来解决那些重要的问题,太多的人只是在为自己的老板,自己关注的局部需求而工作,而目前全世界真正能够从全局审视整个内核栈设计的人也就在5个左右。(虽然能够为Android/ARM/Chrome写驱动的人很多,但我们仍然花了2~3年的时间才得到足够的资助实现了modesetting编程接口的原子化,这种工作才是对所有人都会有帮助的工作)。

 

 

也许是该谈谈全新的 Linux 显示驱动模型的时候了

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/47358.html

(0)
上一篇 2021年8月6日
下一篇 2021年8月6日

相关推荐

发表回复

登录后才能评论