0
$\begingroup$

I am using MTKViews for select UI elements inside of my UIKit app. I have a central metal controller that does something somewhat like this:

public class MetalView: MTKView                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   {

    var id:Int? = nil
    func getBuffer() -> MTLCommandBuffer {
        if (id == nil) {
            id = MetalView.idCounter
            MetalView.idCounter += 1
            MetalView.frameRegistry.append(id!)
            setNeedsDisplay()
        }

        if MetalView.frameRegistry.contains(id!) {
            MetalView.frameRegistry.removeAll()
            if let buffer = MetalView.savedBuffer {
                buffer.commit()
                buffer.waitUntilCompleted()
            }
            MetalView.savedBuffer = MetalView.queue.makeCommandBuffer()
        }
        MetalView.frameRegistry.append(id!)
        return MetalView.savedBuffer!
    }

    static private var savedBuffer:MTLCommandBuffer? = nil
    static private var frameRegistry:[Int] = []
    static private var idCounter:Int = 0

}

Each metal UI Element subclasses this gets its own id allowing it to call getBuffer in its draw function to get the frame's command buffer.

This code is based on two assumptions

  1. Each MTKView gets its own drawable
  2. You should only make one MTLCommandBuffer per frame

That is how I understand things to work.

Unfortunately this is creating a fairly obvious synchronization error with the textures

enter image description here

This should be a gradient of uniform hue but the hue was rapidly switched and as a result this tearing is left with one part drawing a different hue than the other.

So I suppose my questions are:

  1. Are my assumptions correct
  2. What is the proper way to share a MTLCommandBuffer across Metal drawing objects when not all of them may need to draw every frame.
  3. How do I fix this issue?
$\endgroup$
  • $\begingroup$ My gut feeling is that you would want 1 command buffer per drawable per frame, but I don't know that's actually the case. Do you have overlapping MTKViews? What's the reasoning behind having multiple MTKViews? Seems like it would be easier if there was one view into which you drew multiple objects. $\endgroup$ – user1118321 Jul 26 '18 at 2:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.