【问题标题】:Rendering Quads Performance with Metal使用 Metal 渲染 Quads 性能
【发布时间】:2015-03-14 01:36:15
【问题描述】:

我正在尝试使用 Metal API 在 Apple A7 GPU 上尽可能快地渲染大量非常小的二维四边形。研究 GPU 的三角形吞吐量数,例如here,根据 Apple 在他们的主题演示期间在屏幕上引用 >1M 三角形,我希望能够以 60fps 的速度每帧渲染 500,000 个这样的四边形。考虑到所有这些都是可见的(在屏幕上,而不是被 z 缓冲区隐藏)和微小的(对于光栅化器来说很棘手),可能会少一些,所以这可能不是 GPU 超级优化的用例。也许那个 Apple 演示以 30fps 运行,所以假设大约 200,000 应该是可行的。肯定有 100,000……对吧?

但是,在我的测试应用程序中,最大值仅为 20,000 左右——不止于此,而且 iPad Air 上的帧速率降至 60 以下。它有 100,000 个四边形,以 14 fps 的速度运行,即吞吐量为 280 万三角形/秒(与 AnandTech 文章中引用的 6810 万个屏幕三角形相比!)。

即使我将四边形缩小为单个像素,使用微不足道的片段着色器,性能也不会提高。所以我们可以假设这是顶点绑定,并且 Xcode 中的 GPU 报告同意(“Tiler”为 100%)。顶点着色器也很简单,只做一点缩放和平移数学,所以我假设瓶颈是某个固定功能阶段...?

只是为了获得更多背景信息,我使用单个实例绘制调用渲染所有几何图形,每个实例一个四边形,即每个实例 4 个顶点。四边形的位置是从一个单独的缓冲区应用的,该缓冲区由顶点着色器中的实例 id 索引。我也尝试了其他一些方法(非实例化,所有顶点都预先转换,实例化+索引等),但这没有帮助。没有复杂的顶点属性、缓冲区/表面格式或我能想到的任何其他东西似乎可能会在驱动程序/GPU 中遇到缓慢的路径(尽管我当然不能确定)。混合已关闭。几乎所有其他东西都处于默认状态(视口、剪刀、ztest、剔除等)。

该应用程序是用 Swift 编写的,但希望这并不重要 ;)

我想了解的是,在渲染这样的四边形时(与“适当的”3d 场景相反),我所看到的性能是否符合预期,或者是否需要一些更高级的技术才能接近广告的三角形吞吐量。人们认为这里的限制瓶颈可能是什么?

另外,如果有人知道为什么这在 OpenGL 中可能比在 Metal 中更快(我没有尝试过,也想不出任何原因),那么我也很想听听。

谢谢

编辑:添加着色器代码。

vertex float4 vertex_shader(
        const constant float2* vertex_array [[ buffer(0) ]],
        const device QuadState* quads [[ buffer(1) ]],
        constant const Parms& parms [[ buffer(2) ]],
        unsigned int vid [[ vertex_id ]],
        unsigned int iid [[ instance_id ]] )
{
    float2 v = vertex_array[vid]*0.5f;

    v += quads[iid].position;

    // ortho cam and projection transform
    v += parms.cam.position;
    v *= parms.cam.zoom * parms.proj.scaling;

    return float4(v, 0, 1.0);
}


fragment half4 fragment_shader()
{
    return half4(0.773,0.439,0.278,0.4);
}

【问题讨论】:

  • 你能告诉我们你的顶点布局/描述符和你的着色器代码吗?在我在这里的示例应用程序中,我可以在 iPad mini 2 上达到每帧 150ktris,在 iPhone 6 上达到 >300ktris/帧。我的三角形的平均覆盖率为 2 个像素。
  • 当然,我在上面添加了着色器代码。我没有明确设置顶点布局。我还注意到对于 Tiler 来说,有多少屏幕被四边形覆盖很重要(我预计这对片段阶段很重要,但很惊讶地看到它对顶点阶段的影响如此之大......猜猜这是一个平铺缓存效果)。也就是说,将所有四边形集中在屏幕的一个小区域中,而不是将它们均匀地分布在整个地方,可以大大提高性能,然后我也可以打出大于 100k 的三角形。也许这就是它们达到 >1M 的方式:具有非常高 tri 计数的小物体..
  • 是的,瓦工与它有很大关系。这些小三角形中的大多数只会碰到单个图块,并且必须移动到 GPU 上的图块越少,拼贴器的开销就越少。 FWIW,我看不出你的着色器有什么明显的错误。

标签: ios swift opengl-es gpu metal


【解决方案1】:

如果没有看到您的 Swift/Objective-C 代码,我无法确定,但我猜您在调用您的实例化代码上花费了太多时间。当您的模型中有数百个三角形而不是两个三角形时,实例化很有用。

尝试创建一个包含 1000 个四边形的顶点缓冲区,看看性能是否有所提高。

【讨论】:

    猜你喜欢
    • 2012-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-22
    • 1970-01-01
    • 2022-12-01
    • 2018-12-30
    • 2012-12-05
    相关资源
    最近更新 更多