用金属渲染四边形性能

时间:2015-01-15 15:39:44

标签: ios swift opengl-es gpu metal

我尝试使用Metal API在Apple A7 GPU上尽可能快地渲染大量非常小的2D四边形。研究GPU的三角形吞吐量数字,例如here,并且在他们的主题演示期间,Apple在屏幕上引用了> 1M三角形,我希望能够以60fps的速度每帧渲染500,000个这样的四边形。也许少一点,因为所有这些都是可见的(在屏幕上,没有被z缓冲区隐藏)和微小的(对于光栅化器来说很棘手),所以这可能不是GPU用于超级优化的用例。也许Apple演示以30fps的速度运行,所以让我们说~200,000应该是可行的。当然是100,000 ......对吧?

然而,在我的测试应用程序中,最大值仅为~20,000 - 超过此值,并且iPad Air上的帧速率降至60以下。使用100,000个四边形时,它以14 fps的速度运行,即吞吐量为2.8M trianlges / sec(与AnandTech文章中引用的68.1M onscreen 三角形相比!)。

即使我使用一个简单的片段着色器使四边形像素变小,性能也不会提高。所以我们可以假设这是顶点绑定的,并且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);
}

1 个答案:

答案 0 :(得分:1)

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

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