在金属着色器中的缓冲区之间进行选择

时间:2018-10-03 21:17:44

标签: metal

我正在努力将OpenGL应用程序移植到Metal。在我的旧应用程序中,我曾经绑定两个缓冲区,一个绑定有顶点和各自的颜色,一个绑定有顶点和各自的纹理,并根据某些应用程序逻辑在这两个缓冲区之间切换。现在在Metal中,我从Hello Triangle示例开始,我尝试运行此顶点着色器

vertex RasterizerData
vertexShader(uint vertexID [[vertex_id]],
             constant AAPLVertex1 *vertices1 [[buffer(AAPLVertexInputIndexVertices1)]],
             constant AAPLVertex2 *vertices2 [[buffer(AAPLVertexInputIndexVertices2)]],
             constant bool &useFirstBuffer [[buffer(AAPLVertexInputIndexUseFirstBuffer)]])
{
    float2 pixelSpacePosition;
    if (useFirstBuffer) {
        pixelSpacePosition = vertices1[vertexID].position.xy;
    } else {
        pixelSpacePosition = vertices2[vertexID].position.xy;
    }
    ...

和此Objective-C代码

bool useFirstBuffer = true;
[renderEncoder setVertexBytes:&useFirstBuffer
                       length:sizeof(bool)
                      atIndex:AAPLVertexInputIndexUseFirstBuffer];
[renderEncoder setVertexBytes:triangleVertices
                       length:sizeof(triangleVertices)
                      atIndex:AAPLVertexInputIndexVertices1];

(其中AAPLVertexInputIndexVertices1 = 0AAPLVertexInputIndexVertices2 = 1AAPLVertexInputIndexUseFirstBuffer = 3),这将导致vertices2永远不会被访问,但是仍然出现错误:failed assertion 'Vertex Function(vertexShader): missing buffer binding at index 1 for vertices2[0].' < / p>

如果我在Metal代码中将if (useFirstBuffer)替换为if (true),则一切正常。怎么了?

2 个答案:

答案 0 :(得分:1)

当您对条件语句进行硬编码时,编译器足够聪明,可以消除引用缺少缓冲区的分支(通过dead-code elimination),但是当必须在运行时评估条件语句时,编译器不会不知道该分支永远不会被采用。

由于必须绑定所有声明的缓冲区参数,因此,未绑定的缓冲区将不受约束地跳到验证层。如果不遵循该路径,可以在Vertices2插槽(使用-setVertexBytes:length:atIndex:)上绑定一些“虚拟”字节。缓冲区的长度相同并不重要,因为毕竟虚拟缓冲区永远不会真正被访问。

答案 1 :(得分:0)

在atIndex参数中,您使用值AAPLVertexInputIndexUseFirstBuffer和AAPLVertexInputIndexVertices1调用代码,但在Metal代码中,值AAPLVertexInputIndexVertices1和AAPLVertexInputIndexVertices2出现在buffer()规范中。看来您需要在调用代码中使用AAPLVertexInputIndexVertices1而不是AAPLVertexInputIndexUseFirstBuffer。

相关问题