Metal着色器语言是用来编写3D图形渲染逻辑和并行计算核心逻辑的一门编程语言。Metal框架来完成APP的实现时,则需要Metal编程许愿。
Metal语言使用Clang和LLVM进行编译处理,基于c++11.0语言设计。我们主要用来编写在GPU上执行的图像渲染逻辑代码以及通用并行计算逻辑代码。
下面我们来介绍一下Metal的一些基本内容
Metal数据类型:
bool布尔类型,true/false
char 有符号8位整数
unsigned char /uchar 无符号8-bit整数
short 有符号16-bit整数
unsigned short /ushort 无符号32-bit整数
half 16位bit浮点数(Metal没有double类型,用half代替)
float 32bit浮点数
size_t 64无符号整数
void 该类型表示一个空的值集合
```
int4 test = int4(0,1,2,3);
我们可以通过x,y,z,w和r,g,b,a来获取test中的各个内容.
例如
int a = test.x;
int b = test.y;
……
int m = test.r;
int n = test.a;
……
也可以赋值
int4 c;
c.xyzw = test;
//修改:
x.z = 1.0;
int2 pos;
pos.y = 2.0f;//合法
pos.z = 1.0f;//非法
pos.xx = float2(3.0,4.0);//非法
另外,rgba不能与xyzw混合使用
```
纹理Textures 类型
纹理类型是一个句柄,它指向一个一维/二维/三维纹理数据
枚举值:定义了访问权利
enum class access{sample,read,write};
sample:纹理对象可以被采样,采样一维这是使用或不使用采样器从纹理中读取数据。
read:不使用采样器,一个图形渲染函数或者一个并行计算函数可以读取纹理对象。
write:一个图形渲染函数或者一个并行计算函数可以向纹理对象写入数据。
texture1d<T,access a = access::sample>
texture2d<T,access a = access::sample>
texture3d<T,access a = access::sample>
T:数据类型,设定了从纹理中读取或向纹理中写入时的颜色类型,T可以是half,float,short,int等。
代码示例
void foo (texture2d<float> imgA [[ texture(0) ]] ,
texture2d<float, access::read> imgB [[ texture(1) ]],
texture2d<float, access::write> imgC [[ texture(2) ]])
{ ... }
采样器类型Samplers
采样器类型决定了如何对一个纹理进行采样操作,在Metal框架中有一个对应着色器语言的采样器的对象,MTLSamplerState这个对象作为图形渲染着色器函数参数或是并行计算函数的参数传递。
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修饰符声明
constexpr sampler s(coord::pixel,address::clamp_to_zero,
filter::linear);
constexpr sampler a(coord::normalized);
constexpr sampler b(address::repeat);
constexpr sampler s(address::clamp_to_zero,filter::linear)
函数修饰符
Metal有三种修饰符类型:
Kernel,表示该函数是一个数据并行计算着色器函数,它可以被分配在一维/二维/三维线程组中去执行。
vertex,表示该函数是一个顶点着色器函数,它将为顶点数据流中的每一个顶点数据执行一次然后为每个顶点生成数据输出到绘制管线。
fragment,表示该函数是一个片元着色器函数,它将为片元数据流中的每个片元和其关联执行一次然后将每个片元生成的颜色数据输出到绘制管线中。
注意:
1、使用kernel修饰的函数,其返回值必须是void
2、一个被函数修饰符修饰的函数不能在调用其他也被函数修饰符修饰的函数;这样会导致编译失败。
用于变量或参数的地址空间修饰符
Metal着色器语言使用地址空间修饰符来表示一个函数变量或者参数变量,被分配于那一片内存区域,所有的着色函数(vertex,fragment,kernel)的参数,如果是指针或是引用,都必须带有空间修饰符号。
device
threadgroup
constant
thread
对于图形着色器函数,其指针或是引用类型的参数必须定义为device或是constant地址空间;对于并行计算着色器函数,其指针或是引用类型的参数必须定义为device或是threadgroup或是constant地址空间。
Device Address Space(设备地址空间)
在设备地址空间指向设备内存池分配出来的缓存对象,它是可读也是可写的;一个缓存对象可以被声明成一个标量,向量或是用户自定义结构体的指针或是引用
注意:纹理对象总是在设备地址空间分配内存,device地址空间修饰符不必出现在纹理类型定义中,一个纹理对象内容无法直接访问Metal提供读写纹理的内建函数。
threadgroup Address Space(线程组地址空间)
线程组地址空间用于为并行计算着色函数分配内存变量,这些变量被一个线程组的所有线程共享,在线程组地址空间分配的变量不能被用于图形绘制着色函数[顶点着色器函数,片元着色器函数]
在并行计算着色函数中,在线程组地址空间分配的变量为一个线程组使用,声明周期和线程组相同
kernel void my_func(threadgroup float *a [[ threadgroup(0) ]],...) {
// A float allocated in threadgroup address space threadgroup float x;
// An array of 10 floats allocated in
// threadgroup address space
threadgroup float b[10];
}
constant Address Space常量地址空间
常量地址空间指向的缓存对象也是从设备内存池分配存储,但是它是只读的;
在程序域的变量必须定义在常量地址空间并且声明的时候初始化,用来初始化的值必须是编译时的常量
在程序域的变量的声明周期和程序一样,在程序中的并行计算着色函数或图形绘制着色函数调用,但是contsant的值不回保持不变。
注意:常量地址空间的指针或是引用可以作为函数的参数,向声明为常量的变量赋值会产生编译错误,声明常量但是没有赋予初值也会编译错误
thread Address Space线程地址空间
thread地址空间指向每个线程准备的地址空间,这个线程的地址空间定义的变量在其他线程不可见,在图形绘制着色函数或者并行计算着色函数中声明的变量thread地址空间分配;
函数参数与变量
图形绘制或者并行计算着色器函数的输入输出都是通过传递参数,除了常量地址空间变量和程序域定义的采样器除外
device buffer:设备缓存,一个指向设备地址空间的任意数据类型的指针或引用
constant buffer:常量缓存区,一个指向常量地址空间的任意数据类型的指针或引用
texture :纹理对象
sampler :采样器对象
threadGroup :在线程组中提供各线程共享的缓存。
注意:被着色器函数的缓存(device,constant)不能重名
Attribute Qualifiers to Location Buffers,Textures and Samplers用于寻址缓存,纹理采样器的属性修饰符。
内建变量属性修饰符
[[vertex_id]] 顶点id标识符
[[position]] 顶点信息
[[point_size]] 点的大小
[[color(m)]] 颜色
[[stage_in]]:片元着色器函数使用的单个片元输入数据由顶点着色器函数输出然后经过光栅化生成的,顶点和片元着色函数都是只能有一个参数被声明为“stage_in”修饰符,对于一个使用了“stage_in”修饰符的自定义的结构体,其成员可以为一个整形或浮点标量或是整形或浮点向量
网友评论