我不想使用texture1d_array
。我可以简单地传递一个float数组吗?我将在内核函数中写入它。
答案 0 :(得分:2)
为了写入内核函数内部的float数组,您需要向内核提供buffer参数。该参数的类型应为device float *
,并带有一个buffer
属性,并指定要占用的参数表槽:
kernel void my_kernel(device float *data [[buffer(0)]],
uint threadIndex [[thread_position_in_grid]])
{
data[threadIndex] = /* calculate value for this element */;
}
要在您的应用代码中创建这样的缓冲区,请请求您的Metal设备分配该缓冲区:
let buffer = device.makeBuffer(length: MemoryLayout<Float>.stride * dataCount,
options: [])!
在Mac上,您可能想使用.storageModeManaged
选项创建缓冲区,该选项不会自动将您从内核写入的值同步回CPU可读的内存。您可以使用blit编码器和synchronize(resource:)
方法从GPU内存中复制回来。在iOS上,托管缓冲区不存在,除通常的情况外,不需要同步(确保您永远不会从其他人正在写入的同一位置读取内容)。
当您准备分派计算工作时,请将缓冲区绑定为计算命令编码器的参数:
computeCommandEncoder.setBuffer(buffer, offset: 0, index: 0)
分派任何有意义的网格以完成工作。在尝试读取缓冲区内容之前,将您可能需要执行的所有其他工作(包括同步命令)编码到命令缓冲区中,提交命令缓冲区并确保已完成。
要读取缓冲区的内容,请将缓冲区的内容强制转换为适当类型的UnsafeMutableBufferPointer
,这使您可以像对待其他Sequence
一样对待缓冲区:
let data = UnsafeMutableBufferPointer<Float>(start: buffer.contents().assumingMemoryBound(to: Float.self),
count:dataCount)
// iterate over elements of data or whatever...