Metal 系列教程
Metal_入门01_为什么要学习它
Metal_入门02_带你走流程
前言
前段时间在研究OpenGL ES和 SceneKit ,感觉到iOS 系统有很多有趣又好玩的东西,我个人是比较喜欢折腾这些技术的,不是项目需求,只是为了揭开那些东西神秘的面纱,仅此而已,为什么我又开始研究Metal 了呢?因为在学习SceneKit 的时候,发现它有两套渲染机制,OpenGL 和 Matal ,OpenGL 还算比较熟悉,但是Metal部分就不太清除了,所以SceneKit 的学习,暂时搁浅,从今天开始,就开始和它谈恋爱。不知能不能找到真爱。
初步了解
a.自我介绍
Metal框架支持GPU硬件加速、高级3D图形渲染以及大数据并行运算。且提供了先进而精简的API来确保框架的细粒度(fine-grain),并且在组织架构、程序处理、图形呈现、运算指令以及指令相关数据资源的管理上都支持底层控制。其核心目的是尽可能的减少CPU开销,而将运行时产生的大部分负载交由GPU承担
感觉有点还蛮多的,姑且相信你,在交往过程中,再去体会吧!
b.主要的技能
1.3D图形渲染
2.并行运算
c.网友对Metal的理解
1.当我们使用OpenGL ES 渲染一个纹理的时候,需要将数据从cpu 拷贝一份到gpu 中,以防止gpu 和cpu同时访问这块内存,而反观Metal,就会发现它并无需这样的处理方式,开发者可以在CPU和GPU之间同步使用这些数据
2.是Metal能预判GPU的状态从而避免那些多余的校验和编辑。在使用OpenGL的时候,习惯上我们会挨个儿设置GPU的状态,然后每次进行绘制调用之前必须要校验一道GPU的状态。在最糟糕的情况下你甚至需要为了一个新的GPU状态重编译一遍阴影效果,当然,在这里采用预判GPU状态就显得相当必要了。不过Metal另辟蹊径,在初始化渲染引擎的时候,GPU的状态会被打包进一个预估的渲染通道,(render pass),此状态下渲染通道会与多种资源一起被使用,而其他的状态不会有任何影响。Metal使用的渲染通道不需要多余的校验,因而最大限度的减少了API负载,且对于每一帧的渲染都有质的提升
3.然很多API都通过具体类来实现平台支持,不过Metal使用的方法是基于协议的。因为Metal中具体的类型是由运行的设备所决定的。这很好的鼓励了程序员选择面向接口编程而非面向实现,以降低程序的耦合。当然也意味着需要冒着风险大量的在Objective C运行时来对Metal的类型添加继承和扩展类型
d.我们应该学习Metal 的哪些内容
1.命令提交模型
2.内存管理模型
3.独立编译的绘图着色器程序和并行计算的函数
- Metal 框架的特点
1.消除“隐藏”的性能瓶颈,如隐式状态验证。你可以在多线程异步控制GPU,有效用于平行创建和提交命令缓冲区
2.描述了缓冲和纹理对象代表了GPU的内存分配。纹理对象有特定的像素格式,并可用于纹理图像或附件对象
3.使用相同的数据结构和资源(如缓冲区、纹理和命令队列),用于图形和计算操作。此外,金属着色语言支持图形和计算功能。Metal使得资源能够和runtime接口、图形着色器、并计算函数之间共享
4.metal 着色器可以和你的app代码一样在运行时加载,编译,这样的好处时能够更好的生成代码,以及编译调试
5.Metal 不能再后台执行命令代码,否则系统崩溃
- 命令提交模型深入学习
a.在Metal 的架构中,MTLDevice 协议定义了简单的代表GPU 的接口,此协议提供了方法去查询设备的属性,创建设备的特殊对象,比如缓冲区或者纹理,编码和排队渲染和计算命令被提交给GPU执行
b.命令队列由命令缓冲队列和组织这些命令缓冲执行顺序的命令队列组成,命令缓冲区包含用于在特定设备上执行的编码命令,命令编码器将绘制、计算、和blitting命令添加到命令缓冲区,将命令缓冲区最终提交到设备上执行
c .MTLCommandQueue 协议了一个命令队列接口,主要提供了方法创建命令缓冲对象,MTLCommandBuffer协议为命令缓冲对象定义了一些方法,提供方法去创建命令编码器,入队命令缓冲区执行,检查状态,以及一些其他操作,MTLCommandBuffer 协议提供了一下几种编码类型,决定了编码不同种类的GPU工作,到指定的命令缓冲区中
MTLRenderCommandEncoder:主要用户绘图编码
MTLComputeCommandEncoder: 主要用于并行计算
MTLBlitCommandEncoder:编码简单的缓冲区和纹理拷贝操作,以及像mipmap 图像的生成
d.在任何时候,只有单个命令编码器可以被激活,添加命令到一个命令缓冲区上去,下一个命令编码器被创建和用与同一缓冲区之前,必须将上一个命令编码器结束掉
e.当所有编码完成时,你提交MTLCommandBuffer 对象,这就意味着GPU 已经标记了命令缓冲区,准备开始执行
下图展示了命令队列,命令缓冲区区,命令编码器之间的关系,(buffer, texture, sampler, depth and stencil state, pipeline state) 表示特定于某一特定命令编码器的资源和状态
以上内容,大体阐述了下面几件事情
1.MTLDevice 代表GPU 可以执行命令,可以创建新的命令队列,可以分配内存,可以创建纹理和查询设备信息
2.MTLCommandQueue 接受GPU 将要顺序执行的命令缓冲区对象的列表,所有命令缓冲对象发送到一个单一队列被保证是按照顺序执行的,命令队列是线程安全的,允许多个命令缓冲区同时进行编码
3.MTLCommandBuffer 存储了编码命令知道缓冲区被提交到GPU被执行,一个单一的命令缓冲区对象可以包含许多不同种类的编码命令,取决有编码器的数量和类型,在一典型的app 应用中,一个完整的渲染帧,被包含在一个单一的命令缓冲区中,即使渲染的帧,包含多个渲染传递,计算处理函数,或者或blit操作,命令缓冲区是单次使用的对象,不能被重用,一旦命令缓冲区被提交到GPU去执行,只有一种操作是有效的,就是等待命令缓冲区被加入执行列表或处理程序块登记命令缓冲区执行处理程序块讨论完成并检查命令缓冲区的执行情况,命令缓冲区也代表工作的唯一独立跟踪单元的应用程序
4.MTLRenderCommandEncoder 命令编码器是一个短暂的对象,你用一次写命令和状态中,GPU可以执行一个命令缓冲区格式。许多命令编码器对象方法将命令追加到命令缓冲区上。当一个命令编码器是活动的,它有它的命令缓冲区的附加命令的独占权。一旦你完成编码的命令,调用endEncoding方法。要写进一步的命令,创建一个新的命令编码器
- 区分可重用的对象和不可重用的对象
a.可重用的对象
Command queues
Data buffers
Textures
Sampler states
Libraries
Compute states
Render pipleline states
Depth/stencil states
b.不可重用的对象
Command buffer
command encoder
我提醒广大网友
Metal 是一门特别深的技术,可能需要你花费你半年左右的时间去学习它,希望有持之以恒的情深。
本节的内容先阐述到这里,有人看到这里就选择了放弃,但是自信的人往往会点赞继续!
参考资料
Metal编程指导
着色器语言学习指南
经典案例