通过这篇文章你将了解Metal渲染管线的工作流程,这有助于你深入了解Metal工作流程,以及Metal是基于什么现有条件设计的。
参考文章: 《Metal by Tutorials》
1.CPU和GPU
所有计算机都有一个中央处理单元(CPU),可以驱动计算机上的操作和管理资源。他们还有一个图形处理单元(GPU)。
GPU是一种专门的硬件组件,可以非常快速地处理图像、视频和大量数据。这被称为吞吐量。吞吐量由特定时间单位处理的数据量来衡量。
另一方面,CPU无法非常快速地处理大量数据,但它可以非常快速地处理许多顺序任务(一个接一个)。处理任务所需的时间称为延迟。
理想的设置包括低延迟和高吞吐量。低延迟允许串行执行排队任务,因此CPU可以执行命令,而不会系统变得缓慢或无响应;高吞吐量允许GPU异步渲染视频和游戏,而不会使CPU停滞不前。由于GPU具有高度并行化的架构,专门重复执行相同的任务,并且很少或没有数据传输,因此它能够处理大量数据。
2. 渲染管线
如下图所示,渲染管线分为以下几个部分:
图形管道将顶点带过多个阶段,在此期间,顶点的坐标在不同空间之间转换。
作为程序员,您只关心顶点和片段处理阶段,因为只有它们是可编程阶段。
1.顶点获取:
通过设置顶点缓冲对象,可以给GPU传递顶点数据。
类似如下代码:
renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0)
2.顶点处理
在这个阶段,顶点是单独处理的。您编写代码来计算每个顶点照明和颜色。更重要的是,您通过各种坐标空间发送顶点坐标,以获取它们在最终帧缓冲区中的位置。
3.图元装配
上一阶段将分组为数据块的处理顶点发送到此阶段。需要记住的是,属于相同几何形状(原始)的顶点始终位于同一块中。这意味着一个点的一个顶点,或一条线的两个顶点,或一个三角形的三个顶点,将始终在同一块中,因此永远不需要第二个块获取。不仅仅是顶点信息,CPU同时还会发送与顶点相关联的信息。类似下面的代码:
renderEncoder.drawIndexedPrimitives(type: .triangle,
indexCount: submesh.indexCount, indexType: submesh.indexType, indexBuffer: submesh.indexBuffer.buffer,
indexBufferOffset: submesh.indexBuffer.offset)
第一个参数是绘制图元的类型,这里Metal支持五种图元类型(和OpenGL ES类似)
如下图所示:
图示清晰地展示了几种类型的区别,这里就不做过多赘述了。
4.光栅化
目前有两种现代渲染技术在不同的路径上发展,但有时一起使用:光线追踪和光栅化。他们完全不同;两者都有利弊。
在渲染静态和遥远的内容时,首选光线追踪——您将在第18章“用光线渲染”中阅读更多内容,而当内容更接近相机且更动态时,更倾向于光栅化。
通过光线追踪,对于屏幕上的每个像素,它都会向场景发送光线,看看是否与物体相交。如果是,请将像素颜色更改为该对象的颜色,但前提是该对象比之前为当前像素保存的对象更接近屏幕。
光栅化的作用相反:对于场景中的每个对象,将光线发送回屏幕,并检查对象覆盖的像素。深度信息与光线追踪的方式相同,因此如果当前对象比之前保存的对象更近,它将更新像素颜色。
此时,从上一阶段发送的所有连接顶点都需要使用其X和Y坐标在二维网格上表示。此步骤称为三角形设置。
在这里,光栅化器需要计算任何两个顶点之间线段的斜率或陡度。当知道三个顶点的三个斜率时,三角形可以从这三个边形成。
接下来,一个名为扫描转换的过程在屏幕的每一行上运行,以查找十字路口,并确定什么是可见的,什么是不可见的。此时,要在屏幕上绘图,只需要它们确定的顶点和斜率。
扫描算法确定线段上的所有点或三角形内的所有点是否可见,在这种情况下,三角形完全充满颜色。
简而言之,光栅化就是把矢量图形转化为像素点的过程。
5.顶点处理
如上图所示:
顶点获取单元从内存中抓取顶点,并将其传递给调度器单元。
调度器单元知道哪些着色器内核可用,因此它调度工作。
工作完成后,分销商部门知道这项工作是顶点还是碎片处理。
如果是顶点处理工作,它会将结果发送到原始汇编单元。此路径继续到光栅化单元,然后返回到调度器单元。
如果是片段处理工作,它会将结果发送到颜色书写单元。
最后,彩色像素被送回内存。
6.帧缓冲
一旦碎片被处理成像素,分销商单元就会将其发送到颜色书写单元。该单元负责在称为帧缓冲区的特殊内存位置写入最终颜色。从这里,视图的每个帧都会刷新其彩色像素。但这是否意味着颜色在屏幕上显示时写入帧缓冲区?
使用一种称为双缓冲的技术来解决这种情况。当第一个缓冲区显示在屏幕上时,第二个缓冲区在后台更新。然后,交换两个缓冲区,第二个缓冲区显示在屏幕上,而第一个缓冲区更新,循环继续。
大致了解完渲染管线后,接下来就是结合demo来了解Metal编程了。