Metal/Metal2 + Swift:如何将复杂的Swift结构体作为着色器参数传递?

3

我有一个Metal结构体:

struct BlurDesc {
    short fenceRows;
    short offs;
    short sampleCnt;
    float muls[64];
};

它被用作着色器参数:

kernel void hBlurCompute(
    constant BlurDesc & blurDesc [[ buffer(0) ]],
    texture2d<half, access::read> srcTexture [[ texture(0) ]],
    texture2d<half, access::write> hBlurTexture [[ texture(1) ]],
    ushort gid [[ thread_position_in_grid ]]
) {

以下为对应的Swift结构体:

struct BlurDesc {
    var fenceRows : Int16 = 0
    var offs : Int16 = -32
    var sampleCnt : Int16 = 64
    let muls = Array<Float>(repeating: (1.0/64), count: 64)
}

var blurDesc = BlurDesc()

如何将Swift结构体作为参数传递给着色器?

是否有可能从中创建具有正确字节顺序的字节缓冲区,并以某种方式将其传递给:MTLDevice.makeBuffer(bytes pointer: UnsafeRawPointer, length: Int, options: MTLResourceOptions = [])

2个回答

3

除非Swift最近在语言定义中添加了某些内容,否则Swift不能保证结构体在原始内存中的内存布局,包括字节顺序、元素顺序、任何填充,甚至是否连续(而不是分成非相邻的子块)。

因此,在纯Swift中最健壮的解决方案(而不仅仅是适用于您正在测试的当前编译器版本的解决方案)是使用(不安全的)raw(buffer)pointers,并手动将字节打包到Metal缓冲区中。

或者只需使用C结构体和C子例程进行打包(可使用桥接标头从Swift中调用所有内容)。


2
这是一个帮助打包的Github项目:https://github.com/michaeldorner/ByteBackpacker - hotpaw2
谢谢,这帮助了我继续前进。 - Endre

0

使用苹果的simd框架,轻松避免痛苦。

Swift

struct BlurDesc {
    var fenceRows : simd_short1 = 0
    var offs : simd_short1 = -32
    var sampleCnt : simd_short1 = 64
    let muls = Array<simd_float>(repeating: (1.0/64), count: 64)
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接