指针(内存)在Swift中与16K对齐,用于创建金属缓冲区

时间:2014-12-08 20:02:29

标签: ios swift metal

我想创建一个带有newBufferWithBytesNoCopy功能的金属缓冲区,让CPU和GPU共享内存并实现零拷贝数据传输。

newBufferWithBytesNoCopy函数采用UnsafeMutablePointer类型指针,指针需要对齐到16K(16384)字节。

有人可以提供有关如何在Swift中创建特定大小的对齐内存的建议吗?

3 个答案:

答案 0 :(得分:6)

我相信这对你有用:

var memory:UnsafeMutablePointer<Void> = nil
var alignment:UInt = 0x4000 // 16K aligned
var size:UInt = bufferSize // bufferSize == your buffer size

posix_memalign(&memory, alignment, size)

供参考:

http://pubs.opengroup.org/onlinepubs/009695399/functions/posix_memalign.html

答案 1 :(得分:2)

Swift PageAligned Array(只是工作解决方案)

PageAlignedArray是一个项目,用于处理与Metal一起使用的内存时内存分配问题。

更多细节

4096字节对齐

我没有看到你的16k字节要求。调试器说4k。也许你可以提供参考?它应该基于系统的页面大小。

使用posix_memalign

最初的想法来自memkite我相信并且这样:

ListView

计算内存大小

您希望计算要分配的正确内存量,以使其落在字节边界上。这意味着您可能需要分配比您想要的更多的东西。在这里你传递你需要的大小和对齐,它将返回你应该分配的数量。

private func setupSharedMemoryWithSize(byteCount: Int) ->
    (pointer: UnsafeMutablePointer<Void>,
    memoryWrapper: COpaquePointer)
{
    let memoryAlignment = 0x1000 // 4096 bytes, 0x4000 would be 16k
    var memory: UnsafeMutablePointer<Void> = nil
    posix_memalign(&memory, memoryAlignment, byteSizeWithAlignment(memoryAlignment, size: byteCount))

    let memoryWrapper = COpaquePointer(memory)

    return (memory, memoryWrapper)
}

使用功能

private func byteSizeWithAlignment(alignment: Int, size: Int) -> Int
{
    return Int(ceil(Float(size) / Float(alignment))) * alignment
}

不要忘记释放你分配的记忆。

在没有posix_memalign的情况下分配共享内存。

这些天你可以通过指定.StorageModeShared来分配没有let (pointer, memoryWrapper) = setupSharedMemoryWithSize(byteCount) var unsafeVoidPointer: UnsafeMutablePointer<Void> = pointer // Assuming your underlying data is unsigned 8-bit integers. let unsafeMutablePointer = UnsafeMutablePointer<UInt8>(memoryWrapper) let unsafeMutableBufferPointer = UnsafeMutableBufferPointer(start: unsafeMutablePointer, count: byteCount) 的内存。

posix_memalign

答案 2 :(得分:0)

在经历了这个问题的一些烦恼之后,我决定继续创建一个简单的解决方案,这将使这更容易。

我创建了一个名为PageAlignedArray的Swift数组实现,它与内置Swift数组的接口和功能相匹配,但总是驻留在页面对齐的内存中,因此可以很容易地成为{ {1}}。我还添加了一种方便的方法来直接将MTLBuffer转换为Metal缓冲区。

当然,您可以继续改变您的阵列,并且您的更新将自动提供给GPU共享内存架构。但是,请记住只要数组的长度发生变化,就必须重新生成PageAlignedArray对象。

以下是一个快速代码示例:

MTLBuffer

示例使用 var alignedArray : PageAlignedContiguousArray<matrix_double4x4> = [matrixTest, matrixTest] alignedArray.append(item) alignedArray.removeFirst() // Behaves just like a built-in array, with all convenience methods // When it's time to generate a Metal buffer: let device = MTLCreateSystemDefaultDevice() let testMetalBuffer = device?.makeBufferWithPageAlignedArray(alignedArray) ,但该数组应适用于任何Swift值类型。请注意,如果使用引用类型(例如任何类型的matrix_double4x4),则数组将包含指向元素的指针,因此无法从GPU代码中使用。

请在此处抓取classhttps://github.com/eldoogy/PageAlignedArray