前段时间在研究SceneKit,感受到iOS 系统有不少有趣又好玩的东西,我我的是比较喜欢折腾这些技术的,在研究SceneKit 的时候,发现它有两套渲染机制,OpenGL 和 Matal ,OpenGL 还算比较熟悉,可是Metal部分就不太清除,因而决定好好研究,一下这磨人的小妖精。编程
1.什么是Matal?api
Metal 是一个和 OpenGL ES 相似的面向底层的图形编程接口,经过使用相关的 api 能够直接操做 GPU ,最先在 2014 年的 WWDC 的时候发布,并于今年发布了 Metal 2。 Metal框架支持GPU硬件加速、高级3D图形渲染以及大数据并行运算。且提供了先进而精简的API来确保框架的细粒度(fine-grain),而且在组织架构、程序处理、图形呈现、运算指令以及指令相关数据资源的管理上都支持底层控制。其核心目的是尽量的减小CPU开销,而将运行时产生的大部分负载交由GPU承担安全
2.主要的技能bash
1.3D图形渲染 2.并行运算网络
Metal 具备特色数据结构
有步骤讲解视频以及资料.由于简书文章没有地方放.你们能够加一下个人群获取一下。在群里讨论一下Metal这一块。iOS技术交流群:923910776.多线程
使用Metal和Objective-C来建立一个有基本脉络的应用:画一个简单的三角形。架构
注意:Metal应用不能跑在iOS模拟器上,它们须要一个设备,设备上装载着苹果A7芯片或者更新的芯片。因此须要一台这样的设备(iPhone 5S,iPad Air,iPad mini2)来完成代码的测试。app
流程框架
1.配置 Device 和 Queue 2.获取 CommandBuffer 3.配置 CommandBufferEncoder 4.配置 PipelineState 5.建立资源 6.Encoder Buffer 【若有须要的话能够用 Threadgroups 来分组 Encoder 数据】 7.提交到 Queue 中
- 若是有技术和我讨论或者想拿源码和思惟导图资料的, 请联系我时,备注一下Matal
- 加我技术交流QQ群:923910776
初始化
新建一个普通的工程 Single View Application,在 VC 中导入 Metal Framework。
MTLDevice
都说是操做 GPU 了,固然咱们要拿到 GPU 对象,Metal 中提供了 MTLDevice 的接口,表明了 GPU。
//获取设备
id<MTLDevice> device = MTLCreateSystemDefaultDevice();
if (device == nil) {
NSLog(@"don't support metal !");
return;
}
复制代码
当设备不支持 Metal 的时候会返回空。
MTLCommandQueue
有了 GPU 以后,咱们须要一个渲染队列 MTLCommandQueue,队列是单一队列,确保了指令可以按顺序执行,里面的是将要渲染的指令 MTLCommandBuffer,这是个线程安全的队列,能够支持多个 CommandBuffer 同时编码。 经过 MTLDevice 能够获取队列
id<MTLCommandQueue> queue = self.device.newCommandQueue;
复制代码
MTKView
要用 Metal 来直接绘制的话,须要用特殊的界面 MTKView,同时给它设置对应的 device 为咱们上面获取到 MTLDevice,并把它添加到当前的界面中。
_mtkView = [[MTKView alloc] initWithFrame:self.view.frame device:_device];
[self.view addSubview:_mtkView];
复制代码
渲染
咱们配置好 MTLDevice,MTLCommandQueue 和 MTKView 以后,咱们开始准备须要渲染到界面上的内容了,就是要塞进队列中的缓冲数据 MTLCommandBuffer 。 简单的流程就是先构造 MTLCommandBuffer ,再配置 CommandEncoder ,包括配置资源文件,渲染管线等,再经过 CommandEncoder 进行编码,最后才能提交到队列中去。
MTLCommandBuffer
有了队列以后,咱们开始构建队列中的 MTLCommandBuffer,一开始获取的 Buffer 是空的,要经过 MTLCommandEncoder 编码器来 Encode ,一个 Buffer 能够被多个 Encoder 进行编码。
MTLCommandBuffer 是包含了多种类型的命令编码 - 根据不一样的 编码器 决定 包含了哪些数据。 一般状况下,app 的一帧就是渲染为一个单独的 Command Buffer。MTLCommandBuffer 是不支持重用的轻量级的对象,每次须要的时候都是获取一个新的 Buffer。
Buffer 有方法能够 Label ,用来增长标签,方便调试时使用。
建立
这里咱们经过以下方法建立
//command buffer
id<MTLCommandBuffer> commandBuffer = [_queue commandBuffer];
复制代码
执行
监听结果
commandBuffer.addCompletedHandler { (buffer) in
}
commandBuffer.waitUntilCompleted()
commandBuffer.addScheduledHandler { (buffer) in
}
commandBuffer.waitUntilScheduled()
复制代码
建立 Metal 资源
接下来我须要把咱们须要绘制的内容 encode 到咱们上面生成 MTLCommandBuffer 中。我 们这里是要画一个三角形,因此要有三个顶点,而后须要绘制三角形的图片。分别用 MTLBuffer 来读入三个顶点。
在 Metal 中是归一化的坐标系,以屏幕中心为原点(0, 0, 0),且是始终不变的。面对屏幕,你的右边是x正轴,上面是y正轴,屏幕指向你的为z正轴。长度单位这样来定:窗口范围按此单位刚好是(-1,-1)到(1,1),即屏幕左下角坐标为(-1,-1),右上角坐标为(1,1)。
因此咱们要画在中间一个正三角形的话,三个顶点分别为
(0.577, -0.25, 0.0, 1.0) (-0.577, -0.25, 0.0, 1.0) (0.0, 0.5, 0.0, 1.0)
Shader (着色器) 和 Pipeline (渲染管线)
能够添加多个 Metal 文件,最后都会编译到二进制文件default.metallib 中。 经过 Xcode 的 File - New - File 菜单,新建一个 Metal 文件。
渲染管线
着色器这边的工做已经完成,下面咱们须要把它和咱们的 CommandBuffer 关联起来,就须要咱们的 PipelineState 渲染管线了。
MTLCommandEncoder 编码器
有了资源文件,渲染管线以后,咱们能够开始作最后的步骤了,构造 MTLCommandEncoder 编码器。 指令编码器包括 渲染 计算 位图复制三种编码器。
这里咱们是为了渲染一个三角形,因此这里用的是 MTLRenderCommandEncoder 。
绘制
编码结束以后,就能够开始准备提交到 GPU 了。 配置须要绘制的 Layer,获取 MTKView 的 Layer 就能够。
如今全部的工做就都完成了,运行项目就能够看到三角形了
调试
如何进行调试和评估性能呢? 这里 iOS 提供了两个工具
在 WWDC 2015,苹果发布了 Metal Performance Shaders (MPS) 框架,iOS 9 上的一组高性能的图像滤镜,其实就是边写好的 Shaders,提供了优秀的图像处理能力。同时还提供了高性能的矩阵运算的 Shaders ,能用来作机器学习的运算,在 GPU 上运行卷积神经网络。
提醒广大网友
Metal 是一门特别深的技术,可能须要你花费你半年左右的时间去学习它,但愿有锲而不舍的情深。