本篇对计算机图形渲染原理及iOS的渲染原理进行简要介绍
CPU & GPU
可视化应用程序都是由 CPU 和 GPU 协作执行的。
- CPU
Central Processing Unit,现代计算机的三大核心部分之一,作为整个系统的运算和控制单元。
CPU 内部的流水线结构使其拥有一定程度的并行计算能力。(多核切换)
CPU 可以处理逻辑复杂,依赖性高的数据运算。
- GPU
Graphics Processing Unit,一种可进行绘图运算工作的专用微处理器。
GPU是连接计算机和显示终端的纽带。
GPU 能够生成 2D/3D 的图形图像和视频,从而能够支持基于窗口的操作系统、图形用户界面、视频游戏、可视化图像应用和视频播放。
GPU 具有非常强的并行计算能力。
GPU 处理高并发,依赖性低的逻辑运算。
GPU 强大的并行计算能力使其能够快速将图形结果计算出来并在屏幕的所有像素中进行显示。所以,通常使用 GPU 来渲染图形。
屏幕图像显示原理
光栅扫描
- 逐行扫描
CRT 显示器的电子枪从上到下逐行扫描,扫描完成后显示器就呈现一帧画面。然后电子枪回到初始位置进行下一次扫描。
- 同步信号
为了同步显示器的显示过程和系统的视频控制器,显示器会用硬件时钟产生一系列的定时信号。
- HSync
当电子枪换行进行扫描时,显示器会发出一个
水平同步信号
(horizonal synchronization)。
- VSync
而当一帧画面绘制完成后,电子枪回复到原位,准备画下一帧前,显示器会发出一个
垂直同步信号
(vertical synchronization)。
显示器通常以固定频率进行刷新,这个刷新率就是 VSync 信号产生的频率。
现在主流的液晶显示屏其原理与上述基本一致。
图像显示
- CPU 将图片解码计算后 经由系统总线 (Bus) 提交至 GPU;
- GPU 渲染完成后将渲染结果存入帧缓冲区 (Frame Buffer);
- 视频控制器(Video Controller)会按照 VSync 信号逐帧读取帧缓冲区的数据(位图),并刷新部件;
- 经过数据转换后最终由显示器进行逐行扫描显示。
- 帧缓冲区
简称帧缓存或显存,它是屏幕所显示画面的一个直接映象,又称为位映射图(Bit Map)或光栅。
帧缓冲区 是由像素组成的二维数组,每一个存储单元对应屏幕上的一个像素,整个帧缓冲对应一帧图像,即当前屏幕画面。
帧缓冲通常包括:颜色缓冲,深度缓冲,模板缓冲和累积缓冲。
这些缓冲区可能是在一块内存区域,也可能单独分开。
- 视频控制器
图像撕裂
在渲染过程中,当视频控制器还未读取完成时,即屏幕内容刚显示一半时,GPU 将新的一帧内容提交到帧缓冲区并把两个缓冲区进行交换后,视频控制器就会把新的一帧数据的下半段显示到屏幕上,造成画面撕裂,出现断层。
撕裂现象 在于视频控制器显示速度小于GPU处理图形的速度。
在显示器处理显卡丢过来的第1帧的时候,第2帧又到了,导致同一个画面同时出现1、2两帧,撕裂就产生了。
解决图像撕裂
- 垂直同步(VSync)
前面讲到 显示器通常以VSync 信号产生的固定频率进行刷新。
即垂直同步相当于加锁。
当开启垂直同步后,GPU 会等待显示器的 VSync 信号发出后,才进行新的一帧渲染和缓冲区更新。
- 双缓冲机制(DoubleBuffering)
为解决帧缓冲区读取和刷新的效率问题,GPU 开辟A/B两个帧缓冲区,一个缓冲区通过视频控制器进行当前帧数据的读取显示,另一个缓冲区进行接收下一帧GPU渲染的图像。两个缓冲区都执行结束,然后再交换缓冲区。
当A帧缓冲区拿到第一帧数据,给A缓冲区加上一把锁,屏幕控制器从A拿到数据并逐行扫描完成,A帧缓冲区解锁,并且屏幕控制器指向B帧缓冲区,B帧缓冲区加锁并逐行扫描显示,在屏幕控制器扫描B帧缓冲区的时候,A帧缓冲区拿到GPU传过来的新一帧数据,以此类推,解决撕裂问题。
通过垂直同步+双缓冲机制,能解决画面撕裂现象,但需要消费更多的计算资源,也会带来部分延迟,出现掉帧/卡顿问题。
掉帧/卡顿
每帧画面的处理时间大概在16.7ms(1s/60 ≈16.7ms),当超过这个时间就会出现掉帧现象。
当接收接收Vsync ,由于cpu/gpu图⽚数据(速度大于了16.7ms) -> 拿不到FrameBuffer ->这个时候屏幕控制器只能显示同一帧的数据,即: 掉帧(重复渲染同⼀帧数据)。
三级缓存区
为减少掉帧现象,引入三级缓存区,在双缓冲区的基础上再添加一个缓冲区,提高交换速率,减少卡顿。
三级缓冲区是为了充分利用CPU/GPU的空余时间。
注意:三级缓冲区也有可能出现掉帧,并不能完全解决掉帧,只是尽量减少掉帧现象。