Metal是苹果公2014年推出的一套取代OpenGLES的渲染应用程序编程接口,支持到iOS8以上。Metal不单延续了OpenGLES中的渲染高级3D图形
,还可以使用GPU
高效完成数据并行计算。
Core Image
, SpriteKit
, 和 SceneKit
已经在使用了。
Cpu:处理顶点数据->GPU: 顶点处理(顶点着色器)->图元装配(5种)->光栅化->片段处理(片元着色器)->帧缓存区
OpenGl
可以对照这幅图回忆一下自己的知识结构和OpenGLES中的知识点。
Separate Your Rendering Loop
分开渲染循环:不希望将渲染的处理逻辑放到ViewController | View中。建议单独创建一个类来完成各种Metal的渲染绘制工作。Respond to View Events
响应代理<MTKViewDelegate>的事件Metal Command Objects
创建一个命令对象,即创建执行命令的GPU图一
图二
两张图可以对比来看
838133-8b76a2d6479f743b.jpg
MTKView理解上可以对标GLKView来理解。 相同点: 提供用于绘制layer的专属视图。
不同点:
MTLDevice
Metal是直接操作GPU的,所以需要获取GPU的使用权限。在iOS中一般是通过默认的方式MTLCreateSystemDefaultDevice()
获取GPU的使用权限。也可以使用MTLCopyAllDevices()
来获取系统中所有Metal设备对象的引用数组。
MTLDevice协议表示可以执行命令的GPU,提供了如下功能
在获取了GPU后,还需要一个渲染队列,即命令队列Command Queue类型是MTLCommandQueue
,该队列是与GPU交互的第一个对象,队列中存储的是将要渲染的命令MTLCommandBuffer
。正好对应上方图。
创建方式:
_commandQueue = [_device newCommandQueue];
命令缓存区Command Buffer主要是用于存储编码的命令,其生命周期是指导缓存区被提交到GPU执行为止,单个的命令缓存区可以包含不同的编码命令,主要取决于用于构建它的编码器的类型和数量。
创建方式:
commandBuffer = [_commandQueue commandBuffer]
Command Queue
来创建的CommandEncoder
都需要通过当前buffer来进行提交、渲染、绘制.commandBuffer在未提交命令缓存区之前,是不会开始执行的。等待提交后命令缓存区将按其按照加入队的顺序进行执行。当然这是整个编码步骤中的最后一步。 commandBuffer的执行顺序有以下两种:
MTLRenderCommandEncoder表示单个渲染过程中相关联的渲染状态和渲染命令(可以对标OpenGL中的上下文状态机来理解),有以下功能:
图形资源
,例如缓存区和纹理对象,其中包含顶点、片元、纹理图片数据MTLRenderPipelineState对象
,其中包含编译的渲染状态、顶点着色器、片段着色器固定功能状态
,包括视口,三角形填充模式,剪刀矩形,深度和模板测试以及其他值MTLCommandBuffer
对象的makeRenderCommandEncoder(descriptor :)
方法来创建MTLRenderCommandEncoder
对象。setRenderPipelineState(_ :)
方法以指定MTLRenderPipelineState
,该状态定义图形渲染管道的状态,包括顶点和片段函数。commandEncoder
调用setVertexBytes:length:atIndex:
函数传递到metal shader Language
文件的顶点着色器和片元着色器函数commandEncoder
调用setViewport:
函数设置视口大小等endEncoding()
方法以终止渲染命令编码器。MTLRenderPipelineDescriptor管道状态描述符:在渲染过程中使用的渲染配置状态,包括光栅化(例如多重采样),可见性,混合,镶嵌和图形功能状态,主要是渲染管道描述符中指定顶点或片段函数。
举例:
MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
//管道名称
pipelineStateDescriptor.label = @"Simple Pipeline";
//可编程函数,用于处理渲染过程中的各个顶点
pipelineStateDescriptor.vertexFunction = [defaultLibrary newFunctionWithName:@"vertexShader"];
//可编程函数,用于处理渲染过程中各个片段/片元
pipelineStateDescriptor.fragmentFunction = [defaultLibrary newFunctionWithName:@"fragmentShader"];
//一组存储颜色数据的组件
pipelineStateDescriptor.colorAttachments[0].pixelFormat = mtkView.colorPixelFormat;
//同步创建并返回渲染管线状态对象
_pipelineState = [_device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor error:&error];
官方文档定义为渲染命令编码器描述符:用于保存渲染过程中的一组结果
下图中红圈位置代表MTLRenderPassDescriptor
在Metal整个渲染流程中的位置,也可以对标OpenGLES中的frameBuffer
来理解
Metal渲染流程