Metal CIKernel instances support arguments with arbitrarily structured data

In the last few weeks in my spare time I've tried to convert a `CIFilter` with a custom color kernel from a string to a metal written kernel.

The purpose of this filter is to pixellate an image and then apply a custom palette of colors. Pixellation is made by CI Pixellate and then I apply this shader.

float4 eight_bit_buffer(sampler image, constant simd_float3 palette[], float paletteSize, destination dest) {
        float4 color = image.sample(image.transform(dest.coord()));

        float dist = distance(color.rgb, palette[0]);
        float3 returnColor = palette[0];
        for (int i = 1; i < floor(paletteSize); ++i) {
            float tempDist = distance(color.rgb, palette[i]);
            if (tempDist < dist) {
                dist = tempDist;
                returnColor = palette[i];
            }
        }
        return float4(returnColor, 1);
    }

The first argument is the image the second is an array of float3 that makes the palette of color.

Since iOS13 there was written this in the change note:

Metal CIKernel instances support arguments with arbitrarily structured data but I couldn't find any reference in the the documentation or videos.

I've tried to do my myself basically trying to create an Data object and pass it to the shader function. At a first try I simply created a Data object and appended SIM3<Double> to it, but it wasn't working so I tought it could be an issue with memory allignment and I came up with this, but it won't work either.

func toSIMD3() -> SIMD3<Float> {
         return [Float(r) / 255.0, Float(g) / 255.0, Float(b) / 255.0]
     }
static func SIMD3Palette(_ palette: [RGB]) -> [SIMD3<Float>] {
        return palette.map{ $0.toSIMD3() }
    }

static func toSIMD3Buffer(from palette: [RGB]) -> Data {
        var simd3Palette = SIMD3Palette(palette)
        let size = MemoryLayout<SIMD3<Float>>.size
        let count = palette.count
        let palettePointer = UnsafeMutableRawPointer.allocate(
            byteCount: count * MemoryLayout<SIMD3<Float>>.stride,
            alignment: MemoryLayout<SIMD3<Float>>.alignment)
        let simd3Pointer = simd3Palette.withUnsafeMutableBufferPointer { (buffer) -> UnsafeMutablePointer<SIMD3<Float>> in
            let p = palettePointer.initializeMemory(as: SIMD3<Float>.self,
            from: buffer.baseAddress!,
            count: buffer.count)
            return p
        }
        let data = Data(bytesNoCopy: simd3Pointer, count: count * MemoryLayout<simd3>.stride, deallocator: .free)
       
        return data
    }

Have anyone discovered how to pass arbitrarily structured data to a CIKernel?

Best,

Andrea