如何在iOS的Metal中链接过滤器?

7

我完成了Simon Gladman(@flexmonkey)的此教程,用于从AVFoundation中捕获图像并对输出应用滤镜。然而,我正在努力寻找一种方法来用自己的计算着色器替换模糊滤镜。换句话说,在那里提到的YCbCrColorConversion滤镜之后,我需要将我的自定义着色器连接起来。

let commandBuffer = commandQueue.makeCommandBuffer()
let commandEncoder = commandBuffer.makeComputeCommandEncoder()
// pipelineState has compiled YCbCrColorConversion filter
commandEncoder.setComputePipelineState(pipelineState)
commandEncoder.setTexture(ytexture, at: 0)
commandEncoder.setTexture(cbcrTexture, at: 1)
commandEncoder.setTexture(drawable.texture, at: 2) // out texture

commandEncoder.dispatchThreadgroups(threadGroups,threadsPerThreadgroup: threadGroupCount)
commandEncoder.endEncoding()

let inPlaceTexture = UnsafeMutablePointer<MTLTexture> .allocate(capacity: 1)
        inPlaceTexture.initialize(to: drawable.texture)

// How to replace this blur with my own filter?????
blur.encodeToCommandBuffer(commandBuffer, inPlaceTexture: inPlaceTexture, fallbackCopyAllocator: nil)

commandBuffer.presentDrawable(drawable)
commandBuffer.commit();

我应该创建一个新的commandBuffer、commandEncoder和单独的pipelineState来编译第二个内核函数吗?这将把第一个过滤器的输出作为第二个过滤器的输入。有没有更有效的方法来实现这一点,或者这是最优的方法?

我是Metal的初学者,因此非常欢迎对管道工作原理的任何解释。

1个回答

9
你不需要创建一个新的命令缓冲区或另一个计算编码器,但你需要创建一个计算管道状态来使用你自己的内核函数。应该在初始化期间执行这个操作,在你当前创建YCbCr转换管道状态的地方。
要将效果链接在一起,你需要创建一个中间纹理,作为YCbCr转换的输出纹理和你的内核的输入。可绘制纹理将成为你的内核函数的输出纹理。你可以像当前调度YCbCr转换工作一样派发你自己内核的工作(即每个线程组的线程数和线程组数量相同)。
中间纹理应该与可绘制纹理具有相同的尺寸和格式。你可以懒惰地创建它并持有一个引用,当可绘制大小改变时重新创建它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接