尝试在Metal和Core Image的帮助下,将简单的小插图滤镜应用于iPhone6的原始相机提要时,我发现在MTKView中处理和渲染的帧之间存在很多滞后

我遵循的方法是(MetalViewController.swift):

  • 使用AVCaptureVideoDataOutputSampleBufferDelegate获取原始相机输出
  • 转换CMSampleBuffer> CVPixelBuffer> CGImage
  • 使用此MTLTexture创建一个CGImage

  • 点号2和3在名为fillMTLTextureToStoreTheImageData的方法中
  • CIFilter应用于从CIImage中的MTLTexture获取的MTKViewDelegate

  •     func draw(in view: MTKView) {
    
            if let currentDrawable = view.currentDrawable {
                let commandBuffer = self.commandQueue.makeCommandBuffer()
    
                if let myTexture = self.sourceTexture{
    
                    let inputImage = CIImage(mtlTexture: myTexture, options: nil)
    
                    self.vignetteEffect.setValue(inputImage, forKey: kCIInputImageKey)
    
                    self.coreImageContext.render(self.vignetteEffect.outputImage!, to: currentDrawable.texture, commandBuffer: commandBuffer, bounds: inputImage!.extent, colorSpace: self.colorSpace)
    
                    commandBuffer?.present(currentDrawable)
    
                    commandBuffer?.commit()
                }
            }
        }
    

    性能根本不是苹果在此文档中提到的:https://developer.apple.com/library/archive/documentation/GraphicsImaging/Conceptual/CoreImaging/ci_tasks/ci_tasks.html#//apple_ref/doc/uid/TP30001185-CH3-TPXREF101

    我想念什么吗?

    最佳答案

    您的第2步太慢了,无法支持实时渲染...,看来您缺少了几个步骤。为了您的目的,通常会:

    建立:

  • 创建CVPixelBuffer池-使用CVPixelBufferPoolCreate
  • 使用CVMetalTextureCacheCreate创建一个金属纹理池

  • 对于每一帧:
  • 转换CMSampleBuffer> CVPixelBuffer> CIImage
  • 通过过滤器管道
  • 传递CIImage
  • 将输出图像从步骤1中创建的池中渲染为CVPixelBuffer
  • 使用CVMetalTextureCacheCreateTextureFromImage与过滤的CVPixelBuffer一起创建金属质感

  • 如果设置正确,所有这些步骤将确保您的图像数据保留在GPU上,而不是从GPU到CPU再回到GPU进行显示。

    好消息是,所有这些都在Apple https://developer.apple.com/library/archive/samplecode/AVCamPhotoFilter/Introduction/Intro.html#//apple_ref/doc/uid/TP40017556的AVCamPhotoFilter示例代码中进行了演示。特别是请参见RosyCIRenderer类及其 super class FilterRenderer

    10-08 12:28