In Metal在packed_float4
和float4
之间有什么区别?
答案 0 :(得分:15)
此信息来自here
float4
的{{1}}字节对齐。这意味着此类型的内存地址(例如16
)将被0x12345670
整除(也就是最后一个十六进制数字为16
)。
0
的对齐方式为packed_float4
。地址的最后一位数字为4 bytes
,0
,4
或8
创建自定义结构时,这很重要。假设你想要一个包含2个普通c
和1 float
/ float4
的结构:
packed_float4
对于struct A{
float x, y;
float4 z;
}
struct B{
float x, y;
packed_float4 z;
}
:A
的对齐方式必须为float4
,并且由于16
必须位于正常的float4
之后,所以float
和8
之间的空格为y
个字节。以下是z
在内存中的样子:
A
对于 Address | 0x200 | 0x204 | 0x208 | 0x20c | 0x210 | 0x214 | 0x218 | 0x21c |
Content | x | y | - | - | z1 | z2 | z3 | z4 |
^Has to be 16 byte aligned
:B
的对齐方式为packed_float4
,与4
相同,因此在任何情况下都可以在float
之后立即跟进:
float
如您所见, Address | 0x200 | 0x204 | 0x208 | 0x20c | 0x210 | 0x214 |
Content | x | y | z1 | z2 | z3 | z4 |
占用A
个字节,而32
仅占用B
个字节。当您拥有这些结构的数组时,24
将为每个元素占用A
个字节。因此,为了传递大量数据,后者是首选。
您需要8
的原因是因为GPU无法处理float4
字节对齐4
,您无法返回{{} 1}}在着色器中。这是因为我假设的表现。
最后一件事:当你声明一个结构的Swift版本时:
packed_float4
此结构将等于Metal中的packed_float4
和 not struct S {
let x, y: Float
let z : (Float, Float, Float, Float)
}
。元组就像B
。
所有这些也适用于其他矢量类型,例如A
,packed_floatN
等。
答案 1 :(得分:-1)
我从the documentation收集的内容:
打包的数据类型是数组,而解压缩的计数器部分是结构。
这是他们的用法:
packed_float4 packedFloat4;
packedFloat4[0] = 0.0f;
packedFloat4[1] = 1.0f;
packedFloat4[2] = 2.0f;
packedFloat4[3] = 3.0f;
packed_float4 anotherPackedFloat4 = [0.0f, 1.0f, 2.0f, 3.0f] //array initalizer
//vs.
float4 f;
f.x = 0; //equivalent to f.r = 0;
f.y = 1; //equivalent to f.g = 1;
f.z = 2; //equivalent to f.b = 2;
f.w = 3; //equivalent to f.a = 3;
float4 anotherFloat4 = float4(0.0f, 1.0f, 2.0f, 3.0f) //constructor call