深度金属渲染速度

时间:2017-03-03 18:45:09

标签: swift macos metal

我一直在努力加快游戏中的渲染速度,但只是设法让它变得更慢,而且我很难知道这是怎么回事。我在2D游戏中绘制了一些地形,所以想象在各种纹理的屏幕上有长条纹。

先前的实现将整理各种纹理并迭代它们并以不同的方式绘制与纹理相关联的三角形,这可以想象导致更多的绘制调用并且在整个过程中多次强制切换一些制服如果我们绕着边缘缠绕的过程。

所以现在我所做的就是将所有纹理打包在一起,这样我就不必将它们更改出去,并且可以同时绘制大片三角形。这将绘制计数从接近4000降低到不到一千(通过Xcode中的捕获框架工具测量),但是大幅减慢了框架的速度。因此,使用相同数量的三角形渲染相同的场景,但fps从大约40到10。

在超过一千个简单的drawPrimitives(.Triangle ...之前,一次只有5或6个三角形,现在每次只有几百个调用超过100个三角形。

例如[drawPrimitives:3 vertexStart:1944 vertexCount:348 instanceCount:116],报告它需要1.93毫秒才能完成。

在一个帧捕获它显示这些调用绘制100左右需要2 + ms!为什么这么久!!这让我感到非常奇怪,因为它可以在大约3微秒内完成一个四边形,所以如果它缩放我会想象这个条带只需要.2ms

两个实现之间的着色器是相同的,并且非常简单。我描述了准备三角形的代码,它更快。我唯一可以指出的是实际的drawPrimitives调用,但无法弄清楚为什么它现在陷入困境。

那么为什么画面调用次数少4倍,导致帧速率提高3倍?我错过了为什么这么慢!我效率更高!!!

修改 这是着色器代码:

vertex TerrainFragmentIn terrainVertex(const device TerrainVertex* verts [[ buffer(0) ]],
                            uint v_id [[ vertex_id ]],
                            constant Constants &mvp [[buffer(1)]],
                            constant ModelMatrix &modelMat [[buffer(2)]]
                            ) {
    TerrainVertex vert = verts[v_id];

    TerrainFragmentIn outVertex;
    outVertex.position = mvp.viewProjectionMatrix * modelMat.modelMatrix * float4(vert.position.x,vert.position.y,0,1);
    outVertex.shadow  = vert.shadow;
    outVertex.uv = vert.tex;
    return outVertex;
}

fragment float4 terrainFragment(TerrainFragmentIn inFrag [[stage_in]],
                            texture2d<float, access::sample> colorTexture [[ texture(0) ]],
                            sampler colorSampler [[ sampler(0) ]]) {
    float4 color = colorTexture.sample(colorSampler, inFrag.uv);
    color *= float4(inFrag.shadow,inFrag.shadow,inFrag.shadow,1.0);

    return color * 2;
}

这些结构被定义为这样,并且在迅速方面是相同的:

struct TerrainVertex {
    float2 position [[ attribute(0) ]];
    float2 tex      [[ attribute(1) ]];
    float shadow    [[ attribute(2) ]];
};

struct Constants {
    float4x4 viewProjectionMatrix;
};

struct ModelMatrix {
    float4x4 modelMatrix;
};

90%的通话几乎没有状态变化 DrawCalls

每个三角形大约为20x30像素。在这些电话中,我没有做任何混合。我实际上希望我在捕获时获得诊断或警告/错误但是没有,遗憾的是没有。我在运行10.12.3的rMPB上进行测试。我还没有在iOS上尝试过。

1 个答案:

答案 0 :(得分:1)

在屏幕截图中,它显示实例计数为120.

在调用drawPrimitives时,是否将instanceCount参数设置为原始计数(看起来像它)。如果你是,那么每个绘制调用都会呈现120 * 120 = 14400个三角形,这可以解释为什么合并绘制调用会使你的帧速率恶化,因为你每次都要绘制三角形平方基元。

如果您不使用实例化(并且着色器暗示您不是),则应将instanceCount设置为1.