How to use UnsafeMutableRawPointer to fill an arra

2019-04-08 21:24发布

I have a Metal texture, I want to access its data from Swift by making it a float4 array (so that I can access each pixel 4 color components).

I discovered this method of MTLTexture :

getBytes(UnsafeMutableRawPointer, bytesPerRow: Int, bytesPerImage: Int, from: MTLRegion, mipmapLevel: Int, slice: Int)

I don't know at all how to use UnsafeMutableRawPointer, how it works, and how to get the data back into a simple Swift array.

My first attempt was to create a pointer and allocate enough space like that, but I don't even know if that's what I should do:

var pointer = UnsafeMutableRawPointer.allocate(bytes: myTextureSizeInBytes, alignedTo: 0)  

Then I have no idea at all of how to get this data back into a standard Swift array...

Thank you.

标签: swift metal
3条回答
仙女界的扛把子
2楼-- · 2019-04-08 22:04

Another option is to create an array of the appropriate size and pass the address to the underlying storage to the function:

var pixelData = Array(repeating: float4(), count: myTextureSizeInFloat4)
pixelData.withUnsafeMutableBytes {
    texture.getBytes($0.baseAddress!, ...)
}

Inside the closure, $0 is a UnsafeMutableRawBufferPointer representing the array storage as a collection of bytes, and $0.baseAddress is a pointer to the first byte.

查看更多
迷人小祖宗
3楼-- · 2019-04-08 22:19

First, let's assume you have a UnsafeRawPointer and a length:

let ptr: UnsafeRawPointer = ...
let length: Int = ...

Now you want to convert that to an [float4]. First, you can convert your UnsafeRawPointer to a typed pointer by binding it to a type:

let float4Ptr = ptr.bindMemory(to: float4.self, capacity: length)

Now you can convert that to a typed buffer pointer:

let float4Buffer = UnsafeBufferPointer(start: float4Ptr, count: length)

And since a buffer is a collection, you can initialize an array with it:

let output = Array(float4Buffer)

For much more on working with UnsafeRawPointer, see SE-0138, SE-0107, and the UnsafeRawPointer Migration Guide.

查看更多
狗以群分
4楼-- · 2019-04-08 22:24

This is a Swift 4 example of converting a literal UInt8 array to an UnsafeMutableRawPointer and back to an UInt32 array

static func unsafePointerTest() {
    //let a : [UInt8] = [0,0,0,4,0,0,0,8,0,0,0,12]
    let a : [UInt8] = [0x04, 0x00, 0x00, 0x00,
                       0x08, 0x00, 0x00, 0x00,
                       0x0C, 0x00, 0x00, 0x00] //little endian
    //0xFF, 0xF0, 0xF0, 0x12]  //317780223 = 12F0F0FF
    let b:UnsafeMutableRawPointer = UnsafeMutableRawPointer(mutating:a)
    let bTypedPtr = b.bindMemory(to: UInt32.self, capacity: a.count/4)
    let UInt32Buffer = UnsafeBufferPointer(start: bTypedPtr, count: a.count/4)
    let output = Array(UInt32Buffer)
    print(output)
}
查看更多
登录 后发表回答