1.Metal 是一个和 OpenGL ES 类似的面向底层的图形编程接口,可以直接操作GPU;支持iOS和OS X,提供图形渲染和通用计算能力。(不支持模拟器)-
Metal框架支持GPU硬件加速、高级3D图形渲染以及大数据并行运算。且提供了先进而精简的API来确保框架的细粒度(fine-grain),并且在组织架构、程序处理、图形呈现、运算指令以及指令相关数据资源的管理上都支持底层控制。其核心目的是尽可能的减少CPU开销,而将运行时产生的大部分负载交由GPU承担
MTLDevice :对象代表GPU,通常使用MTLCreateSystemDefaultDevice获取默认的GPU;
MTLCommandQueue:由device创建,用于创建和组织MTLCommandBuffer,保证指令(MTLCommandBuffer)有序地发送到GPU;MTLCommandBuffer会提供一些encoder,包括编码绘制指令的MTLRenderCommandEncoder、编码计算指令的MTLComputeCommandEncoder、编码缓存纹理拷贝指令的MTLBlitCommandEncoder。对于一个commandBuffer,只有调用encoder的结束操作,才能进行下一个encoder的创建,同时可以设置执行完指令的回调。
MTLRenderCommandEncoder,MTLComputeCommandEncoder,MTLBlitCommandEncoder:分别代表渲染,计算,拷贝指令
PipelineState:也是由device创建其包含了顶点着色器和片元着色器以及并行运算,动态的供CommandEncoder使用,一个state代表一组着色器
Texture和Buffer:由device创建,动态的供CommandEncoder使用
Threadgroups:结构体,是并行计算着⾊器的线程组数量,动态的供MTLComputeCommandEncoder使用
GPUs的类型很多,每一种都有各自的接收和执行指令方式,在MTLCommandEncoder把指令进行封装后,MTLCommandBuffer再做聚合到一次提交里。
暂态和⾮非暂态对象:
暂态对象:
在Metal中有些对象被设计成暂态,使⽤用它们⾮非常轻量,下⾯面这些对象是暂态的,被设计来⼀一次性使⽤用,它们的创建和销毁的成本都⾮非常廉价,它们的创建⽅方法都返回autoreleased对象。
Command Buffers
Command Encoders
非暂态对象:
下⾯面这些对象是⾮非暂态的,在性能相关的代码⾥里应该尽量重⽤用之,避免反复创建
Command Queues
Buffers
Textures
Sampler States Libraries
Compute States
Render Pipeline States
Depth/Stencil States
并行计算
通用图形计算是general-purpose GPU,简称GPGPU。
GPU可以用于加密、机器学习、金融等,图形绘制和图形计算并不是互斥的,Metal可以同时使用计算管道进行图形计算,并且用渲染管道进行渲染。
计算管道只有一个步骤,就是kernel function(内核函数),内核函数直接读取并写入资源,不像渲染管道需要经过多个步骤;
MTLComputePipelineState 代表一个计算处理管道,只需要一个内核函数就可以创建,相比之下,渲染管道需要顶点和片元两个处理函数;
每次内核函数执行,都会有一个唯一的gid值;
内核函数的执行次数需要事先指定,这个次数由格子大小决定。
threadgroup 指的是设定的处理单元,这个值要根据具体的设备进行区别,但必须是足够小的,能让GPU执行;
threadgroupCount 是需要处理的次数,一般来说threadgroupCount*threadgroup=需要处理的大小。
上图左边是一幅1024*768个像素大小的图片,那么共需要1024*768个线程;我们将这些线程分为32*48个线程组,每个线程组有32*16个线程(上右图)
Metal Language
1. Metal 与 C++ 11.0
Metal 这门语言是基于C++ 11.0标准设计的.它在C++基础是行多了一些拓展和限制.下面我们可以简单介绍介绍Metal着色语言与C++11.0 相比之下的修改和限制:
1.1 Metal 语言支持重载,如果C++11.0,包括方法重载规则,可以包括参数的地址空间描述符.Metal着色语言中的标识为图形渲染入口函数或是并行计算入口函数的不可以被重载
1.2 Templates 模块
Metal 着色语言支持的模板如图C++11.0 一样.
1.3 Preprocessing Directives 预编译指令
Metal 和 C++11.0 一样支持预编译指令
1.4 Restrictions 限制
如下的C++11.0特性在Metal 着色语言中是不支持的;
Lambda表达式
递归函数调用
动态转换操作符
类型识别
对象创建(new)和释放(delloc)操作符
操作符noexcept
goto跳转
变量存储修饰符register和thread_local
虚函数修饰符
派生类
异常处理
1.5 Metal着色语言是有对于指针的使用限制
1.6Metal图形和并行计算函数用到的入参如果是指针必须使用地址空间修饰符(device,threadgroup,constant)
1.7 不支持函数指针
1.8 Metal函数名不能命名为main函数
基本数据类型:
Metal的数据类型包含表示向量和矩阵的类型,原子数据类型,缓存,纹理,采样器,数组,自定义结构体,还会描述类型对齐和类型转换.
1. 标量数据类型:
Metal 支持如下表格的类型,但是它不支持double,long,unsigned long ,long long,unsigned long long,long double
Metal 数据类型
注意
f或者F,表示单精度浮点类型字面量,(例如,0.5f 或 0.5F);
h或者H,表示半单精度浮点类型字面量,(例如,0.5h 或 0.5H);
u或者U,表示无符号整形字面量.
2.向量和矩阵数据类型
Metal着色语言通过系统向量数学库支持一系列的向量和矩阵数据类型.
向量支持如下类型
booln
charn
shortn
intn
ucharn
ushortn
uintn
halfn
floatn
向量中的n,指的是维度.假设2,表示二维
矩阵支持如下类型
halfnxm
floatnxm
nxm分别指的是矩阵的行数和列数.
3. 访问向量的分量
//基本数据类型
bool a = true;
char b = 5;
int d = 15;
size_t c = 1;
ptrdiff_t f = 2;
//向量
bool2 A= [1,2];
float4 pos = float4(1.0,2.0,3.0,4.0);
float x = pos[0];
float y = pos[1];
float4 VB;
for(int i = 0; i < 4 ; i++)
VB[i] = pos[i] * 2.0f;
Metal 支持(,)作为选择向量分量进行访问操作符.可以使用坐标分量或者是颜色分量的字母来存取向量.向量名.xyzw,或是向量名.rgba;
//通过向量字母来获取元素
int4 test = int4(1,2,3,4);
int a = test.x;
int b = test.y;
int c = test.z;
int d = test.w;
int e = test.r;
int f = test.g;
int g = test.b;
int h = test.a;
缓存:
函数修饰符:
变量和参数修饰符:
注意:device是可变的,constant是不可变的
用于缓存、纹理、采样器的寻址修饰符:
index表示了一个缓存、纹理、采样器的位置,它是一个索引;
[[position]] 表示顶点坐标,为什么必须要指定postion不指定textureCoordinate等?因为顶点着色器要使用postion而其它是要传递给片元着色器的, [[ vertex_id ]]表示顶点数组中某一个顶点坐标
顶点着色器除了用 [[ vertex_id ]]和 [[ buffer(index) ]]来定位单个顶点,还可以使用[[ stage_in ]]和[ attribute(index) ]、 [[ vertex_id ]]来定位单个顶点