Search code examples
swiftmetalswift5

Problem accessing MTLBuffer via typed UnsafeMutualPointer


I have a function that is passed an optional MTLBuffer. My goal is to iteratively change values in that buffer using an index into a Typed pointer to the same buffer. However, when I run the code, I'm getting an error "Thread 1: EXC_BAD_ACCESS (code=2, address=0x1044f1000)".

Am I converting to the Typed UnsafeMutablePointer correctly?

Would it be better to covert to a Typed UnsafeMutableBufferPointer? If so, how would I convert from the MTLBuffer to Typed UnsafeMutableBufferPointer?

Any idea why I'm getting this error?

Note: I've removed most guard checks to keep this simple. I've confirmed the MTLDevice (via device), bufferA allocation, dataPtr and floatPtr are all non-nil. floatPtr and dataPtr do point to the same memory address.

This is how I allocate the buffer:

bufferSize = 16384
bufferA = device?.makeBuffer(length: bufferSize, options: MTLResourceOptions.storageModeShared)`

Here's my code operating on the buffer:

guard let dataPtr = bufferA?.contents() else {
  fatalError("error retrieving buffer?.contents() in generateRandomFloatData()")
}

let floatPtr = dataPtr.bindMemory(to: Float.self, capacity: bufferA!.length)

for index in 0...bufferSize - 1 {
  floatPtr[index] = 1.0 // Float.random(in: 0...Float.greatestFiniteMagnitude)
}

Thank you!


Solution

  • Am I converting to the Typed UnsafeMutablePointer correctly?

    NO.

    When you call makeBuffer(length:options:) you pass the length in bytes. But, a Float occupies 4 bytes in memory.

    So, you may need to modify some parts related to number of elements:

    let floatPtr = dataPtr.bindMemory(to: Float.self, capacity: bufferA!.length/MemoryLayout<Float>.stride)
    
    for index in 0..<bufferSize/MemoryLayout<Float>.stride {
      floatPtr[index] = 1.0 // Float.random(in: 0...Float.greatestFiniteMagnitude)
    }