具有输入和输出一维数据缓冲区的金属计算着色器?

Metal compute shader with 1D data buffer in and out?

我知道可以将一维数组缓冲区传递给金属着色器,但是否可以将其输出到一维数组缓冲区?我不希望它写入纹理 - 我只需要一组处理过的值。

我可以使用以下代码通过着色器获取值,但它们一次只有一个值。理想情况下,我可以得到整个数组(与输入一维数组缓冲区的顺序相同)。

任何示例或指示将不胜感激!

var resultdata = [Float](repeating: 0, count: 3)
let outVectorBuffer = device.makeBuffer(bytes: &resultdata, length: MemoryLayout<float3>.size, options: [])
commandEncoder!.setBuffer(outVectorBuffer, offset: 0, index: 6)

commandBuffer!.addCompletedHandler {commandBuffer in
    let data = NSData(bytes: outVectorBuffer!.contents(), length: MemoryLayout<float3>.size)
    var out: float3 = float3(0,0,0)
    data.getBytes(&out, length: MemoryLayout<float3>.size)
    print("data: \(out)")
}

//In the Shader:
kernel void compute1d(
    ...
    device float3 &outBuffer [[buffer(6)]],
    outBuffer = float3(1.0, 2.0, 3.0);
 )

两件事:

  • 您需要创建足够大的缓冲区来容纳任意数量的 float3 元素。不过,在计算缓冲区大小时,您确实需要使用 .stride 而不是 .size。特别是,float3 具有 16 字节对齐,因此数组中的元素之间存在填充。所以,你会使用像 MemoryLayout<float3>.stride * desiredNumberOfElements.

  • 这样的东西
  • 然后,在着色器中,您需要将outBuffer的声明从引用更改为指针。所以,device float3 *outBuffer [[buffer(6)]]。然后你可以索引它来访问元素(例如 outBuffer[2] = ...;)。