0

我有一个自定义的CIFilter,使用CIImageProcessorKernel. 内核本身非常简单:

@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

这很好用,因为它产生了预期的结果。我遇到的问题是它在带有两个 GPU 的 MacBook Pro 上使用集成 GPU,我希望它使用离散 GPU。如果我将MTLCreateSystemDefaultDevice()(离散 GPU)的结果传递给-[MPSImageAreaMin initWithDevice:...],则会出现断言失败:

-[MTLDebugComputeCommandEncoder setComputePipelineState:] 断言失败 computePipelineState 与不同的设备相关联

这大概是因为MTLComputeCommandEncoder负责运行的机器内部使用的实例-encodeToCommandBuffer:sourceTexture:destinationTexture:已经设置为使用集成 GPU。我认为这来自于从物体中commandBuffer拉出。CIImageProcessorOutput

我的问题:是否可以指定要使用的 GPU -encodeToCommandBuffer:sourceTexture:destinationTexture:?大概这涉及自定义输出/金属命令缓冲区,但我不确定。

4

1 回答 1

2

使用哪个 GPU 应由CIContext执行图像处理的 GPU 决定。您应该能够使用[CIContext contextWithMTLDevice:]初始化程序指定设备。

顺便说一句,从 macOS 10.15 开始,还有一个内置CIMorphologyRectangleMinimum过滤器可以做同样的事情。从 10.13 开始,还有一个循环版本可用。

于 2019-11-01T18:47:19.147 回答