本章詳細(xì)介紹了“Metal”數(shù)據(jù)類型,包括代表矢量和矩陣的類型。本章還討論了原子數(shù)據(jù)類型,緩沖區(qū),紋理,采樣器,數(shù)組 ,用戶定義的結(jié)構(gòu),類型對(duì)齊和類型轉(zhuǎn)換。
2.1標(biāo)量數(shù)據(jù)類型
Metal支持表2.1中列出的標(biāo)量類型。Metal確實(shí)不支持double, long long, unsigned long long, 和 long double類型。
表2.1 Metal常量數(shù)據(jù)類型
| 類型 | 描述 |
|---|---|
| bool | 條件數(shù)據(jù)類型的值為真否則為假 。 為true可擴(kuò)展為整數(shù)常量1,為false可擴(kuò)展為整數(shù)常量0 |
| char int8_t |
有符號(hào)二進(jìn)制補(bǔ)碼8位整數(shù)。 |
| unsigned char uchar uint8_t |
一個(gè)無符號(hào)的8位整數(shù)。 |
| short int16_t |
有符號(hào)二進(jìn)制補(bǔ)碼16位整數(shù)。 |
| unsigned short ushort uint16_t |
一個(gè)無符號(hào)的16位整數(shù)。 |
| int int32_t |
有符號(hào)二進(jìn)制補(bǔ)碼32位整數(shù)。 |
| unsigned int uint uint32_t |
一個(gè)無符號(hào)的32位整數(shù)。 |
| long int64_t All OS: Since Metal 2.2. |
有符號(hào)二進(jìn)制補(bǔ)碼64位整數(shù)。 |
| unsigned long uint64_t All OS: Since Metal 2.2. |
一個(gè)無符號(hào)的64位整數(shù)。 |
| half | 16位浮點(diǎn)數(shù)。half數(shù)據(jù)類型必須符合IEEE 754 binary16存儲(chǔ)格式。 |
| float | 32位浮點(diǎn)數(shù)。float數(shù)據(jù)類型必須符合IEEE 754 單精度存儲(chǔ)格式。 |
| size_t |
sizeof操作后的無符號(hào)整數(shù)類型。這是一個(gè)64位無符號(hào)整數(shù)。 |
| ptrdiff_t | 有符號(hào)整數(shù)類型,是兩個(gè)指針相減得到的結(jié)果。這是一個(gè)64位帶符號(hào)整數(shù)。 |
| void |
void類型包括一組空值;它是無法完成的不完整類型。 |
Metal 支持:
? f或 F 后綴表示指定單精度浮點(diǎn)字面數(shù)值(例如 0.5f 或 0.5F )。
? h 或 H 后綴表示指定半精度浮點(diǎn)字面數(shù)值(例如 0.5 或 0.5H )。
? u 或 U 后綴表示無符號(hào)整數(shù)字面數(shù)值。
? l 或 L 后綴表示有符號(hào)長(zhǎng)整型字面數(shù)值。
表2.2列出了大多數(shù)標(biāo)量數(shù)據(jù)類型的大小和對(duì)齊。
表2.2 常量數(shù)據(jù)類型的大小和對(duì)齊
| 類型 | 大小 (in bytes) |
對(duì)齊 (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向量數(shù)據(jù)類型
Metal支持由系統(tǒng)矢量數(shù)學(xué)庫實(shí)現(xiàn)的矢量數(shù)據(jù)類型的子集。Metal支持這些向量類型名稱,其中 n 是 2 ,3 ,4 ,分別表示2-、3-或4-分量向量類型:
- booln
- charn
- shortn
- intn
- longn
- ucharn
- ushortn
- uintn
- ulongn
- halfn
- floatn
Metal也支持 vec <T,n> 哪里 T 是有效的標(biāo)量類型,并且n 是 2 ,3,4 , 代表2 ,3或4分量向量類型
表2.3列出了向量數(shù)據(jù)類型的大小和對(duì)齊。
表2.3 向量數(shù)據(jù)類型的大小和對(duì)齊
| 類型 | 大小 (in bytes) |
對(duì)齊 (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 訪問向量組件
您可以使用數(shù)組索引來訪問矢量分量。數(shù)組索引 0 指向量的第一部分,索引 1個(gè) 到第二個(gè)組件,依此類推。以下示例顯示了 訪問陣列組件的各種方法:
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支持使用句點(diǎn)( . )作為選擇運(yùn)算符來訪問矢量分量,使用可能表示坐標(biāo)或顏色數(shù)據(jù)的字母:
<vector_data_type>.xyzw
<vector_data_type>.rgba
以下代碼初始化矢量測(cè)試,然后使用 .xyzw 或 .rgba選擇語法以訪問各個(gè)組件:
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
組件選擇語法允許選擇多個(gè)組件:
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);
組件選擇語法還允許組件的排列或復(fù)制:
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)
組件組表示法可以出現(xiàn)在表達(dá)式的左側(cè)(左值)。要形成左值,可以應(yīng)用旋轉(zhuǎn)。得到的左值可以是標(biāo)量類型,也可以是向量類型,具體取決于指定的組件數(shù)。每個(gè)組件必須是受支持的標(biāo)量或向量類型。向量類型的結(jié)果左值不能包含重復(fù)的組件。
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);
不允許使用以下矢量組件訪問方法,這會(huì)導(dǎo)致編譯時(shí)錯(cuò)誤:
- 訪問超出聲明向量類型會(huì)報(bào)錯(cuò)。2-component向量數(shù)據(jù)類型只能訪問 .xy 或.rg元素。3-component向量數(shù)據(jù)類型只能訪問.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.
? 在左側(cè)兩次訪問相同的組件是模棱兩可的,并且是錯(cuò)誤的:
// This is illegal because 'x' is used twice.
pos.xx = float2(3.0f, 4.0f);
? 訪問不同數(shù)量的組件是一個(gè)錯(cuò)誤:
// This is illegal due to a mismatch between float2 and float4.
pos.xy = float4(1.0f, 2.0f, 3.0f, 4.0f);
? 一次訪問中混合.rgba和.xyzw的語法錯(cuò)誤:
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;
帶有向量的指針或指向向量的引用是錯(cuò)誤的:
float4 pos = float4(1.0f, 2.0f, 3.0f, 4.0f);
my_func(&pos.xy); // This is an illegal pointer to a swizzle.
sizeof返回向量類型的大?。灰越M件的個(gè)數(shù)乘以每個(gè)組件的大小表示。
例如,
sizeof(float4) 返回 16;
sizeof(half4) 返回 8.
2.2.2 向量構(gòu)造器
您可以使用構(gòu)造函數(shù)從一組標(biāo)量或向量創(chuàng)建向量。參數(shù)簽名確定如何構(gòu)造和初始化向量。例如,如果向量?jī)H使用單個(gè)標(biāo)量參數(shù)初始化,則構(gòu)造的向量的所有分量都將設(shè)置為該標(biāo)量值。
如果從多個(gè)標(biāo)量,一個(gè)或多個(gè)向量或標(biāo)量和向量的混合物構(gòu)造向量,則向量的組成部分將從參數(shù)的組成部分中按順序構(gòu)造 。參數(shù)從左到右使用。在使用下一個(gè)參數(shù)的任何組件之前,每個(gè)參數(shù)按順序消耗其所有組件。
這是float4構(gòu)造函數(shù)的列表 :
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 構(gòu)造函數(shù)的列表:
float3(float x);
float3(float x, float y, float z);
float3(float a, float2 b);
float3(float2 a, float b);
float3(float3 x);
這是float2 構(gòu)造函數(shù)的列表:
float2(float x);
float2(float x, float y);
float2(float2 x);
以下示例說明了上述構(gòu)造函數(shù)的用法:
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);
向量構(gòu)造器初始化不足會(huì)導(dǎo)致編譯時(shí)錯(cuò)誤。
2.2.3 向量類型打包
必須將第2.2節(jié)中描述的向量數(shù)據(jù)類型與向量的大小對(duì)齊。您還可以要求將其向量數(shù)據(jù)緊密打包;例如,一個(gè)頂點(diǎn)結(jié)構(gòu)可能包含位置,法線,切線向量和紋理坐標(biāo),它們緊密包裝并作為緩沖區(qū)傳遞給頂點(diǎn)函數(shù)。
支持的打包向量類型名稱為:
? 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列出了打包矢量數(shù)據(jù)類型的大小和對(duì)齊方式。

打包的矢量數(shù)據(jù)類型通常用作數(shù)據(jù)存儲(chǔ)格式。Metal支持打包矢量數(shù)據(jù)類型的賦值,算術(shù),邏輯,關(guān)系和復(fù)制構(gòu)造函數(shù)。 Metal還支持從打包的矢量數(shù)據(jù)類型到對(duì)齊的矢量數(shù)據(jù)類型的加載和存儲(chǔ),反之亦然。
例如,
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] );
您可以使用數(shù)組索引來訪問打包矢量數(shù)據(jù)類型的組件。但是,您不能使用.xyzw或.rgba選擇語法以訪問打包矢量數(shù)據(jù)類型的組件。
例如,
packed_float4 f;
f[0] = 1.0f; // OK
f.x = 1.0f; // This is illegal and results in a compilation error.
2.3矩陣數(shù)據(jù)類型
Metal支持由system math庫實(shí)現(xiàn)的矩陣數(shù)據(jù)類型的子集。支持的矩陣類型名稱為:
? 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。一個(gè)矩陣類型floatnxm是由n個(gè)floatm向量類型組成。同樣的halfnxm是由n個(gè)halfm組成。
表2.5列出了矩陣數(shù)據(jù)類型的大小和對(duì)齊方式。

2.3.1 訪問矩陣組件
您可以使用數(shù)組下標(biāo)語法來訪問矩陣的組件。將單個(gè)下標(biāo)應(yīng)用于矩陣會(huì)將矩陣視為列向量的數(shù)組。兩個(gè)下標(biāo)選擇一列,然后選擇一行。最上面的列是列0。然后,第二個(gè)下標(biāo)對(duì)所得的矢量進(jìn)行運(yùn)算,如先前為矢量所定義的。
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輸入的數(shù)組。
使用非恒定表達(dá)式訪問矩陣范圍之外的組件將導(dǎo)致不確定的行為。使用常量表達(dá)式訪問位于矩陣范圍之外的矩陣組件會(huì)產(chǎn) 生編譯時(shí)錯(cuò)誤。