注:本文旨在记录笔者的学习过程,仅代表笔者个人的理解,如果有表述不准确的地方,欢迎各位指正!因为涉及到的概念来源自网络,所以如有侵权,也望告知!
前言
本文的主要目的是带大家了解Metal程序中的Metal着⾊语⾔的语法规则。
正文
一、Metal 着色语⾔
- Lambda表达式
- 递归函数调⽤
- 动态转换操作符
- 类型识别
- 对象创建(
new)和释放(delloc)操作符 - 操作符
noexcept goto跳转- 虚函数修饰符
- 派⽣类
- 异常处理
二、Metal 语法介绍
1、Metal 数据类型--标量数据类型
- bool 布尔类型, true/false
- char 有符号8位整数;
- unsigned char /uchar ⽆符号8-bit 整数;
- short 有符号16-bit整数;
- unsigned short / ushort ⽆符号32-bit 整数;
- half 16位bit 浮点数;
- float 32bit 浮点数;
- size_t 64 ⽆符号整数;
- void 该类型表示⼀个空的值集合;
注:Metal ⽀持后缀表示字⾯量类型, 例如 0.5F, 0.5f; 0.5h, 0.5H;
2、Metal 向量和矩阵数据类型
- booln
- charn
- shortn
- intn
- ucharn
- ushortn
- uintn
- halfn
- floatn
矩阵⽀持如下类型:
- halfnxm
- floatnxm
注:nxm分别指的是矩阵的⾏数和列数
3、纹理Textures 类型
其中access枚举值: 定义了访问权利;
enum class access {sample ,read ,write};
- sample : 纹理对象可以被采样. 采样⼀维这是使⽤或不使⽤采样器从纹理中读取数据;
- read : 不使⽤采样器, ⼀个图形渲染函数或者⼀个并⾏计算函数可以读取纹理对象;
- write: ⼀个图形渲染函数或者⼀个并⾏计算函数可以向纹理对象写⼊数据;
texture1d<T, access a = access::sample>
texture2d<T, access a = access::sample>
T : 数据类型 设定了从纹理中读取或是向纹理中写⼊时的颜⾊类型. T可以是half, float, short, int 等;
4、采样器类型 Samplers
Metal支持的采样器参数:
- enum class coord { normalized, pixel };
从纹理中采样时,纹理坐标是否需要归⼀化;
- enum class filter { nearest, linear };
纹理采样过滤⽅式, 放⼤/缩⼩过滤模式;
- enum class min_filter { nearest, linear };
设置纹理采样的缩⼩过滤模式;
- enum class mag_filter { nearest, linear };
设置纹理采样的放⼤过滤模式;
- enum class s_address { clamp_to_zero, clamp_to_edge, repeat, mirrored_repeat };
- enum class t_address { clamp_to_zero, clamp_to_edge, repeat, mirrored_repeat };
- enum class r_address { clamp_to_zero, clamp_to_edge, repeat, mirrored_repeat };
设置纹理s,t,r坐标的寻址模式;
- enum class address { clamp_to_zero, clamp_to_edge, repeat, mirrored_repeat };
设置所有的纹理坐标的寻址模式;
- enum class mip_filter { none, nearest, linear };
设置纹理采样的mipMap过滤模式, 如果是none,那么只有⼀层纹理⽣效;
注:在Metal 程序中初始化的采样器必须使⽤ constexpr 修饰符声明
5、函数修饰符
- kernel , 表示该函数是⼀个数据并⾏计算着⾊函数. 它可以被分配在⼀维/⼆维/三维线程组中去执⾏;
- vertex , 表示该函数是⼀个顶点着⾊函数 , 它将为顶点数据流中的每个顶点数据执⾏⼀次然后为每个顶点⽣成数据输出到绘制管线;
- fragment , 表示该函数是⼀个⽚元着⾊函数, 它将为⽚元数据流中的每个⽚元 和其关联执⾏⼀次然后将每个⽚元⽣成的颜⾊数据输出到绘制管线中;
- 使⽤kernel 修饰的函数. 其返回值类型必须是void 类型;
- 只有图形着⾊函数才可以被 vertex 和 fragment 修饰. 对于图形着⾊函数, 返回值类型可以辨认出它是为顶点做计算还是为每像素做计算. 图形着⾊函数的返回值可以为 void , 但是这也就意味着该函数不产⽣数据输出到绘制管线; 这是⼀个⽆意义的动作;
- ⼀个被函数修饰符修饰的函数不能在调⽤其他也被函数修饰符修饰的函数; 这样会导致编译失败;
6、⽤于变量或者参数的地址空间修饰符
- device
- threadgrounp
- constant
- thread
a、Device Address Space(设备地址空间)
b、threadgrounp Address Space(线程组地址空间)
c、constant Address Space(常量地址空间)
d、thread Address Space(线程地址空间)
7、函数参数与变量
- device buffer- 设备缓存, ⼀个指向设备地址空间的任意数据类型的指针或者引⽤;
- constant buffer -常量缓存区, ⼀个指向常量地址空间的任意数据类型的指针或引⽤
- texture - 纹理对象;
- sampler - 采样器对象;
- threadGrounp - 在线程组中供各线程共享的缓存.
Attribute Qualifiers to Locate Buffers, Textures, and Samplers ⽤于寻址缓存,纹理,采样器的属性修饰符。对于每个着⾊器函数来说,⼀个修饰符是必须指定的。他⽤来设定⼀个缓存,纹理, 采样器的位置,如:
- device buffers/ constant buffer --> [[buffer (index)]]
- texture -- [[texture (index)]]
- sampler -- [[sampler (index)]]
- threadgroup buffer -- [[threadgroup (index)]]
8、内建变量属性修饰符
- [[vertex_id]] 顶点id 标识符;
- [[position]] 顶点信息(float4) / 述了⽚元的窗⼝相对坐标(x, y, z, 1/w);
- [[point_size]] 点的⼤⼩(float);
- [[color(m)]] 颜⾊, m编译前得确定;
- [[stage_in]] : ⽚元着⾊函数使⽤的单个⽚元输⼊数据是由顶点着⾊函数输出然后经过光栅化⽣成的.顶点和⽚元着⾊函数都是只能有⼀个参数被声明为使⽤“stage_in”修饰符,对于⼀个使⽤了“stage_in”修饰符的⾃ 定义的结构体,其成员可以为⼀个整形或浮点标量,或是整形或浮点向量 ;