对 iOS 中 GPU 编程的高度优化的框架 Metal

序言

前段时间在研究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 平台独有的
  • 消除“隐藏”的性能瓶颈,如隐式状态验证。你能够在多线程异步控制GPU,有效用于平行建立和提交命令缓冲区
  • 描述了缓冲和纹理对象表明了GPU的内存分配。纹理对象有特定的像素格式,并可用于纹理图像或附件对象
  • 使用相同的数据结构和资源(如缓冲区、纹理和命令队列),用于图形和计算操做。此外,金属着色语言支持图形和计算功能。Metal使得资源可以和runtime接口、图形着色器、并计算函数之间共享
  • Metal 着色器能够和你的app代码同样在运行时加载,编译,这样的好处时可以更好的生成代码,以及编译调试
  • 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 ,用来增长标签,方便调试时使用。

建立

  • MTLCommandQueue - commandBuffer 方法 ,只能加到建立它的队列中。
  • 获取 retain 的对象 commandBufferWithUnretainedReferences 可以重用 通常不推荐

这里咱们经过以下方法建立

//command buffer
    id<MTLCommandBuffer> commandBuffer = [_queue commandBuffer];
复制代码

执行

  • enqueue 顺序执行
  • commit 插队尽快执行 (若是前面有 commit 就仍是排队等着)

监听结果

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 渲染 3D 编码器
  • MTLComputeCommandEncoder 计算编码器
  • MTLBlitCommandEncoder 位图复制编码器 拷贝 buffer texture 同时也能生成 mipmap

这里咱们是为了渲染一个三角形,因此这里用的是 MTLRenderCommandEncoder 。

绘制

编码结束以后,就能够开始准备提交到 GPU 了。 配置须要绘制的 Layer,获取 MTKView 的 Layer 就能够。

如今全部的工做就都完成了,运行项目就能够看到三角形了

调试

如何进行调试和评估性能呢? 这里 iOS 提供了两个工具

  • Xcode 中的 Capute GPU Frame
  • Instruments 中的 Metal System Trace

总结

在 WWDC 2015,苹果发布了 Metal Performance Shaders (MPS) 框架,iOS 9 上的一组高性能的图像滤镜,其实就是边写好的 Shaders,提供了优秀的图像处理能力。同时还提供了高性能的矩阵运算的 Shaders ,能用来作机器学习的运算,在 GPU 上运行卷积神经网络。

提醒广大网友

Metal 是一门特别深的技术,可能须要你花费你半年左右的时间去学习它,但愿有锲而不舍的情深。

相关文章
相关标签/搜索