Swift 将结构中的数组传递给金属着色器

Swift 将结构中的数组传递给金属着色器,swift,metal,Swift,Metal,我的制服结构在Swift中定义为: struct Uniforms { var t = Float(0.0) var arr = [0.2, 0.2, 0.2, 0.2, 0.2] } 但是,我无法为它分配适当的MTLBuffer,因为MemoryLayout.stride返回16。这与Swift规范中关于数组是值类型的陈述相矛盾。实际上,MemoryLayout将其视为引用类型 长话短说,如何将包含数组的统一结构传递给着色器(我使用常量名称空间来传递它,这一切都很好)。我是否

我的制服结构在Swift中定义为:

struct Uniforms {
    var t = Float(0.0)
    var arr = [0.2, 0.2, 0.2, 0.2, 0.2]
}
但是,我无法为它分配适当的
MTLBuffer
,因为
MemoryLayout.stride
返回
16
。这与Swift规范中关于数组是值类型的陈述相矛盾。实际上,
MemoryLayout
将其视为引用类型


长话短说,如何将包含数组的统一结构传递给着色器(我使用常量名称空间来传递它,这一切都很好)。我是否需要通过一个单独的[[buffer(n)]]参数单独传递数组,我将把数组中的内存复制到这个参数中?有更简单的选择吗?

由于Swift对结构布局没有任何保证,因此直接将此类结构的内容复制到金属缓冲区是很危险的(同样,如前所述,数组包含
Double
s,金属目前无论如何都不支持)。根据实际问题的形状,有几种不同的方法可以起作用

如果知道数组中的最大元素数,可以添加一个表示实际计数的结构成员,并将着色器所需的结构的最后一个元素设置为固定长度数组:

#define MAX_VALUE_COUNT 1024
struct ShaderUniforms {
    float t;
    uint32_t valueCount;
    float values[MAX_VALUE_COUNT];
};
然后,在Swift中,您可以分配一个最大大小的金属缓冲区(在这种人为的情况下是4104字节),并将所需的任意多个数组元素复制到缓冲区中(当然,前面是其他结构成员)


或者,可以使用指针类型的单独缓冲区参数(例如,
常量浮点*值[[buffer(1)]]
)。这将允许您拥有一个不受显式编码到着色器中的任何内容限制的值计数。

这很悲哀(关于Swift)。关于您关于“常量浮点*值[[buffer(1)]]”的评论-这不应该在着色器中引用吗?谢谢根据这个问题/答案,Swift目前似乎可以为结构制作正确的布局:-这是否意味着我唯一的问题是在Swift中,数组实际上不是一种值类型-我是否可以以某种方式在Swift中制作存储在结构中的所有数组值?如果没有数组,我认为现在可以使用structs。如果只是引用float,就不能索引到它,我不知道如何将该类型作为指针的引用来编写。可以想象,您可以将其键入为对固定长度数组的引用,甚至可能是对可变长度数组的引用,尽管其语法是粗略的。在我看来,仅仅把它作为一个指针来写是相当干净的。我不知道为什么你会选择依赖斯威夫特的未指明的行为。虽然顺序是确定的,但我在规范中没有发现Swift不会在数组之前插入任意填充,也没有说数组的第一个元素位于数组本身的地址。如果你想得到布局的保证,用(Objective-)C写下类型,在这里你可以控制布局和对齐,并把它连接起来。也许是“常量数组和值”?