Synchronize CARenderer with .private MTLTextuer

46 views Asked by At

What is the proper way to synchronize the work done by CARenderer when rendering to a MTLTexture that has storageMode = .private?

In another long and somewhat rambling post, I think I've proved that CARenderer is still doing work by the time I get to use the texture. In that post, I "solved" it by making the MTLHeap return textures that have a .hazardTrackingMode = .tracked.

However various other posts (that I can't find right now) indicate the synchronization is done at heap level, which doesn't sound the best for performance. For this, and also because I want to learn more, is there a way to synchronize the work done by CARenderer, given that the texture has mode == private? AFAIK you can't queue up a command buffer with a blit encoder on that texture resource, as that doesn't appear supported. Also, the docs indicate that's to sync GPU<->CPU, which is not relevant if the texture is .private only.

Relevant code that is calling CARenderer, below:

if let renderCommandBuffer: MTLCommandBuffer = queue.makeCommandBuffer() {
    let renderCommandEncoder: MTLRenderCommandEncoder = renderCommandBuffer.makeRenderCommandEncoder(descriptor: currentDescriptor)!
    renderCommandEncoder.label = "Clear Target"
    renderCommandEncoder.endEncoding()
    renderCommandBuffer.commit()
    renderCommandBuffer.waitUntilScheduled()
    
    // A CARenderer; already bound to a CALayer root and using some MTLTexture as a target
    rendererToUse.beginFrame(atTime: CACurrentMediaTime(), timeStamp: nil)
    rendererToUse.addUpdate(rendererToUse.bounds)
    rendererToUse.render()
    rendererToUse.endFrame()
    
    /*
     Trying to sync texture (to get around the pink frame problem).
     This works only for .managed targets, which we're not
     */
    if let blitCommandBuffer: MTLCommandBuffer = queue.makeCommandBuffer(), target.storageMode == .managed {
        let blitCommandEncoder: MTLBlitCommandEncoder = blitCommandBuffer.makeBlitCommandEncoder()!
        blitCommandEncoder.synchronize(resource: target)
        blitCommandEncoder.endEncoding()
        blitCommandBuffer.commit()
        blitCommandBuffer.waitUntilCompleted()
    }
    
    // HERE!
    // Magical code to synchronize the work done by CARenderer to the MTLTexture
}

Appologies if this is considered a duplicate post, I'm simply trying to ask the question more cleanly, without all the possibly muddled ideas of my previous post.

Full render code: https://gist.github.com/scornflake/2bca7aa3e877f0db36836a0fb575d731

0

There are 0 answers