本章详细介绍了“Metal”数据类型,包括代表矢量和矩阵的类型。本章还讨论了原子数据类型,缓冲区,纹理,采样器,数组 ,用户定义的结构,类型对齐和类型转换。
2.1标量数据类型
Metal支持表2.1中列出的标量类型。Metal确实不支持double
, long long
, unsigned long long
, 和 long double
类型。
表2.1 Metal常量数据类型
类型 | 描述 |
---|---|
bool | 条件数据类型的值为真否则为假 。 为true可扩展为整数常量1,为false可扩展为整数常量0 |
char int8_t |
有符号二进制补码8位整数。 |
unsigned char uchar uint8_t |
一个无符号的8位整数。 |
short int16_t |
有符号二进制补码16位整数。 |
unsigned short ushort uint16_t |
一个无符号的16位整数。 |
int int32_t |
有符号二进制补码32位整数。 |
unsigned int uint uint32_t |
一个无符号的32位整数。 |
long int64_t All OS: Since Metal 2.2. |
有符号二进制补码64位整数。 |
unsigned long uint64_t All OS: Since Metal 2.2. |
一个无符号的64位整数。 |
half | 16位浮点数。half 数据类型必须符合IEEE 754 binary16存储格式。 |
float | 32位浮点数。float 数据类型必须符合IEEE 754 单精度存储格式。 |
size_t | sizeof 操作后的无符号整数类型。这是一个64位无符号整数。 |
ptrdiff_t | 有符号整数类型,是两个指针相减得到的结果。这是一个64位带符号整数。 |
void | void 类型包括一组空值;它是无法完成的不完整类型。 |
Metal 支持:
• f
或 F
后缀表示指定单精度浮点字面数值(例如 0.5f 或 0.5F )。
• h
或 H
后缀表示指定半精度浮点字面数值(例如 0.5 或 0.5H )。
• u
或 U
后缀表示无符号整数字面数值。
• l
或 L
后缀表示有符号长整型字面数值。
表2.2列出了大多数标量数据类型的大小和对齐。
表2.2 常量数据类型的大小和对齐
类型 | 大小 (in bytes) |
对齐 (in bytes) |
---|---|---|
bool | 1 | 1 |
char int8_t unsigned char uchar uint8_t |
1 | 1 |
short int16_t unsigned short ushort uint16_t |
2 | 2 |
int int32_t unsigned int uint uint32_t |
4 | 4 |
long int64_t unsigned long uint64_t |
8 | 8 |
size_t | 8 | 8 |
half | 2 | 2 |
float | 4 | 4 |
2.2向量数据类型
Metal支持由系统矢量数学库实现的矢量数据类型的子集。Metal支持这些向量类型名称,其中 n 是 2 ,3 ,4 ,分别表示2-、3-或4-分量向量类型:
- booln
- charn
- shortn
- intn
- longn
- ucharn
- ushortn
- uintn
- ulongn
- halfn
- floatn
Metal也支持 vec
表2.3列出了向量数据类型的大小和对齐。
表2.3 向量数据类型的大小和对齐
类型 | 大小 (in bytes) |
对齐 (in bytes) |
---|---|---|
bool2 | 2 | 2 |
bool3 | 4 | 4 |
bool4 | 4 | 4 |
char2 uchar2 |
2 | 2 |
char3 uchar3 |
4 | 4 |
char4 uchar4 |
4 | 4 |
short2 ushort2 |
4 | 4 |
short3 ushort3 |
8 | 8 |
short4 ushort4 |
8 | 8 |
int2 uint2 |
8 | 8 |
int3 uint3 |
16 | 16 |
int4 uint4 |
16 | 16 |
long2 ulong2 |
16 | 16 |
long3 ulong3 |
32 | 32 |
long4 ulong4 |
32 | 32 |
half2 | 4 | 4 |
half3 | 8 | 8 |
half4 | 8 | 8 |
float2 | 8 | 8 |
float3 | 16 | 16 |
float4 | 16 | 16 |
2.2.1 访问向量组件
您可以使用数组索引来访问矢量分量。数组索引 0 指向量的第一部分,索引 1个 到第二个组件,依此类推。以下示例显示了 访问阵列组件的各种方法:
pos = float4(1.0f, 2.0f, 3.0f, 4.0f);
float x = pos[0];// x = 1.0
float z = pos[2];// z = 3.0
float4 vA = float4(1.0f, 2.0f, 3.0f, 4.0f);
float4 vB;
for (int i=0; i<4; i++)
vB[i] = vA[i] * 2.0f // vB = (2.0, 4.0, 6.0, 8.0);
Metal支持使用句点( . )作为选择运算符来访问矢量分量,使用可能表示坐标或颜色数据的字母:
.xyzw
.rgba
以下代码初始化矢量测试,然后使用 .xyzw 或 .rgba选择语法以访问各个组件:
int4 test = int4(0, 1, 2, 3);
inta=test.x; // a=0
intb=test.y; // b=1
intc=test.z; // c=2
intd=test.w; // d=3
inte=test.r; // e=0
intf=test.g; // f=1
intg=test.b; // g=2
inth=test.a; // h=3
组件选择语法允许选择多个组件:
float4 c;
c.xyzw = float4(1.0f, 2.0f, 3.0f, 4.0f);
c.z = 1.0f;
c.xy = float2(3.0f, 4.0f);
c.xyz = float3(3.0f, 4.0f, 5.0f);
组件选择语法还允许组件的排列或复制:
float4 pos = float4(1.0f, 2.0f, 3.0f, 4.0f);
float4 swiz = pos.wzyx; // swiz = (4.0f, 3.0f, 2.0f, 1.0f)
float4 dup = pos.xxyy; // dup = (1.0f, 1.0f, 2.0f, 2.0f)
组件组表示法可以出现在表达式的左侧(左值)。要形成左值,可以应用旋转。得到的左值可以是标量类型,也可以是向量类型,具体取决于指定的组件数。每个组件必须是受支持的标量或向量类型。向量类型的结果左值不能包含重复的组件。
float4 pos = float4(1.0f, 2.0f, 3.0f, 4.0f);
// pos = (5.0, 2.0, 3.0, 6.0)
pos.xw = float2(5.0f, 6.0f);
// pos = (8.0, 2.0, 3.0, 7.0)
pos.wx = float2(7.0f, 8.0f);
// pos = (3.0, 5.0, 9.0, 7.0)
pos.xyz = float3(3.0f, 5.0f, 9.0f);
不允许使用以下矢量组件访问方法,这会导致编译时错误:
- 访问超出声明向量类型会报错。2-component向量数据类型只能访问 .xy 或.rg元素。3-component向量数据类型只能访问.xyz或.rgb。
float2 pos; // This is a 2-component vector.
pos.x = 1.0f; // x is legal and so is y.
pos.z = 1.0f; // z is illegal and so is w. z is the 3rd component.
float3 pos; // This is a 3-component vector.
pos.z = 1.0f; // z is legal for a 3-component vector.
pos.w = 1.0f; // This is illegal. w is the 4th component.
• 在左侧两次访问相同的组件是模棱两可的,并且是错误的:
// This is illegal because 'x' is used twice.
pos.xx = float2(3.0f, 4.0f);
• 访问不同数量的组件是一个错误:
// This is illegal due to a mismatch between float2 and float4.
pos.xy = float4(1.0f, 2.0f, 3.0f, 4.0f);
• 一次访问中混合.rgba和.xyzw的语法错误:
float4 pos = float4(1.0f, 2.0f, 3.0f, 4.0f);
pos.x = 1.0f; // OK
pos.g = 2.0f; // OK
// These are illegal due to mixing rgba and xyzw attributes.
pos.xg = float2(3.0f, 4.0f);
float3 coord = pos.ryz;
带有向量的指针或指向向量的引用是错误的:
float4 pos = float4(1.0f, 2.0f, 3.0f, 4.0f);
my_func(&pos.xy); // This is an illegal pointer to a swizzle.
sizeof
返回向量类型的大小;以组件的个数乘以每个组件的大小表示。
例如,
sizeof(float4) 返回 16;
sizeof(half4) 返回 8.
2.2.2 向量构造器
您可以使用构造函数从一组标量或向量创建向量。参数签名确定如何构造和初始化向量。例如,如果向量仅使用单个标量参数初始化,则构造的向量的所有分量都将设置为该标量值。
如果从多个标量,一个或多个向量或标量和向量的混合物构造向量,则向量的组成部分将从参数的组成部分中按顺序构造 。参数从左到右使用。在使用下一个参数的任何组件之前,每个参数按顺序消耗其所有组件。
这是float4
构造函数的列表 :
float4(float x);
float4(float x, float y, float z, float w);
float4(float2 a, float2 b);
float4(float2 a, float b, float c);
float4(float a, float b, float2 c);
float4(float a, float2 b, float c);
float4(float3 a, float b);
float4(float a, float3 b);
float4(float4 x);
这是float3
构造函数的列表:
float3(float x);
float3(float x, float y, float z);
float3(float a, float2 b);
float3(float2 a, float b);
float3(float3 x);
这是float2
构造函数的列表:
float2(float x);
float2(float x, float y);
float2(float2 x);
以下示例说明了上述构造函数的用法:
float x = 1.0f, y = 2.0f, z = 3.0f, w = 4.0f;
float4 a = float4(0.0f);
float4 b = float4(x, y, z, w);
float2 c = float2(5.0f, 6.0f);
float2 a = float2(x, y);
float2 b = float2(z, w);
float4 x = float4(a.xy, b.xy);
向量构造器初始化不足会导致编译时错误。
2.2.3 向量类型打包
必须将第2.2节中描述的向量数据类型与向量的大小对齐。您还可以要求将其向量数据紧密打包;例如,一个顶点结构可能包含位置,法线,切线向量和纹理坐标,它们紧密包装并作为缓冲区传递给顶点函数。
支持的打包向量类型名称为:
• packed_charn
• packed_shortn
• packed_intn
• packed_ucharn
• packed_ushortn
• packed_uintn
• packed_halfn
• packed_floatn
n指的是2、3或4,分别代表2、3或4分量向量类型。(packed_booln
向量类型名称保留。)
表2.4列出了打包矢量数据类型的大小和对齐方式。
打包的矢量数据类型通常用作数据存储格式。Metal支持打包矢量数据类型的赋值,算术,逻辑,关系和复制构造函数。 Metal还支持从打包的矢量数据类型到对齐的矢量数据类型的加载和存储,反之亦然。
例如,
device float4 *buffer;
device packed_float4 *packed_buffer;
int i;
packed_float4 f ( buffer[i] );
pack_buffer[i] = buffer[i]; // An operator used to convert from packed_float4 to float4.
buffer[i] = float4( packed_buffer[i] );
您可以使用数组索引来访问打包矢量数据类型的组件。但是,您不能使用.xyzw
或.rgba
选择语法以访问打包矢量数据类型的组件。
例如,
packed_float4 f;
f[0] = 1.0f; // OK
f.x = 1.0f; // This is illegal and results in a compilation error.
2.3矩阵数据类型
Metal支持由system math库实现的矩阵数据类型的子集。支持的矩阵类型名称为:
• halfnxm
• floatnxm
Where n and m are numbers of columns and rows. n and m must be 2, 3, or 4
n和m指的是列和行,必须是2、3、4。一个矩阵类型floatnxm
是由n个floatm
向量类型组成。同样的halfnxm
是由n个halfm
组成。
表2.5列出了矩阵数据类型的大小和对齐方式。
2.3.1 访问矩阵组件
您可以使用数组下标语法来访问矩阵的组件。将单个下标应用于矩阵会将矩阵视为列向量的数组。两个下标选择一列,然后选择一行。最上面的列是列0。然后,第二个下标对所得的矢量进行运算,如先前为矢量所定义的。
float4x4 m;
// This sets the 2nd column to all 2.0.
m[1] = float4(2.0f);
// This sets the 1st element of the 1st column to 1.0.
m[0][0] = 1.0f;
// This sets the 4th element of the 3rd column to 3.0.
m[2][3] = 3.0f;
您可以访问 floatnxm
和 Halfnxm
矩阵作为n floatm
或 n halfm
输入的数组。
使用非恒定表达式访问矩阵范围之外的组件将导致不确定的行为。使用常量表达式访问位于矩阵范围之外的矩阵组件会产 生编译时错误。