最近,GTK 新增了两个渲染器:一个用于 GL,另一个用于 Vulkan。
由于命名很难,我们重用了现有名称,并将它们称为“ngl”和“vulkan”。它们是由相同的源代码构建的,因此我们也称它们为“统一”渲染器。
但它们令人兴奋之处是什么?
单一来源
如前所述,这两个渲染器由相同的源代码构建。它被建模为遵循 Vulkan API,并进行了一些抽象来涵盖 Vulkan 和 GL(更具体地说,GL 3.3+ 和 GLES 3.0+)之间的差异。这使我们可以共享大部分基础设施,用于遍历场景图、维护变换和其他状态、缓存纹理和字形,并且更容易使两个渲染器保持最新并保持一致。
这种统一的方法能否进一步扩展,以涵盖 macOS 上的基于 Metal 的渲染器或 Windows 上的基于 DirectX 的渲染器?有可能。Vulkan/GL 组合的优势在于它们基本上共享相同的着色器语言(GLSL,有一些变体)。Metal 或 DirectX 则不是这样。对于这些平台,我们需要复制着色器或使用像 SPIRV-Cross 这样的翻译工具。
如果这让你感到兴奋,欢迎提供帮助。
实现细节
旧的 GL 渲染器为每种渲染节点类型使用简单的着色器,并且经常为了更复杂的内容而求助于离屏渲染。统一渲染器也具有(更强大的)每个节点的着色器,但是它们不会依赖于离屏渲染,而是会使用一个复杂的着色器来解释缓冲区中的数据。在游戏编程中,这种方法被称为 ubershader。
统一渲染器的实现不如旧的 GL 渲染器优化,并且编写时侧重于正确性和可维护性。因此,它可以正确处理更多种类的渲染节点树。
这是一个看起来无害的示例
repeat { bounds: 0 0 50 50; child: border { outline: 0 0 4.3 4.3; widths: 1.3; } }


新功能
如果没有一些实实在在的好处,我们就不会做这么多工作。当然,这里有一些新特性和功能。让我们来看一些
抗锯齿。旧的 GL 渲染器的一个大问题是它会丢失精细的细节。如果某个东西足够小,可以落在一个像素线的边界之间,它就会直接消失。特别是,这可能会影响下划线,例如助记符。统一渲染器通过进行抗锯齿处理来更好地处理这种情况。这不仅有助于保留精细细节,还可以防止原始图形的轮廓出现锯齿状。

分数缩放。抗锯齿也是让我们正确处理分数缩放的基础。如果你的 1200 × 800 窗口设置为缩放到 125 %,使用统一渲染器,我们将使用 1500 × 1000 大小的帧缓冲区,而不是让合成器缩小 2400 × 1600 的图像。像素少得多,图像更清晰。
任意渐变。旧的 GL 渲染器处理具有最多 6 个颜色停靠点的线性、径向和圆锥渐变。统一渲染器允许无限数量的颜色停靠点。新的渲染器还将抗锯齿应用于渐变,因此锐利的边缘将具有平滑的线条。

Dmabufs。简要偏离新渲染器,我们致力于 dmabuf 支持和图形卸载,去年秋季。新的渲染器支持此功能,并将其扩展为在被要求通过 render_texture API(目前仅限 Vulkan 渲染器)生成纹理时创建 dmabufs。
有任何尖锐的边缘吗?
通常情况下,新功能也可能带来新的陷阱。作为应用程序开发人员,以下是一些需要注意的事项
不再有 glshader 节点。是的,它们为 4.0 版本制作了一些花哨的演示,但是它们与旧的 GL 渲染器紧密相关,因为它们对该渲染器公开的 GLSL API 做出了假设。因此,新的渲染器不支持它们。
文档中已警告过您
如果存在问题,此函数将返回 FALSE 并报告错误。您应该在使用着色器进行渲染之前使用此函数,并且如果失败,则使用具有更简单着色器或不使用着色器的回退。
值得庆幸的是,许多 glshader 节点的用法不再必要,因为自 4.0 版本以来,GTK 已经获得了新功能,例如遮罩节点和对直接 alpha 纹理的支持。
分数位置。旧的 GL 渲染器会四舍五入,因此您可以侥幸地向它传递分数位置。新的渲染器会将事物放置在您告诉它的位置。这有时可能会产生意想不到的后果,因此应该留意并确保您的位置在它们应该在的地方。
特别是,请注意 cairo 风格的绘图,在其中将线放置在半像素位置,以便它们精确地填充一行的像素。
驱动程序问题。新的渲染器正在以新的和不同的方式使用图形驱动程序,因此有可能触发该方面的问题。
请将您看到的问题提交给 GTK,即使它们看起来像是驱动程序问题,因为对于我们来说,了解新代码在各种驱动程序和硬件上的工作情况非常有用。
但它更快吗?
不,新的渲染器(目前)并不更快。
旧的 GL 渲染器针对速度进行了大量优化。它还使用简单得多的着色器,并且不进行诸如抗锯齿等功能所需的数学运算。我们希望最终使新的渲染器更快,但即使在我们实现该目标之前,新功能和正确性也使它们非常令人兴奋。所有基于 GPU 的渲染器都足够快,可以以 60 或 144 fps 的速度渲染当今的 GTK 应用程序。
话虽如此,在一些非科学基准测试中,Vulkan 渲染器在某些方面接近并超过了旧的 GL 渲染器。新的 GL 渲染器由于我们尚未追踪到的某些原因而速度较慢。
新默认值
在刚刚发布的 4.13.6 快照中,我们已将 ngl 渲染器设置为新的默认值。这是一个试探气球,渲染器需要更广泛地使用不同的应用程序进行测试,以验证它们是否已为生产做好准备。如果出现重大问题,我们可以将 4.14 版本的渲染器恢复为 gl 渲染器。
我们决定暂时不将 Vulkan 渲染器设置为默认值,因为它在一些应用程序集成方面落后于 GL 渲染器:webkit GTK4 端口与 GL 一起使用,而不是与 Vulkan 一起使用,并且 GtkGLArea 和 GtkMediaStream 目前都生成 Vulkan 渲染器无法直接导入的 GL 纹理。所有这些问题都将在不久的将来得到解决,然后我们将重新考虑默认渲染器的决定。
如果您在非常旧的硬件上使用 GTK,您可能会更好地使用旧的 GL 渲染器,因为它对 GPU 的要求更少。您可以使用 GSK_RENDERER 环境变量覆盖渲染器选择
GSK_RENDERER=gl
未来计划和可能性
新的渲染器为实现我们长期以来一直想要的东西奠定了良好的基础,例如
- 正确的颜色处理(包括 HDR)
- GPU 上的路径渲染
- 可能包括字形渲染
- 脱离主线程的渲染
- 性能(在旧的和功能较弱的设备上)
其中一些将是我们近期和中期工作的重点。
总结
新的渲染器具有一些令人兴奋的功能,并且会有更多功能即将推出。
请尝试一下,并告诉我们哪些对您有效,哪些无效。