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

cro*_*m87 5 vertex-shader ios metal

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

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

renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0)
Run Code Online (Sandbox Code Playgroud)

然后我们可以在着色器中检索它:

vertex float4 basic_vertex(const device VertexIn* vertexIn [[ buffer(0) ]], unsigned int vid [[ vertex_id ]])
Run Code Online (Sandbox Code Playgroud)

据我了解,每个顶点都会调用一次顶点函数,每次调用时顶点函数都会更新以包含顶点索引.

问题是,从哪里来的vertex_id?

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

renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0)
renderEncoder.setVertexBuffer(vertexBuffer2, offset: 0, index: 1)
Run Code Online (Sandbox Code Playgroud)

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

谢谢!

Ken*_*ses 7

这是由您在渲染命令编码器上进行的绘制调用确定的.采用最简单的绘制方法:

drawPrimitives(type:vertexStart:vertexCount:)
Run Code Online (Sandbox Code Playgroud)

vertexCount决定你的顶点函数调用多少次.传递给顶点函数的顶点ID是从vertexStartto到的范围内的顶点ID vertexStart + vertexCount - 1.

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

drawPrimitives(type:vertexStart:vertexCount:instanceCount:)
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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