arraysswiftmetalmtlbuffer

Update MTLBuffer from Array with offset


I'm trying some test coding with swift, Metal and iOS. I have an MTLBuffer and an Array:

    var uint16Array:[UInt16] = Array(repeating: 0, count: 16)
    var mtlBuffer:MTLBuffer = device.makeBuffer(bytes: uint16Array, length: 32)!

If I update the array

    uint16Array[0] = 22
    uint16Array[7] = 22
    uint16Array[15] = 22

then I can update the mtlbuffer:

    mtlBuffer.contents().copyMemory(from: uint16Array, byteCount:32)

But... If I want to copy from array index != 0.... How to do?.

"pseudocode":

     mtlBuffer.contents().copyMemory(from: uint16Array[4], byteCount:22) 

(not works, of course)

I have tried some code with "withUnsafeBufferPointer", "UnsafeRawPointer(uint16Array + 4)", etc but without success.


Solution

  • Access the non-zero index of uint16Array via withUnsafePointer

    import Metal
    
    var uint16Array:[UInt16] = Array(repeating: 0, count: 16)
    let device = MTLCreateSystemDefaultDevice()!
    var mtlBuffer: MTLBuffer = device.makeBuffer(
        bytes: uint16Array, 
        length: uint16Array.count * MemoryLayout<Int16>.stride
    )!
    
    // Print the original values
    print("Original mtlBuffer:")
    printBufferValues(buffer: mtlBuffer) 
    // [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    
    uint16Array = [UInt16](0..<16)
    
    let firstIndex = 3
    let lastIndex = 10
    let range = lastIndex - firstIndex
    
    withUnsafePointer(to: &uint16Array[firstIndex]) {
        mtlBuffer
            .contents()
            .advanced(by: firstIndex * MemoryLayout<Int16>.stride)
            .copyMemory(from: $0, byteCount: range * MemoryLayout<Int16>.stride)
    }
    
    
    // Print the modified values
    print("\nModified mtlBuffer:")
    printBufferValues(buffer: mtlBuffer) 
    // [0, 0, 0, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0]
    
    // Function to print buffer values
    func printBufferValues(buffer: MTLBuffer) {
        let pointer = buffer.contents().assumingMemoryBound(to: Int16.self)
        let bufferValues = UnsafeBufferPointer(start: pointer, count: buffer.length / MemoryLayout<Int16>.stride)
        print(Array(bufferValues))
    }