Metal Shading Language 1、数据类型 - Data Type(1)

标量数据类型 - Scalar Data Types

Metal不支持这些数据类型:double, long, unsigned long, long long, unsigned long long, long double

支持以下类型及其描述:

bool - 布尔数据类型,取值有true或false,true可以扩展为整数常量1,false可以扩展为整数常量0

har/int8_t - 有符号8-bit整型

unsigned char/uchar/uint8_t - 无符号8-bit整型

short/int16_t - 有符号16-bit整型

unsigned short/ushort/uint16_t - 无符号16-bit整型

int/int32_t - 有符号32-bit整型

unsigned int/ uint/ uint32_t - 无符号32-bit整型

half - 一个16-bit浮点数

float - 一个32-bit浮点数

size_t - 一个16-bit浮点数

ptrdiff_t - 64-bit有符号整数,表示两个指针的差

void - 该类型表示一个空的值集合

MSL支持使用下面的后缀用来表示字面量类型

f或是F用来表示单精度浮点型字面量(比如 0.5f 或是 0.5F)

h或是H用来表示半单精度浮点型字面量(比如0.5h 或是0.5H) 

u或是U用来表示无符号整形字面量。

标量数据类型的大小和对齐方式:

向量数据类型 - Vector and Matrix Data Types

Metal着色语言通过系统向量数学库支持一系列的向量和矩阵数据类型。 

Metal支持的向量类型名如下:

booln, charn, shortn, intn, ucharn, ushortn, uintn, halfn, floatn

n的取值为2,3或是4,分别表示一个2维,3维或是4维向量类型。

向量数据类型的大小和对齐方式:

如何访问向量

向量的分量可以使用数组下标进行访问存取。数组下标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 = (2.0, 4.0, 6.0, 8.0);

vB[i] = vA[i] * 2.0f 

}

Metal支持使用(.)作为选择向量分量进行访问的操作符,可以使用表示坐标分量或是颜色分量的字母来存取向量: 向量名.xyzw 或是 向量名.rgba

示例:

int4 test = int4(0, 1, 2, 3);

int a = test.x; // a=0

int b = test.y; // b=1

int c = test.z; // c=2

int d = test.w; // d=3

int e = test.r; // e=0

int f = test.g; // f=1

int g = test.b; // g=2

int h = 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);

如下的向量分量访问方法是不被允许会导致编译错误:

1、访问向量分量时,如果超过了向量声明的维度数会产生错误。一个2维向量可以通过 .xy 或 .rg 访问其分量。一 个3维的向量可以通过 .xyz 或 .rgb 访问其分量,如下面的例子所示:

float2 pos;

pos.x = 1.0f; // is legal; so is y

pos.z = 1.0f; // is illegal; so is w

float3 pos;

pos.z = 1.0f; // is legal

pos.w = 1.0f; // is illegal

2、如果作为左值,同一个分量出现多于一次是错误的,如下例所示:

// illegal - 'x' used twice

pos.xx = float2(3.0f, 4.0f);

// illegal - mismatch between float2 and float4

pos.xy = float4(1.0f, 2.0f, 3.0f, 4.0f);

3、.rbga 和 .xyzw 不能在同一次访问中混用,如下例所示:

.rbga 和 .xyzw 不能在同一次访问中混用,如下例所示:

float4 pos = float4(1.0f, 2.0f, 3.0f, 4.0f);

pos.x = 1.0f; // OK

pos.g = 2.0f; // OK

pos.xg = float2(3.0f, 4.0f); // illegal - mixed qualifiers used float3 coord = pos.ryz; // illegal - mixed qualifiers used

4、指向向量分量的指针或是引用也是不合法的。如下例所示:

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。

向量的构造

构造器可以用一组标量或是向量来构造向量。当一个向量被初始化,参数签名决定了它如何被构造。比如,如果向量的构造只使用一个标量作为参数,那么这个向量所有的分量都被设置为这个标量的值。

如过构造向量时,使用多个标量,一个或是多个向量,或是标量和向量的混合,那么向量的构造就按照参数出现的 顺序。构造时,参数从左到右被使用。每个参数所有的分量都被按顺序读取。

如下是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);

如果构造器参数不足会产生编译时错误。

紧密填充向量类型 - Packed Vector Data Types

向量数据类型都是按照其尺寸对齐的,但是会出现一些情况,开发者需要将向量数据紧密填充。比如,一个顶点数 据结构可能由位置、法向量、正切向量和纹理坐标紧密填充并且以缓存方式传递给一个顶点计算着色函数。

紧密填充向量类型支持如下这些:

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-5列举了紧密填充类型向量的对齐和尺寸。

**注:紧密填充类型的对齐方式并非全为2的n次方

**

紧密填充向量通常用于数据存储格式。载入和存储紧密填充类型向量到一个对齐向量或是反之,都有相应拷贝构造和赋值操作符支持。各算术、逻辑和关系运算符也都支持紧密填充类型向量。

Example:

device float4 *buffer;

device packed_float4 *packed_buffer;

int i;

packed_float4 f ( buffer[i] );

pack_buffer[i] = buffer[i];

// operator to convert from packed_float4 to float4.

buffer[i] = float4( packed_buffer[i] );

可以使用数组下标语法来访问紧密填充类型向量的分量,但是不支持使用.xyzw 和 .rgba语法来访问紧密填充类型向 量的分量。

Example:

packed_float4 f;

f[0] = 1.0f; // OK

f.x=1.0f; //Illegal-compilationerror

矩阵数据类型 - Matrix Data Types

Metal支持的矩阵类型名如下:

1、 halfnxm

2、floatnxm

**n和m分别表示矩阵列数和行数,n和m可以是2,3或是4。

**

一个矩阵被看做是由几个向量构成

比如一个floatnx3的矩阵由n个float3类型向量构成。类似的一个halfnx4矩阵由n个half4类型向量构成。

矩阵数据类型的大小和对齐方式:

访问矩阵分量-Accessing Matrix Data Type

floatnxm可以被当做一个有n个floatm向量构成的数组来访问,halfnxm可以被当做一个有n个halfm向量构成的数组来访问。

矩阵的各分量可以使用数组下标语法来访问。如果只使用一个数组下标访问矩阵,那么数组就是被当做列向量数组被访问,第一列的下标是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;

如果使用一个非常量的表达式作为下标访问矩阵分量越界,那么这个访问行为未知。如果使用一个常量表达式作为下标访问矩阵分量越界,那么将产生一个编译时错误。

矩阵的构造-Matrix Constructors

矩阵构造器可以使用一组标量、向量、或是矩阵来创建新矩阵。

当矩阵被初始化,构造器的参数签名决定矩阵如何 被构造。比如,如果一个矩阵只使用一个标量初始化,那么构造出来的矩阵的对角线上的分量被赋值成这个标量的 值,其他的矩阵分量被设置为0.0,如下例所示:

float4x4(fval);

fval是一个标量浮点数,那么构造出来的矩阵的各分量如下所示:

fval 0.0 0.0 0.0 

0.0 fval 0.0 0.0 

0.0 0.0 fval 0.0 

0.0 0.0 0.0 fval

一个矩阵也可以由另一个有同样尺寸(也就是有相同的行数和列数)的矩阵构造,比如:

float3x4(float3x4);

float3x4(half3x4);

如上从另一个矩阵构造新矩阵的情况下,矩阵的各分量将以列主序来构造。作为参数矩阵必须要有足够的分量来构 造新矩阵的每一个分量,􏰁供了过多的分量(参数矩阵的尺寸比构造矩阵大)会导致编译错误。如果参数矩阵的分 量个数不足用来初始化(参数矩阵的尺寸比构造矩阵小)也会导致编译错误。

一个T类型的n列m行的矩阵可以被n个T类型的m维向量初始化。下面的例子都是合法的初始化:

float2x2(float2, float2);

float3x3(float3, float3, float3);

float3x2(float2, float2, float2);

如下面的例子中的矩阵的构造是不支持的。一个矩阵不支持从多个标量构造,也不支持标量和向量混合构造。

// both cases below are not supported

float2x2(float a00, float a01, float a10, float a11);

float2x3(float2 a, float b, float2 c, float d);

##Alignment of Data Types - 数据对齐

数据对齐 - Alignment of Data Types

对齐说明符:alignas

可以使用对齐说明符(alignas)指定类型或对象的对齐要求。还可以将对齐说明符(alignas)应用于结构或类的变量或数据成员的声明。还可以将其应用于结构、类或枚举类型的声明。

Metal编译器负责根据数据类型的需要将数据项对齐到适当的对齐位置。对于声明为数据类型指针的图形或并行计算函数的参数,Metal编译器假设指针或引用的对象总是按照数据类型的要求进行适当对齐。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342