自定义CIFilter时如何将Swift数组传递至Metal着色语言(MSL)参数
Hey there! I see you're running into a crash when trying to pass a pointer from Swift to your Metal CIFilter kernel. Let's break down why this is happening and go over some reliable alternatives to get your parameter passing working correctly.
Why Your Original Code Crashes
Core Image's kernel argument system doesn't support passing raw Swift/Metal pointers directly. It relies on a predefined set of compatible types (like CIImage, CIVector, NSNumber, or arrays of these types). When you pass an UnsafeMutablePointer, you bypass Core Image's memory management and type validation, leading to unreadable memory and silent crashes.
Solution 1: Pass a [CIVector] Array Directly (Recommended)
Core Image natively supports passing arrays of CIVector to Metal kernels. This is the cleanest approach for your use case:
Updated Swift Code
let 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) ] // Pass the array directly as an argument return self.kernel.apply(extent: inputExtent, roiCallback: roiCallback, arguments: [inputImage, reddish, greenish, blueish, dummyColors])
Updated Metal Code
Use the constant modifier for the array (since it's read-only input) and access elements via index:
extern "C" { namespace coreimage { float4 dyeInThree(sampler src, float3 redVector, float3 greenVector, float3 blueVector, constant float3 a[]) { // Access array elements like a regular array float3 firstColor = a[0]; float3 secondColor = a[1]; float3 thirdColor = a[2]; // Your color processing logic here float4 sourceColor = src.sample(src.coord()); return float4(sourceColor.rgb * firstColor, sourceColor.a); } } }
Solution 2: Pack Values into a Single CIVector (For Fixed-Length Small Arrays)
If your array has a fixed small length (like 3 elements here), you can pack all values into a single extended CIVector and split it in Metal:
Updated Swift Code
// Pack 3 float3 values into one CIVector (9 total components) let packedColors = CIVector( x: 0.9, y: 0.3, z: 0.4, w: 0.2, x2: 0.5, y2: 0.9, z2: 0.5, w2: 0.9, z3: 0.3 ) return self.kernel.apply(extent: inputExtent, roiCallback: roiCallback, arguments: [inputImage, reddish, greenish, blueish, packedColors])
Updated Metal Code
extern "C" { namespace coreimage { float4 dyeInThree(sampler src, float3 redVector, float3 greenVector, float3 blueVector, float9 packedColors) { // Split the packed vector into individual float3 values float3 firstColor = packedColors.xyz; float3 secondColor = packedColors.uvw; float3 thirdColor = float3(packedColors[6], packedColors[7], packedColors[8]); // Your color processing logic here float4 sourceColor = src.sample(src.coord()); return float4(sourceColor.rgb * firstColor, sourceColor.a); } } }
内容的提问来源于stack exchange,提问作者Aryaputra Sudarman

