最近,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 渲染器对每个渲染节点类型使用简单的着色器,并经常求助于屏幕外渲染以获得更复杂的内容。统一渲染器也具有(功能更强大的)每个节点的着色器,但它们不会依赖屏幕外渲染,而是会使用复杂的着色器来解释缓冲区中的数据。在游戏编程中,这种方法被称为超级着色器。
统一渲染器的实现不如旧的 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 请求生成纹理时创建 dmabuf(目前仅限 Vulkan 渲染器)。
有没有什么尖锐的边缘?
通常情况下,新功能也带来了新的潜在陷阱。以下是作为应用程序开发人员需要注意的一些事项
不再有 glshader 节点。是的,它们为 4.0 版本制作了一些精美的演示,但它们与旧的 GL 渲染器紧密相关,因为它们对该渲染器公开的 GLSL API 做出假设。因此,新渲染器不支持它们。
文档中已对此发出警告
如果存在问题,此函数将返回 FALSE 并报告错误。你应在依赖着色器进行渲染之前使用此函数,并在失败时使用具有更简单着色器或不使用着色器的回退。
值得庆幸的是,自 4.0 版本以来,GTK 获得了新功能,例如遮罩节点和对直透明度纹理的支持,许多 glshader 节点的用法不再必要。
分数位置。旧的 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 上渲染路径
- 可能包括字形渲染
- 主线程外的渲染
- 性能(在旧的和功能较弱的设备上)
其中一些将是我们近期和中期工作的重点。
总结
新的渲染器具有一些令人兴奋的功能,未来还会有更多功能。
请尝试一下,并告诉我们哪些功能有效,哪些功能无效。