2 Metal数据类型

本章详细介绍了“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 支持:
fF 后缀表示指定单精度浮点字面数值(例如 0.5f 或 0.5F )。
hH 后缀表示指定半精度浮点字面数值(例如 0.5 或 0.5H )。
uU 后缀表示无符号整数字面数值。
lL 后缀表示有符号长整型字面数值。

表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 哪里 T 是有效的标量类型,并且n 是 2 ,3,4 , 代表2 ,3或4分量向量类型

表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列出了打包矢量数据类型的大小和对齐方式。


image.png

打包的矢量数据类型通常用作数据存储格式。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列出了矩阵数据类型的大小和对齐方式。


16096785306442.png

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;

您可以访问 floatnxmHalfnxm 矩阵作为n floatmn halfm输入的数组。
使用非恒定表达式访问矩阵范围之外的组件将导致不确定的行为。使用常量表达式访问位于矩阵范围之外的矩阵组件会产 生编译时错误。

你可能感兴趣的:(2 Metal数据类型)