Fragment function seems properly written but Metal complains

1.3k views Asked by At

TL;DR: Metal doesn't seem to detect what my vertex shader returns

I have these two functions written in MSL :

vertex float4 base_image_rect(constant float4 *pos [[buffer(0)]],
                                           uint vid [[vertex_id]]) {
    return pos[vid];
}

fragment float4 fragment_image_display(float4 vPos [[stage_in]],
                              texture2d<float, access::sample> imageToRender [[texture(0)]],
                              sampler imageSampler [[sampler(0)]]) {
    return imageToRender.sample(imageSampler, float2(vPos.x, vPos.y));
}

When I try to create my render pipeline state with those, using this code:

// Make image display render pipeline state
let imageDisplayStateDescriptor = MTLRenderPipelineDescriptor()
imageDisplayStateDescriptor.colorAttachments[0].pixelFormat = view.colorPixelFormat
imageDisplayStateDescriptor.vertexFunction = library.makeFunction(name: "base_image_rect")
imageDisplayStateDescriptor.fragmentFunction = library.makeFunction(name: "fragment_image_display")

displayImagePipelineState = try! device.makeRenderPipelineState(descriptor: imageDisplayStateDescriptor)

There is an error at the creation of the pipeline state:

fatal error: 'try!' expression unexpectedly raised an error: Error Domain=CompilerError Code=1 "Link failed: fragment input vPos was not found in vertex shader outputs" [...]

I checked and rechecked the code and can't understand what's wrong.

Any ideas? Thank you!

1

There are 1 answers

3
Ken Thomases On BEST ANSWER

Try replacing stage_in with position. I think that stage_in is mostly used with structs where each field is either annotated with a specific attribute qualifier or matched by name. Apparently, when it's used with a non-struct type, it's trying to match by name. For example, if your vertex function were to output a struct one of whose fields was vPos, that would find it.