打包数据类型与普通数据类型之间的区别

Difference between packed vs normal data type

在 Metal 中,packed_float4float4 有什么区别?

此信息来自here

float4 对齐 16 字节。这意味着这种类型的内存地址(例如0x12345670)将被16整除(也就是最后一个十六进制数字是0)。

另一方面,

packed_float4 的对齐方式为 4 bytes。地址的最后一位将是 048c

这在您创建自定义结构时很重要。假设您想要一个包含 2 个普通 float 和 1 个 float4/packed_float4:

的结构
struct A{
    float x, y;
    float4 z;
}

struct B{
    float x, y;
    packed_float4 z;
}

对于Afloat4的对齐必须是16并且因为float4必须在正常的float之后,所以有将是 yz 之间 8 字节的空 space。这是 A 在内存中的样子:

 Address | 0x200 | 0x204 | 0x208 | 0x20c | 0x210 | 0x214 | 0x218 | 0x21c |
 Content |   x   |   y   |   -   |   -   |   z1  |   z2  |   z3  |   z4  |
                                             ^Has to be 16 byte aligned

对于Bpacked_float4的对齐方式是4,与float相同,因此它可以紧跟在任何float之后案例:

 Address | 0x200 | 0x204 | 0x208 | 0x20c | 0x210 | 0x214 |
 Content |   x   |   y   |   z1  |   z2  |   z3  |   z4  |

如您所见,A 占用 32 字节,而 B 仅使用 24 字节。当您拥有这些结构的数组时,A 将为每个元素占用 8 个字节。所以对于传递大量数据,后者是首选。

你需要 float4 的原因是因为 GPU 无法处理 4 字节对齐的 packed_float4s,你将无法 return packed_float4 在着色器中。这是因为我假设的性能。

最后一件事:当您声明结构的 Swift 版本时:

struct S {
    let x, y: Float
    let z : (Float, Float, Float, Float)
}

这个结构在 Metal 中等于 B A。元组就像 packed_floatN.

所有这些也适用于其他矢量类型,例如 packed_float3packed_short2