Ios 金属着色语言为内核图像颜色内核,如何传递一个float3数组

Ios 金属着色语言为内核图像颜色内核,如何传递一个float3数组,ios,metal,core-image,cifilter,metalkit,Ios,Metal,Core Image,Cifilter,Metalkit,我正试图通过对核心图像使用金属着色语言,从中移植一些CIFilter。 我有一个由RGBstruct数组组成的调色板,我想将它们作为参数传递给自定义CI颜色图像内核。 RGB结构转换为SIMD3数组 这是内核: float4 eight_bit(sample_t image, simd_float3 palette[], float paletteSize, destination dest) { float dist = distance(image.rgb, palette[

我正试图通过对核心图像使用金属着色语言,从中移植一些
CIFilter

我有一个由
RGB
struct数组组成的调色板,我想将它们作为参数传递给自定义CI颜色图像内核。
RGB结构转换为
SIMD3
数组

这是内核:

float4 eight_bit(sample_t image, simd_float3 palette[], float paletteSize, destination dest) {
        float dist = distance(image.rgb, palette[0]);
        float3 returnColor = palette[0];
        for (int i = 1; i < floor(paletteSize); ++i) {
            float tempDist = distance(image.rgb, palette[i]);
            if (tempDist < dist) {
                dist = tempDist;
                returnColor = palette[i];
            }
        }
        return float4(returnColor, 1);
    }
float4八位(示例图像、simd\U float3调色板[]、float调色板大小、目标目标目标){
浮动距离=距离(image.rgb,调色板[0]);
float3返回颜色=调色板[0];
对于(int i=1;i

我想知道如何将数据缓冲区传递给内核,因为将其转换为NSData似乎还不够
我看到了一些示例,但他们使用的是“完整”着色语言,这对于核心图像是不可用的,而核心图像是一种仅用于处理片段的语言

核心映像内核似乎不支持指针或数组参数类型。尽管iOS 13似乎有一些新功能。从发行说明中:

内核实例支持具有任意结构数据的参数

但是,和核心映像一样,似乎没有进一步的文档说明

但是,您仍然可以使用传递缓冲区数据的“旧方法”,将其包装在
CIImage
中,并在内核中对其进行采样。例如:

    let array: [Float] = [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0]
    let data = array.withUnsafeBufferPointer { Data(buffer: $0) }
    let dataImage = CIImage(bitmapData: data, bytesPerRow: data.count, size: CGSize(width: array.count/4, height: 1), format: .RGBAf, colorSpace: nil)

请注意,由于GPU不支持3通道图像,因此没有
CIFormat
。因此,您要么使用单通道
.Rf
并再次将内核中的值重新打包到
float3
,要么在数据中添加一些步骤,分别使用
.RGBAf
float4
(我建议这样做,因为它可以减少纹理获取)。

我做到了,事件如果答案是好的,并部署到较低的目标,结果并不完全是我所期望的。以字符串形式编写的原始内核与上面创建用作数据源的图像的方法之间的差异很大。
没有得到确切的原因,但我作为调色板来源传递的图像在大小和颜色上与创建的图像有点不同(可能是因为颜色空间)。
由于没有关于该声明的文件:

内核实例支持具有任意结构的参数 数据

我在业余时间做了很多尝试,终于做到了这一点。
首先是着色器:

   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);
    }
float4八位缓冲区(采样器图像、常量simd_float3调色板[]、浮点调色板大小、目标dest){
float4 color=image.sample(image.transform(dest.coord());
浮动距离=距离(color.rgb,调色板[0]);
float3返回颜色=调色板[0];
对于(int i=1;i
然后将调色板转换为
SIMD3

static func toSIMD3Buffer(来自调色板:[RGB])->数据{
var simd3palete=simd3palete(调色板)
let size=MemoryLayout.size
让计数=调色板。计数*大小
让palettePointer=UnsafemeutableRawPointer.allocate(
字节数:simd3palete.count*MemoryLayout.stride,
对齐:MemoryLayout.alignment)
让simd3Pointer=simd3Palette.withUnsafeMutableBufferPointer{(buffer)->UnsafeMutablePointer在
设p=palettePointer.initializeMemory(as:SIMD3.self,
发件人:buffer.baseAddress!,
计数:缓冲区。计数)
返回p
}
let data=data(bytesNoCopy:simd3Pointer,count:count*MemoryLayout.stride,deallocator:.free)
返回数据
}
我第一次尝试将SIMD3附加到数据对象,但可能由于内存对齐而无法工作。 请记住释放使用后创建的内存。

希望能帮助其他人。

谢谢你,弗兰克,我会调查的,暂时+1
    let array: [Float] = [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0]
    let data = array.withUnsafeBufferPointer { Data(buffer: $0) }
    let dataImage = CIImage(bitmapData: data, bytesPerRow: data.count, size: CGSize(width: array.count/4, height: 1), format: .RGBAf, colorSpace: nil)
   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);
    }
 static func toSIMD3Buffer(from palette: [RGB]) -> Data {
        var simd3Palette = SIMD3Palette(palette)
        let size = MemoryLayout<SIMD3<Float>>.size
        let count = palette.count * size
        let palettePointer = UnsafeMutableRawPointer.allocate(
            byteCount: simd3Palette.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<Float>>.stride, deallocator: .free)

        return data
    }