Efficiently copying Swift Array to memory buffer for iOS Metal

后端 未结 3 448
再見小時候
再見小時候 2021-02-04 18:23

I am writing an iOS application using Apple\'s new Metal framework. I have an array of Matrix4 objects (see Ray Wenderlich\'s tutorial) that I need to pass in to a shader via

3条回答
  •  傲寒
    傲寒 (楼主)
    2021-02-04 18:46

    I've done this with an array of particles that I pass to a compute shader.

    In a nutshell, I define some constants and declare a handful of mutable pointers and a mutable buffer pointer:

    let particleCount: Int = 1048576
    var particlesMemory:UnsafeMutablePointer = nil
    let alignment:UInt = 0x4000
    let particlesMemoryByteSize:UInt = UInt(1048576) * UInt(sizeof(Particle))
    var particlesVoidPtr: COpaquePointer!
    var particlesParticlePtr: UnsafeMutablePointer!
    
    var particlesParticleBufferPtr: UnsafeMutableBufferPointer!
    

    When I set up the particles, I populate the pointers and use posix_memalign() to allocate the memory:

        posix_memalign(&particlesMemory, alignment, particlesMemoryByteSize)
    
        particlesVoidPtr = COpaquePointer(particlesMemory)
        particlesParticlePtr = UnsafeMutablePointer(particlesVoidPtr)
    
        particlesParticleBufferPtr = UnsafeMutableBufferPointer(start: particlesParticlePtr, count: particleCount)
    

    The loop to populate the particles is slightly different - I now loop over the buffer pointer:

        for index in particlesParticleBufferPtr.startIndex ..< particlesParticleBufferPtr.endIndex
        {
            [...]
    
            let particle = Particle(positionX: positionX, positionY: positionY, velocityX: velocityX, velocityY: velocityY)
    
            particlesParticleBufferPtr[index] = particle
        }
    

    Inside the applyShader() function, I create a copy of the memory which is used as both the input and output buffer:

        let particlesBufferNoCopy = device.newBufferWithBytesNoCopy(particlesMemory, length: Int(particlesMemoryByteSize),
            options: nil, deallocator: nil)
    
        commandEncoder.setBuffer(particlesBufferNoCopy, offset: 0, atIndex: 0)
    
        commandEncoder.setBuffer(particlesBufferNoCopy, offset: 0, atIndex: 1)
    

    ...and after the shader has run, I put the shared memory (particlesMemory) back into the buffer pointer:

        particlesVoidPtr = COpaquePointer(particlesMemory)
        particlesParticlePtr = UnsafeMutablePointer(particlesVoidPtr)
    
        particlesParticleBufferPtr = UnsafeMutableBufferPointer(start: particlesParticlePtr, count: particleCount)
    

    There's an up to date Swift 2.0 version of this at my GitHub repo here

提交回复
热议问题