在哪里正确初始化MTLCommandBuffer?

时间:2019-01-31 16:37:41

标签: ios swift metal

使用GPU Capture按钮进行调试后,将显示一条警告:“您的应用程序在GPU工作期间创建了MTLBuffer对象。在加载时创建缓冲区以获得最佳性能。”

在我的代码中与MTLBuffer有关的唯一事情是每次调用绘图时都会创建MTLCommandBuffer:

override func draw(_ rect: CGRect){

    let commandBuffer = commandQueue.makeCommandBuffer()

    guard var
        image = image,
        let targetTexture:MTLTexture = currentDrawable?.texture else
    {
        return
    }

    let customDrawableSize:CGSize = drawableSize

    let bounds = CGRect(origin: CGPoint.zero, size: customDrawableSize)

    let originX = image.extent.origin.x
    let originY = image.extent.origin.y

    let scaleX = customDrawableSize.width / image.extent.width
    let scaleY = customDrawableSize.height / image.extent.height

    let scale = min(scaleX*IVScaleFactor, scaleY*IVScaleFactor)
    image = image
        .transformed(by: CGAffineTransform(translationX: -originX, y: -originY))
        .transformed(by: CGAffineTransform(scaleX: scale, y: scale))

    ciContext.render(image,
                     to: targetTexture,
                     commandBuffer: commandBuffer,
                     bounds: bounds,
                     colorSpace: colorSpace)


    commandBuffer?.present(currentDrawable!)

    commandBuffer?.commit()

}

我的第一个想法是将其移至其他范围,在此范围内,我可以将命令缓冲区定义为变量,然后在初始化框架时使其等于commandQueue.makeCommandBuffer()。这将立即导致应用程序崩溃。

我不确定如何在没有警告或崩溃的情况下正确进行初始化。 MTLCommandQueue是一个惰性变量。

以下是使其崩溃的更改:

class MetalImageView: MTKView
{
    let colorSpace = CGColorSpaceCreateDeviceRGB()

    var textureCache: CVMetalTextureCache?

    var sourceTexture: MTLTexture!

    var commandBuffer: MTLCommandBuffer?

    lazy var commandQueue: MTLCommandQueue =
        {
            [unowned self] in

            return self.device!.makeCommandQueue()
            }()!
    ...




override init(frame frameRect: CGRect, device: MTLDevice?)
{
    super.init(frame: frameRect,
               device: device ?? MTLCreateSystemDefaultDevice())



    if super.device == nil
    {
        fatalError("Device doesn't support Metal")
    }

    CVMetalTextureCacheCreate(kCFAllocatorDefault, nil, self.device!, nil, &textureCache)

    framebufferOnly = false

    enableSetNeedsDisplay = true

    isPaused = true

    preferredFramesPerSecond = 30

    commandBuffer = commandQueue.makeCommandBuffer()

}

然后我当然除去在我的绘制函数commandBuffer的定义中。

1 个答案:

答案 0 :(得分:1)

此警告涉及MTLBuffer S,不MTLCommandBuffer秒。

您当然不应该主动建立在你的初始化命令缓冲区。精确地在您要对GPU工作进行编码时(即,如您最初在draw方法中所做的那样)创建命令缓冲区。

关于诊断消息,很可能是Core Image在渲染图像时代表您创建了一个临时缓冲区。您对此无能为力,但是取决于缓冲区的大小和绘制的频率,这可能并不重要。