如何将数组从 Swift 传递到 MSL 参数 (C++)

How do I pass an array from Swift to MSL parameter (C++)

我想制作这个自定义 CIFilter。

var dummyColors = [
        CIVector(x: 0.9, y: 0.3, z: 0.4),
        CIVector(x: 0.2, y: 0.5, z: 0.9),
        CIVector(x: 0.5, y: 0.9, z: 0.3)
    ]
    
    var normal = dummyColors.withUnsafeMutableBufferPointer { (buffer) -> UnsafeMutablePointer<CIVector> in
        var p = buffer.baseAddress
        print(p)
        return p!
    }

    //this is  parameter and how to pass bvalue to the kernel function
    return self.kernel.apply(extent: inputExtent,
                             roiCallback: roiCallback,
                             arguments: [inputImage, reddish, greenish, blueish, normal])  // (5)

这是我尝试用指针传递参数。然而,代码似乎不喜欢它,它只是在没有打印错误的情况下崩溃了。

这里是 metal 函数

extern "C" { namespace coreimage {               // (3)

//this is how you define parameter on the top of the function
float4 dyeInThree(sampler src,
                  float3 redVector,
                  float3 greenVector,
                  float3 blueVector,
                  device float3 *a) 

还有其他方法可以将参数传递给我的金属代码吗?

您使用 withUnsafeMutableBufferPointer 获得的指针仅在您传递给函数的闭包内有效。您需要为参数分配一个更“永久”的存储空间。

您可以先使用 UnsafeMutableBufferPointer.allocate 之类的方法来分配内存,但您必须在某处跟踪内存,因为在使用完后需要 deallocate 它。

我对你的用例采纳了这个答案:

这是我用于内存分配的内容:

var dummyColors = [
            SIMD3<Float>(x: 1.1, y: 0.1, z: 0.1), 
            SIMD3<Float>(x: 0.1, y: 1.1, z: 0.1),
            SIMD3<Float>(x: 0.1, y: 0.1, z: 1.1)
        ]

let pointer = UnsafeMutableRawPointer.allocate(
            byteCount: 3 * MemoryLayout<SIMD3<Float>>.stride,
            alignment: MemoryLayout<SIMD3<Float>>.alignment)
let sPointer = dummyColors.withUnsafeMutableBufferPointer { (buffer) -> UnsafeMutablePointer<SIMD3<Float>> in
            let p = pointer.initializeMemory(as: SIMD3<Float>.self,
            from: buffer.baseAddress!,
            count: buffer.count)
            return p
        }
let data = Data(bytesNoCopy: sPointer, count: 3 * MemoryLayout<SIMD3<Float>>.stride, deallocator: .free)

在将缓冲区传递给内核之前,您需要将其转换为 NSData。这是 Metal 函数声明:

extern "C" { namespace coreimage {               // (3)
    float4 dyeInThree(sampler src,
                      float3 redVector,
                      float3 greenVector,
                      float3 blueVector,
                      constant float3 a[]) {

请注意 'constant' 命名空间而不是 'device'。否则 Metal 编译器会在运行时报错。