【问题标题】:How many times is the vertex shader called with metal?用金属调用顶点着色器多少次?
【发布时间】:2017-10-07 15:50:49
【问题描述】:

我一直在学习一些基本的金属渲染,但我对一些基本概念感到困惑:

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

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?

谢谢!

【问题讨论】:

    标签: ios metal vertex-shader


    【解决方案1】:

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

    drawPrimitives(type:vertexStart:vertexCount:)
    

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

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

    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 索引到该缓冲区)。不过,Metal 本身并不知道这一点。

    【讨论】:

      猜你喜欢
      • 2017-06-13
      • 1970-01-01
      • 2020-01-01
      • 1970-01-01
      • 2016-11-13
      • 2012-06-28
      • 2015-11-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多