2

I'm trying to compile custom filters using MSL as discussed in this 2017 WWDC and in this part of the CIFilter Documentation. Without the MTLLINKER_FLAGS my program runs smoothly, but with the flags turned on (value set to -cifilter), my program's metal device.defaultLibrary fails to return vertex and fragment funcations. In fact, when I print out the library's function names they are all empty.

guard let library = device.newDefaultLibrary() else { return }
let pipelineDescriptor = MTLRenderPipelineDescriptor()
pipelineDescriptor.sampleCount = 1
pipelineDescriptor.colorAttachments[0].pixelFormat = .bgra8Unorm
pipelineDescriptor.depthAttachmentPixelFormat = .invalid

NSLog("%@", library.functionNames)
pipelineDescriptor.vertexFunction = library.makeFunction(name: "mapTexture")
pipelineDescriptor.fragmentFunction = library.makeFunction(name: "displayTexture")

do {
    try renderPipelineState = device.makeRenderPipelineState(descriptor: pipelineDescriptor)
}
catch {
    NSLog("%@", error.localizedDescription)
    assertionFailure("Failed creating a render state pipeline. Can't render the texture without one.")
    return
}

Metal Code:

    #include <metal_stdlib>
using namespace metal;

typedef struct {
    float4 renderedCoordinate [[position]];
    float2 textureCoordinate;
} TextureMappingVertex;

vertex TextureMappingVertex mapTexture(unsigned int vertex_id [[ vertex_id ]]) {
    float4x4 renderedCoordinates = float4x4(float4(-1.0, -1.0, 0.0, 1.0),
                                            float4( 1.0, -1.0, 0.0, 1.0),
                                            float4(-1.0,  1.0, 0.0, 1.0),
                                            float4( 1.0,  1.0, 0.0, 1.0));
    float4x2 textureCoordinates = float4x2(float2( 0.0, 1.0),
                                           float2( 1.0, 1.0),
                                           float2( 0.0, 0.0),
                                           float2( 1.0, 0.0));
    TextureMappingVertex outVertex;
    outVertex.renderedCoordinate = renderedCoordinates[vertex_id];
    outVertex.textureCoordinate = textureCoordinates[vertex_id];

    return outVertex;
}

fragment half4 displayTexture(TextureMappingVertex mappingVertex [[ stage_in ]],
                              texture2d<float, access::sample> texture [[ texture(0) ]]) {
    constexpr sampler s(address::clamp_to_edge, filter::linear);

    return half4(texture.sample(s, mappingVertex.textureCoordinate));
}
Chris Wood
  • 306
  • 3
  • 13
  • 1
    I'm no Metal aficionado, but it rather looks like you're trying to extract your custom functions from the default system library, not your own metal file. – Ash Aug 09 '18 at 16:17
  • Oh, looking back now it does look like my library init is wrong. Thanks for pointing that out! – Chris Wood Aug 14 '18 at 00:36
  • No problem! Does it work now? – Ash Aug 14 '18 at 05:48
  • Since you are writing a custom filter I guess you already have found sucess with what I am stuck at. I am trying to apply a simple vignette filter to a live camera feed using metal. The results are pretty slow and laggy, please check this if you can tell me what is missing:https://stackoverflow.com/q/53898780/1364053 – nr5 Dec 23 '18 at 02:50
  • also the value to set is not -cifilter but -cikernel – AndyRoid Feb 26 '19 at 07:23

0 Answers0