我在Swift中将Uniforms结构定义为:
struct Uniforms {
var t = Float(0.0)
var arr = [0.2, 0.2, 0.2, 0.2, 0.2]
}
但是,我无法为其分配适当的MTLBuffer
,因为MemoryLayout<Uniforms>.stride
返回16
。这与Swift规范中关于数组是值类型的说法相矛盾。实际上,MemoryLayout
将其视为引用类型。
长话短说,我如何将包含数组的Uniforms结构传递给着色器(我使用常量名称空间将其传递,在那里一切都很好)。我是否需要通过一个单独的[[buffer(n)]]参数分别传递数组,我将从数组中复制内存?还有更简单的选择吗?
由于Swift无法保证结构布局,因此将这样的结构的内容直接复制到Metal缓冲区中是很危险的(同样,正如所写的那样,该数组包含Double
,但Metal目前尚不支持) )。根据实际问题的形状,可以使用几种不同的方法。
如果知道数组中元素的最大数量,则可以添加指示实际计数的struct成员,并将着色器期望的struct的最后一个元素设为固定长度的数组:
#define MAX_VALUE_COUNT 1024
struct ShaderUniforms {
float t;
uint32_t valueCount;
float values[MAX_VALUE_COUNT];
};
然后,在Swift中,您可以分配最大大小的Metal缓冲区(在这种情况下为4104字节),然后将所需的许多数组元素复制到缓冲区中(当然,在其他struct成员之前)。
或者,可以使用指针类型的单独缓冲区参数(例如constant float *values [[buffer(1)]]
)。这将使您拥有不受显式编码到着色器中的任何内容限制的值计数。