Rendering into multiple views with Metal

91 views Asked by At

I have successfully used Metal to render into a simple view, and update at full FPS, by following and modifying the code at https://github.com/jim-ec/metal-hello-triangle

enter image description here

I am now trying to repeat the process by drawing into multiple views in an NSCollectionView.

enter image description here

My render code is as follows, where each view in the NSCollectionView has a global Renderer object as its delegate:

class Renderer {

/// Initialisation as per the linked tutorial

public func draw(in view: MTKView)
{
    let dataSize     = VERTEX_DATA.count * MemoryLayout.size(ofValue: VERTEX_DATA[0])
    VERTEX_DATA[1][1] = Float(arc4random_uniform(100)) / 100
    let vertexBuffer = view.device?.makeBuffer(bytes:   VERTEX_DATA,
                                              length:  dataSize,
                                              options: [])

    let commandBuffer  = mCommandQueue.makeCommandBuffer()!

    let commandEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: view.currentRenderPassDescriptor!)
    commandEncoder?.setRenderPipelineState(mPipeline)
    commandEncoder?.setVertexBuffer(vertexBuffer, offset: 0, index: 0)
    commandEncoder?.drawPrimitives(type: .triangle,
                                 vertexStart: 0,
                                 vertexCount: 3,
                                 instanceCount: 1)
    commandEncoder?.endEncoding()

    commandBuffer.present(view.currentDrawable!)
    commandBuffer.commit()
    commandBuffer.waitUntilCompleted()
}

}

The arc4random_uniform call is to make the triangles change colour, so I can confirm that they are redrawing.

Unfortunately, views only update around 3 times a second, and not at all in sync. Looking at instruments, the GPU is barely breaking a sweat, and the CPU overhead of both WindowServer and my app are pretty huge. The draw function is now very heavy with makeRenderCommandEncoder becoming a real bottleneck, and there are obviously some synchronisation issues given the sporadic updating.

I expected this to be more-or-less similar performance as I'm still doing a trivial amount of drawing, but it really isn't. What am I doing wrong?

Working example available at https://github.com/SirWhiteHat/MetalPerformanceProblem

Thank you!

0

There are 0 answers