我在Metal中实现了Bezier曲线,希望实现卓越的性能。虽然速度非常好,但我看到数字远低于预期的性能(相对于各种设备的三角形/秒规格)。
具体来说,当我更改某些参数时,我对GPU的行为感到困惑。我使用drawIndexedPrimitives()
渲染数千条贝塞尔曲线。每个实例代表一条曲线,每个实例的顶点数表示每条曲线使用的三角形数。
我传递给顶点着色器的唯一缓冲区是每个实例的参数缓冲区,没有传递每顶点数据。实际贝塞尔曲线点在顶点着色器内计算,不加载任何每顶点数据。
这让我很困惑:我可以大大增加每个实例的顶点数量而不会影响性能,但是增加实例数会直接增加GPU帧处理时间。
我的期望是GPU不应该关心我是否添加实例或顶点 - 更多顶点意味着更多的工作。我错过了什么?
对于一个性能示例,就三角形/秒而言,iPad Pro似乎实现了大约2000条曲线,每条曲线由200个三角形组成,每个曲线大约40FPS(大约25ms /帧)。这相当于大约16M三角形/秒填充率,这明显低于该设备的预期性能。
在同一台iPad Pro上,将每曲线三角形的数量从200倍增加到400只会使每帧时间增加到大约31毫秒。在我们基本上将GPU的工作量增加一倍之后,这个数字增加了24%!如果我们将曲线数量加倍(将每曲线三角形数量保持为200),则每帧的性能下降到大约47ms。
请注意,在这两种情况下,GPU必须渲染完全相同数量的三角形 - 它们之间有什么不同?
完整代码可在GitHub上找到。