meaning-matters
meaning-matters

Reputation: 22946

How to pass arguments to Metal CIWarpKernel?

I have a simple Metal CIWarpKernel:

    float2 MyWarp(destination dest, float offset)
    {
        return float2(dest.coord().x + offset, dest.coord().y);
    }

and:

class MyWarpFilter : CIFilter
{
    var inputImage: CIImage?
    var inputOffset: Float = 100.0

    static var kernel: CIWarpKernel =
    { () -> CIWarpKernel in
        let url = Bundle.main.url(forResource: "MyWarp", withExtension: "ci.metallib")!
        let data = try! Data(contentsOf: url)
        return try! CIWarpKernel(functionName: "MyWarp", fromMetalLibraryData: data) <== ERROR
    }()

    override var outputImage : CIImage?
    {
        get
        {
            guard let input = inputImage else { return nil }

            let roiCallback: CIKernelROICallback =
            { _, rect -> CGRect in
                return CGRect(x: rect.minX, y: rect.minY, width: input.extent.width, height: input.extent.height)
            }

            let arguments: [Any] = [inputOffset]

            return MyWarpFilter.kernel.apply(extent: input.extent,
                                             roiCallback: roiCallback,
                                             image: input, arguments: arguments)
        }
    }
}

When I run this, I get the following run-time error (at line indicated above with <== ERROR):

Thread 1: Fatal error: 'try!' expression unexpectedly raised an error: Foundation._GenericObjCError.nilError

If I remove the second MyWarp() parameter, run the filter with arguments: [] and have a hard-coded offset, there's no error (and the filter translates the image by offset).

What am I doing wrong with passing arguments to the CIWarpKernel?

Upvotes: 1

Views: 609

Answers (1)

OOPer
OOPer

Reputation: 47886

Running your code with iOS Simulator 14.4/Xcode 12.4, I get the following error: (Not sure I made something wrong or this is just a problem of runtime versions.)

Thread 1: Fatal error: 'try!' expression unexpectedly raised an error: Error Domain=CIKernel Code=4 "(null)" UserInfo={CINonLocalizedDescriptionKey=If specified, destination must be the last parameter of a CIKernel function.}

So, at least, you may need to move the parameter destination dest to the last:

    float2 MyWarp(float offset, destination dest)
    {
        return float2(dest.coord().x + offset, dest.coord().y);
    }

Metal Shading Language for Core Image Kernels

destination A kernel parameter type that allows access to the position of the pixel currently being computed. This parameter, which is required for CIWarpKernel and optional for CIColorKernel and CIKernel, must be the last parameter to a kernel function.

Upvotes: 3

Related Questions