用金属调用顶点着色器多少次?

时间:2017-10-07 15:50:49

标签: ios metal vertex-shader

我一直在学习一些基本的金属渲染,我坚持一些基本概念:

我知道我们可以使用以下方法将顶点数据发送到着色器:

renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0)

然后我们可以使用:

在着色器中检索它
vertex float4 basic_vertex(const device VertexIn* vertexIn [[ buffer(0) ]], unsigned int vid [[ vertex_id ]])

据我了解,顶点函数将在每个顶点调用一次,并且vertex_id将在每次调用时更新以包含顶点索引。

问题是,从哪里来的vertex_id?

我可以向着色器发送更多不同大小的数据:

renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0)
renderEncoder.setVertexBuffer(vertexBuffer2, offset: 0, index: 1)

如果vertexBuffer有3个元素,而vertexBuffer2有10个元素......被调用的顶点函数有多少次? 10?

谢谢!

1 个答案:

答案 0 :(得分:6)

这取决于您在渲染命令编码器上进行的绘制调用。采用最简单的绘制方法:

drawPrimitives(type:vertexStart:vertexCount:)

vertexCount确定调用顶点函数的次数。传递给顶点函数的顶点ID是vertexStartvertexStart + vertexCount - 1范围内的顶点ID。

如果你考虑另一种绘制方法:

drawPrimitives(type:vertexStart:vertexCount:instanceCount:)

它遍及相同范围的顶点ID。但是,它会调用顶点函数vertexCount * instanceCount次。将进行instanceCount次调用,顶点ID为vertexStart。对于这些调用,实例ID的范围从0到instanceCount - 1。同样,将有instanceCount次调用,其顶点ID为vertexStart + 1(假设为vertexCount >= 2),其中一个实例ID为[0..instanceCount-1]。等

其他绘制方法有各种其他选项,但它们通常不会影响顶点函数的调用次数。例如,baseInstance会更改实例ID的范围,但不会更改其大小。

各种drawIndexedPrimitives()方法从缓冲区获取特定的顶点ID,而不是枚举范围内的所有顶点ID。该缓冲区可以在多个位置包含给定的顶点ID。对于这种情况,我认为没有定义是否可以针对相同的顶点ID和实例ID多次调用顶点函数。 Metal可能会试图避免重复工作,但实际上最好只是为索引缓冲区中的每个索引调用顶点函数,即使多个这样的索引最终都是相同的顶点ID。

传递给顶点处理阶段的缓冲区中顶点和数据之间的关系完全取决于您。您根本不必传递任何缓冲区。例如,顶点函数可以仅从顶点ID和实例ID完全计算地生成顶点信息。

当然,至少有一些缓冲区包含使用顶点ID索引的每顶点数据的数组,这是很常见的。其他缓冲区可能是对所有顶点都相同的统一数据(也就是说,您不使用顶点ID索引到该缓冲区)。但金属本身并不知道这一点。