Swapping Textures in Metal with the Blit Command Encoder

813 views Asked by At

I recently implemented a water simulation in Metal using a ping pong buffer and compute shaders. It is working well but I was just wondering what the cost of swapping the textures several times a frame would be and whether this could be improved by using the Blit Command Encoder?

Here is a sample of the code:

    let computeEncoder = commandBuffer.makeComputeCommandEncoder()!
    computeEncoder.setComputePipelineState(pipelineState)
    computeEncoder.setTexture(textureA, index: 0)
    computeEncoder.setTexture(textureB, index: 1)

    var width = pipelineState.threadExecutionWidth
    var height = pipelineState.maxTotalThreadsPerThreadgroup / width
    let threadsPerThreadGroup = MTLSizeMake(width, height, 1)
    width = Int(textureA.width)
    height = Int(textureA.height)
    let threadsPerGrid = MTLSizeMake(width, height, 1)

    computeEncoder.dispatchThreads(threadsPerGrid, threadsPerThreadgroup: threadsPerThreadGroup)
    computeEncoder.endEncoding()

    swap(&textureA, &textureB)
1

There are 1 answers

2
Eoin Roe On

This method works nicely:

    let blitEncoder = commandBuffer.makeBlitCommandEncoder()

    blitEncoder?.copy(from: textureA, to: temp)
    blitEncoder?.copy(from: textureB, to: textureA)
    blitEncoder?.copy(from: temp, to: textureB)

    blitEncoder?.endEncoding()

I haven't done any tests to see if this improves performance although I assume it does. Will post results once I have!