title: Where do I properly initialize my MTLCommandBuffer?
body: <p>After debugging using the GPU Capture button, a warning is displayed "Your application created a MTLBuffer object during GPU work. Create buffers at load time for best performance."</p>
  
  <p>The only thing related to a MTLBuffer in my code is the creation of a MTLCommandBuffer every time draw is called: </p>
  
  <pre><code>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()
  
  }
  </code></pre>
  
  <p>My first thought was to move that to a different scope, where I can define my command buffer as a variable, and then make it equal commandQueue.makeCommandBuffer() when the frame is initialized. This immediately crashes the application.</p>
  
  <p>I'm not sure how to initialize this properly without a warning or crash. The MTLCommandQueue is a lazy var.</p>
  
  <p>Here are the changes that makes it crash:</p>
  
  <pre><code>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, &amp;textureCache)
  
      framebufferOnly = false
  
      enableSetNeedsDisplay = true
  
      isPaused = true
  
      preferredFramesPerSecond = 30
  
      commandBuffer = commandQueue.makeCommandBuffer()
  
  }
  </code></pre>
  
  <p>Then I of course remove the definition of commandBuffer in my draw function.</p>