使用MPSImageConvolution内核和Metal计算着色器

时间:2016-05-09 14:07:15

标签: ios xcode convolution metal compute-shader

我正在使用位于https://github.com/FlexMonkey/MetalVideoCapture的MetalVideoCapture示例。我在我的版本中唯一改变的是使用内核值的MPSImageConvolution(而不是MPSImageGaussianBlur):

[-2.0, -1.0, 0.0,
 -1.0,  1.0, 1.0, 
  0.0,  1.0, 2.0]

使用上述值无法以任何可见方式更改输出。但边缘增强内核,例如

[0.0, -1.0, 0.0, 
 0.0,  1.0, 0.0, 
 0.0,  0.0, 0.0]

有效,请注意仅按列主要顺序;即使这就是MPSImageConvolution所期望的,它也无法按行主顺序运行。我真的很难过。我不知道是否有一个明显的原因,卷积内核无法在计算管道中工作(仅在渲染管道中),但我无法在线找到任何信息。

我还修改了代码库,将内核应用于静态图像而不是实时视频源;然而,这产生了相同的结果。

我还想指出我在示例项目的留言板(https://github.com/FlexMonkey/MetalVideoCapture/issues/1#issuecomment-217609500)上发布了相同的问题。这个例子的作者同样像我一样难倒,这让我相信这是某种错误或在我的概念知识中存在的差距,为什么这甚至不能起作用。

2 个答案:

答案 0 :(得分:2)

我确实有一个解决方法,那就是避免使用就地纹理。试试这个:创建一个单独的目标纹理:

    let descriptor = MTLTextureDescriptor.texture2DDescriptorWithPixelFormat(
        drawable.texture.pixelFormat,
        width: drawable.texture.width,
        height: drawable.texture.height,
        mipmapped: false)

    let destination: MTLTexture = device!.newTextureWithDescriptor(descriptor)

YCbCrColorConversion着色器定位到目标位置:

commandEncoder.setTexture(destination, atIndex: 2) // out texture

...然后使用使用目的地的替代encodeToCommandBuffer

encodeToCommandBuffer(commandBuffer, sourceTexture: destination, destinationTexture: drawable.texture)

这些东西可以删除:

//        let inPlaceTexture = UnsafeMutablePointer<MTLTexture?>.alloc(1)
//        inPlaceTexture.initialize(drawable.texture)

西蒙

感谢Warren

答案 1 :(得分:1)

一般来说,除非将卷积滤波器实现为多通滤波器,否则卷积滤波器不会起作用。由于您正在查看相邻像素,因此在一个像素中写出结果会更改其旁边像素的输入,从而导致错误。像这样的小卷积通常被实现为MPS中的单通滤波器。您应该使用就地MPS编码方法,允许框架根据需要交换目标纹理。另一种节省内存的方法是使用MPSTemporaryImages(iOS 10及更高版本)。

MPSImageConvolution应检测使用模式失败和断言。确保在Xcode中打开Metal调试层。如果仍然没有断言,则无法检测到问题是值得的。 http://bugreporter.apple.com