Reputation: 5234
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."
The only thing related to a MTLBuffer in my code is the creation of a MTLCommandBuffer every time draw is called:
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()
}
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.
I'm not sure how to initialize this properly without a warning or crash. The MTLCommandQueue is a lazy var.
Here are the changes that makes it crash:
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()
}
Then I of course remove the definition of commandBuffer in my draw function.
Upvotes: 1
Views: 2243
Reputation: 31782
This warning is related to MTLBuffer
s, not MTLCommandBuffer
s.
You should certainly not proactively create a command buffer in your initializer. Create command buffers precisely when you're about to encode GPU work (i.e. as you were doing initially, in your draw
method).
As for the diagnostic message, it's probably the case that Core Image is creating a temporary buffer on your behalf when rendering your image. There isn't much you can do about this, but depending on the size of the buffer and the frequency of drawing, it probably isn't a big deal.
Upvotes: 2