图形渲染框架
1、绘制工具
UIBezierPath: 创建基于矢量的路径,如圆形、椭圆形和矩形,或者由多个直线和曲线组成的形状。是对CoreGraphics的进一步封装。属于UIKit。
CAShapeLayer: CAShapeLayer继承于CALayer,属于CoreAnimation,需要由UIBezierPath提供路径才能绘制,CAShapeLayer是GPU绘制,性能好,渲染速度快。
CoreGraphics: 基于Quartz框架的2D 绘图引擎, 运行时在CPU上执行绘制命令进行绘图,绘完给GPU渲染。
OpenGL ES: 直接操作GPU渲染。
Metal: 苹果2018推出的在苹果设备上取代OpenGL ES的图形编程接口(或说编程规范更准确),跟OpenGL ES类似使用相关API可直接操作GPU。
2、CPU绘制 & GPU渲染
CPU 绘制: 如重写drawRect方法,并使用Core Graphics的API绘制图形,整个过程在CPU计算,最终生成GPU渲染需要的顶点、纹理数据等。
GPU 渲染:接收CPU生成的顶点、纹理等数据, 通过OpenGL渲染管线生产屏幕显示需要的图像数据。
OpenGL 渲染管线:
3、屏幕成像
GPU最后一步渲染结束之后像素信息(位图),存在帧缓冲中,等待显示器电子束从左上角开始逐行扫描(或隔行扫描)读取显示在屏幕的对应位置。为了有最好的体验,App帧率应尽量保证在60 FPS。
下图中Video Controller(本文中视频控制器) 非iOS UIKit 中的视图控制器,而是属于显卡的一部分。
如图所示的单缓冲模式,当电子束开始新一轮对帧缓冲的扫描的时候,GPU新一帧数据在电子束开始扫描时还没准备好,扫描到一半的时候GPU处理完了,更新了帧缓冲,此时屏幕将显示两帧的图像,出现撕裂现象。
iOS是如何解决这个问题的?
iOS 垂直同步 Vsync + 双缓冲机制 Double Buffering
当电子束完成一帧扫描将要开始新一轮扫描时,发出一个垂直同步信号Vsync。视频控制器接收Vsync会将指针切换到非当前的frame buffer
这个策略解决了屏幕撕裂的问题,但同时也引入了一个新问题:掉帧 Jank , 因为在收到Vsync时,CPU或GPU同样也有可能没有渲染好新位图,此时视频控制器不会去切换指针,两个周期将显示同样的画面。