序言

前段时间在研究SceneKit,感觉到iOS 系统有很多有趣又好玩的东西,我个人是比较喜欢折腾这些技术的,在研究SceneKit 的时候,发现它有两套渲染机制,OpenGL 和 Matal ,OpenGL 还算比较熟悉,但是Metal部分就不太清除,于是决定好好研究,一下这磨人的小妖精。

初步了解

1.什么是Matal?

Metal 是一个和 OpenGL ES 类似的面向底层的图形编程接口,通过使用相关的 api 可以直接操作 GPU ,最早在 2014 年的 WWDC 的时候发布,并于今年发布了 Metal 2。 Metal框架支持GPU硬件加速、高级3D图形渲染以及大数据并行运算。且提供了先进而精简的API来确保框架的细粒度(fine-grain),并且在组织架构、程序处理、图形呈现、运算指令以及指令相关数据资源的管理上都支持底层控制。其核心目的是尽可能的减少CPU开销,而将运行时产生的大部分负载交由GPU承担

2.主要的技能

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)来完成代码的测试。

流程

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 bufferid<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 是一门特别深的技术,可能需要你花费你半年左右的时间去学习它,希望有持之以恒的情深。

转载于:https://juejin.im/post/5cfe6106e51d45598611b943

对 iOS 中 GPU 编程的高度优化的框架 Metal相关推荐

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

    原文出处: Max Christ and Warren Moore   译文出处:migrant   欢迎分享原创到伯乐头条 Metal 框架支持 GPU 加速高级 3D 图像渲染,以及数据并行计算工 ...

  2. iOS中的长文本高度计算

    很多的时候如果只是要显示一些简单的短文本,比如确定.取消什么的,一个UILabel就足够了. 但是某些情况下,文本较长.包含这些文本的View的高度取决于文本的高度.比如我们常见的 微博.虽然文本所占 ...

  3. iOS中AutoLayout自动布局,自适应高度

    以往我们做cell的自适应的时候都是要写许多的代码进行计算高度,而且在适配的时候容易出现问题,费时耗工.那么下面我们就共同探讨一种基于xib的自动计算高度的方法 1.我们先创建tableView,ta ...

  4. iOS中网络编程长连接

    1.长连接在iOS开发中的应用 常见的短连接应用场景: 一般的App的网络请求都是基于 Http1.0 进行的,使用的是 NSURLConnection.NSURLSession 或者是 AFNetw ...

  5. iOS视图成像理论及性能优化

    iOS不是一蹴而就的,其中参杂了无数先驱的心血与智慧.在我们享受着iPhone的便捷时,其实我们忽略了很多细节,视图成像就是这样.每天我们都会不自然的打开手机,点击应用,处理信息,获取快乐,但是我们所 ...

  6. GPU 编程入门到精通(五)之 GPU 程序优化进阶

    版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 博主由于工作当中的需要,开始学习 GPU 上面的编程,主要涉及到的是基于 GPU 的深度学习方面的知识,鉴于之前没有接触过 GP ...

  7. GPU 编程入门到精通(四)之 GPU 程序优化

    版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 博主由于工作当中的需要,开始学习 GPU 上面的编程,主要涉及到的是基于 GPU 的深度学习方面的知识,鉴于之前没有接触过 GP ...

  8. 浅谈iOS中关于app的优化

    目录 我要给出的建议将分为三个不同的等级: 入门级. 中级和进阶级: 入门级(这是些你一定会经常用在你app开发中的建议) 1. 用ARC管理内存 2. 在正确的地方使用reuseIdentifier ...

  9. 深入优化GPU编程概述

    网上关于GPU编程优化的文章很多,本篇博客带领读者更深入的理解GPU编程以及各个函数的运行时间,为开发者优化Shader编程提供一些指导.除了Shader编程中的变量定义精度优化,还有函数的优化,下面 ...

最新文章

  1. 暴风影音CEO冯鑫称与腾讯不惜一战
  2. shedlock mysql_ShedLock日常使用
  3. 全球大学生超级计算机竞赛排名,清华团队蝉联世界大学生超级计算机竞赛总冠军...
  4. Docker/Docker 起步123
  5. 韩顺平循序渐进学java 第13讲 抽象类.接口
  6. IOS背景半透明渐变问题
  7. Java抽象类、接口、类的特殊成员
  8. [BZOJ 2152]聪聪可可(点分治)
  9. 俄羅斯大神 Ratiborus 的推特
  10. ResourceHacker(4.5.30)单文件绿色汉化版
  11. linux检测主机网络配置和状况的命令是,Linux常用网络状态测试命令
  12. H5开发html文件转换pdf,将HTML页面转换为PDF文件并导出
  13. Linux中scp报 not a regular file错误解决方案
  14. Android跳转小项目-CHANGE页面-Recycylerview、List、Context(二)
  15. linux 显卡 卡死,linux服务器显卡崩溃解决方案
  16. QT5单元测试(按键测试)
  17. 产品经理的5分钟统计课:产品/用户/数据平均情况是怎样?
  18. 【locust】使用locust + boomer实现对接口的压测
  19. springcloud 加入spring session通过zuul请求session不一致问题
  20. stm32学习笔记——通用计时器基本原理

热门文章

  1. solr4.4.0 集成 carrot2 支持中文和添加自己的中文分词器的方法。
  2. 窥探Flutter的前世今身
  3. 轻松洁净地面,还能自动清洗烘干拖布,只需一台追觅扫拖机器人
  4. 11. 前端基础--CSS盒子定位
  5. java小项目影院系统
  6. java 影院售票系统_java电影院售票系统
  7. javac HelloWorld.java 找不到文件问题
  8. mysql随机生成数据并插入_python生成随机数据插入mysql
  9. 二次元PHP随机api接口源码,随机二次元图片API接口php源码
  10. ArcEngine IPageLayout 添加经纬网和公里网