如何将浮点数组传递给金属内核函数?

时间:2019-03-19 23:51:21

标签: metal

我不想使用texture1d_array。我可以简单地传递一个float数组吗?我将在内核函数中写入它。

1 个答案:

答案 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...