GTK 新渲染器

最近,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(左)ngl(右)
近距离视图

新功能

如果没有一些实实在在的好处,我们就不会做这么多工作。当然,这里有一些新特性和功能。让我们来看一些

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

GL 与 NGL 的近距离视图

分数缩放。抗锯齿也是让我们正确处理分数缩放的基础。如果你的 1200 × 800 窗口设置为缩放到 125 %,使用统一渲染器,我们将使用 1500 × 1000 大小的帧缓冲区,而不是让合成器缩小 2400 × 1600 的图像。像素少得多,图像更清晰。

任意渐变。旧的 GL 渲染器处理具有最多 6 个颜色停靠点的线性、径向和圆锥渐变。统一渲染器允许无限数量的颜色停靠点。新的渲染器还将抗锯齿应用于渐变,因此锐利的边缘将具有平滑的线条。

具有 64 个颜色停靠点的线性渐变

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 上的路径渲染
  • 可能包括字形渲染
  • 脱离主线程的渲染
  • 性能(在旧的和功能较弱的设备上)

其中一些将是我们近期和中期工作的重点。

总结

新的渲染器具有一些令人兴奋的功能,并且会有更多功能即将推出。

请尝试一下,并告诉我们哪些对您有效,哪些无效。