Search code examples
macosquartz-graphicscore-image

How do you debug syntax errors in a Core Image kernel?


When writing a new Core Image filter, you need to write the kernel in the Core Image Kernel Language which is a mildly mutate OpenGL Shader Language. You compile these at runtime with something like this…

NSString *myCode = ...
NSArray *kernels = [CIKernel kernelsWithString:myCode];

The problem is any syntax error and you just get back a nil instead of an array. The documented API does not suggest a mechanism to get diagnostic information.

If you work on your filter in Quartz Composer, as recommended in the Apple docs, you will notice that it can give you syntax error information. (This only works for simple filters.)

So, how do you get diagnostic information back for an bad kernel source file?

Update: Depending on circumstances, you may get formatted lines on your console. If you are so lucky then you needn't worry about this, just look for lines like:

8: error: in function kernel vec4 clipDetection (uniform in sampler, uniform in float)
8: error: unknown variable name: gratuitous

Of course if you still need to get hold of the information…


Solution

  • If you use introspection on the CIKernel class, you will find a kernelsWithString:messageLog: method. There is no public interface to it, but don't let that stop you…

    NSString *myCode = ...
    NSMutableArray *messageLog = [NSMutableArray array];
    NSArray *kernels = [[CIKernel class] performSelector:@selector(kernelsWithString:messageLog:) withObject:myCode withObject:messageLog];
    if ( messageLog.count > 0) NSLog(@"Error: %@", messageLog.description);
    

    The messageLog argument wants to be a mutable array. In the event of errors, it will have some dictionaries put into it. The contents of these are documented nowhere visible on the internet, but they look something like this (in a case where I added "gratuitous error" to a kernel's source)…

    2012-12-06 17:56:53.077 MyProgram[14334:303] Error: (
            {
            CIKernelMessageDescription = "kernel vec4 clipDetection (uniform in sampler, uniform in float)";
            CIKernelMessageLineNumber = 8;
            CIKernelMessageType = CIKernelMessageTypeFunctionName;
        },
            {
            CIKernelMessageDescription = "unknown variable name: gratuitous";
            CIKernelMessageLineNumber = 8;
            CIKernelMessageType = CIKernelMessageTypeError;
        }
    )
    

    As always, think twice or more about leaving this in shipping code. It is undocumented and Apple could do anything to it at any time. They might even, you know, document it.