I've got a custom CIFilter
, implemented using a subclass of CIImageProcessorKernel
. The kernel itself is very simple:
@implementation ErosionFilterKernel
+ (BOOL)processWithInputs:(NSArray<id<CIImageProcessorInput>> *)inputs
arguments:(NSDictionary<NSString *,id> *)arguments
output:(id<CIImageProcessorOutput>)output
error:(NSError *__autoreleasing *)error
{
error = error ?: &(NSError * __autoreleasing){ nil };
id<MTLCommandBuffer> commandBuffer = output.metalCommandBuffer;
id<MTLTexture> sourceTexture = [inputs.firstObject metalTexture];
id<MTLTexture> destinationTexture = output.metalTexture;
NSInteger distance = [arguments[@"erosionDistance"] integerValue] ?: 1;
MPSImageAreaMin *erodeFilter = [[MPSImageAreaMin alloc] initWithDevice:commandBuffer.device
kernelWidth:distance
kernelHeight:distance];
[erodeFilter encodeToCommandBuffer:commandBuffer sourceTexture:sourceTexture destinationTexture:destinationTexture];
return YES;
}
@end
This works fine, in that it produces the expected result. The problem I'm having is that it uses the integrated GPU on a MacBook Pro with two GPUs, and I'd like it to use the discrete GPU. If I pass the result of MTLCreateSystemDefaultDevice()
(the discrete GPU) into -[MPSImageAreaMin initWithDevice:...]
, I get an assertion failure:
-[MTLDebugComputeCommandEncoder setComputePipelineState:] failed assertion computePipelineState is associated with a different device
This is presumably because the instance of MTLComputeCommandEncoder
used internally by the machinery responsible for running -encodeToCommandBuffer:sourceTexture:destinationTexture:
has already been set up to use the integrated GPU. I think this comes from the commandBuffer
pulled from the CIImageProcessorOutput
object.
My question:
Is it possible to specify the GPU to be used by -encodeToCommandBuffer:sourceTexture:destinationTexture:
? Presumably that involves customizing the output/metal command buffer, but I'm not sure about that.
Which GPU is used should be determined by the CIContext
that performs the image processing. You should be able to specify the device by using the [CIContext contextWithMTLDevice:]
initializer.
By the way, since macOS 10.15 there's also a built-in CIMorphologyRectangleMinimum
filter that does the same. And there's also a circular version that's available since 10.13.