Skia 或 Direct2D 如何使用 GPU 渲染线或多边形?

How does Skia or Direct2D render lines or polygons with GPU?

这是一道理解二维矢量图GPU加速渲染原理的题。

使用 Skia 或 Direct2D,您可以绘制例如圆角矩形,贝塞尔曲线,多边形,还有模糊等效果。

Skia / Direct2D 提供 CPU 和基于 GPU 的渲染。

对于CPU渲染,我或多或少可以想象一下呈现一个圆角矩形。我已经看到了很多不同的线条渲染算法。

但是对于GPU,我没有太多线索。

是否有一些基本示例可以向我展示这些东西如何工作的基本原理?

(可能在Skia的源代码中也能找到解决方案,但我担心它太复杂/通用以至于像我这样的菜鸟根本看不懂。)

对于 direct2d,没有源代码,但由于它在幕后使用 d3d10/11,因此很容易看到它在幕后使用 Renderdoc 做了什么。

基本上,d2d 倾向于通过尝试将任何几何类型放入单个缓冲区来最小化绘制调用,而 skia 具有一些取决于形状类型的专用着色器集。

因此,例如,如果您绘制贝塞尔曲线路径,Skia 将尽可能尝试使用曲面细分着色器(如果您之前渲染的元素是矩形,则需要新的绘制调用),因为您更改了管道状态.

D2D,另一方面,倾向于在 cpu 上进行细分,并推送到某个顶点缓冲区,并且仅当您更改画笔类型时才切换绘制调用(如果您从一种纯色画笔更改为另一种它可以保持相同的着色器,因此它不会切换),或者当缓冲区已满时,或者如果您从形状切换到文本(因为它需要发送纹理图集)。

请注意,当镶嵌贝塞尔曲线路径时,D2D 在使生成的几何体非自相交方面做得非常出色(因此即使在一些复杂的自相交路径上,alpha 混合也能正常工作)。

在圆角矩形的情况下,它做同样的事情,只是镶嵌成三角形。

这允许它在很大程度上减少绘制调用,并允许在非 msaa 表面上进行抗锯齿(这是在网格级别完成的,带有一些带 alpha 的小三角形)。它的缺点是它没有使用太多的硬件功能,并且发出的几何图形可能非常高,即使是看似简单的形状也是如此。

由于 d2d 更喜欢使用三角形带或三角形列表,因此在绘制简单的三角形列表时它可以做一些非常有趣的事情。

对于文本,d2d 使用实例化并为每个字符绘制一个实例四边形,它也擅长批处理这些,因此如果您连续多次调用一些绘制文本函数,它会尝试将其合并为一个也打电话。