计算机渲染图片原理,iOS图像渲染原理解析

CPU和GPU

0e0b326dd6b970055dd50c25d960e6cb.png

从图中结构可以看出

CPU的处理单元少,由控制器和缓存单元,擅长处理复杂的逻辑以及数据结构,CPU中的并行其实是通过时间切片完成的。任务之间依赖性高,擅长逻辑控制

GPU是由许多计算单元组成,每个计算单元可以独立工作,任务之间依赖性低,擅长浮点运算,擅长并发计算

计算机渲染原理

⾼级光栅扫描显示系统结构

0d8fba201f50908e06f21e8587f9e802.png

屏幕扫描

视频控制器/显示控制器从帧缓冲区中读取图像信息(位图),经过数模转换(数字信号处->模拟型号)后通过逐行扫描把图像显示到显示器上的

f77fd464b039a914d1d23e3e918d2661.png

撕裂问题

显示一个完整画面是需要一定时间的,视频控制器在显示图像的过程中,如果这时候帧缓冲区的数据被刷新了,就会造成撕裂的问题,上面部分显示前面一帧的数据,下面部分为新的数据

3a776237a9656e422bb0d3d083ccfe2a.png

双缓冲区和垂直同步

为了解决撕裂,苹果引入了垂直同步(VSync) + 双缓存区(DoubleBuffering)来解决撕裂的问题(苹果使用的就是这个策略)

垂直同步Vsync:每隔1/60s就会发出一个信号,让GPU开始渲染图像,而这个时间间隔足够视频控制器显示图像了,App启动后,会在Runloop注册对应的CFRunLoopSource,通过mach_port,接受来自系统的Vsync事件(实际上是由硬件发出的,每秒钟发60次),CADisplayLink也是同样的原理

双缓存区 DoubleBuffering,使用两个帧缓冲区,视频控制器使用的帧缓冲区和GPU使用的分开,避免视频控制器正在使用的缓冲区被修改,避免撕裂问题,在GPU把帧数据写到帧缓冲区后,会和视频控制器使用的帧缓冲区进行交换,然后等待下一帧的渲染

87f8f12037a41348cdca1f4df6bbc0d7.png

掉帧

上面解决了撕裂的问题,但是还有一个掉帧的问题,如下图

0574188040bc0a5a0200ad9fa090c05b.png

当CPU和GPU渲染图像的时间过长,在下一个垂直同步信号来的时候,GPU并没有处理完一帧的数据,帧缓冲区也就没有交换,视频控制器就会显示原来缓冲区的内容

三缓冲区

从上图可以看出,CPU和GPU是在垂直同步信号到来的时候才开始渲染的工作,为了减少掉帧的情况,引入了三缓冲区

A:显示到屏幕

B:提前渲染号

C:正在渲染

其实相当于预加载,充分利用CPU和GPU的空闲时间,提前渲染好一帧B(同时也会带来画面延迟,当然1帧的延迟是可以接受的),多留出了一帧的时间,即使在渲染C的时候出现了一次掉帧,依然能刘畅渲染,这种情况大大减小了掉帧的可能

但如果渲染C的时间过长(掉多帧),依然会带来掉帧的问题,三缓冲区本质上并不解决掉帧的问题,只是缓解

为了解决掉帧的问题,我们只能尽可能优化我们的代码,减少CPU和GPU的渲染时间

iOS的渲染框架

渲染框架

f7948e33d81e6d34800868ee01d3fd6b.png

可以看到在iOS中的CoreGraphics, CoreAnimation, CoreImage都是通过OpenGL/Metal进行渲染的,我们的App也可以使用OpenGL/Metal来操作GPU进行渲染

CoreAnimation 渲染流⽔线

6828e4ba4b3d98143d96bfea0379fddd.png

CoreAnimation会在Runloop注册一个Observer监听触摸事件,当点击事件到来的时候,Runloop会被唤醒处理相关的业务逻辑(UIView的创建,修改,添加动画等)

最终会在CALayer通过CATransaction提交到RenderServer中,RenderServer会对图片进行解码,并等待下一个VSync的到来

VSync信号到来后,RenderService会通过OpenGL/Metal做一些绘制操作,然后把处理完的数据(纹理,顶点,着色器等)提交给GPU

GPU通过下面渲染流程程(顶点数据->顶点着⾊器->⽚元着⾊器),渲染到帧缓冲区,然后交换帧缓冲区(双缓冲区)

下一个VSync信号到来的时候,视频控制器读取帧缓冲区的数据显示到屏幕上

如果此处有动画,CoreAnimation会通过DisplayLink等机制多次触发相关流程

84c3fb4425af9c497a402dc396216175.png

渲染流程CPU阶段

布局(Frame): layoutSubviews, addSubview

显示(Core Graphics): drawRect, 绘制字符串

准备(QuartzCore/Core Animation):图片decode

提交:通过IPC提交(打包好的layers以及动画属性)给OpenGL/Metal,递归提交subview的layers

OpenGL ES/Metal阶段,主要是对图层进行取色,采样,生成纹理,绑定数据,生成前后帧缓存,为GPU渲染做准备

生成(Generate)

绑定(Bind)

缓存数据(Buffer Data)

启用(Enable)

设置指针(Set Pointers)

绘图(Draw)

清除(Delete)

GPU阶段

接收提交的纹理(Texture)和顶点描述(三角形)

应用变换(transform)

合并渲染(离屏渲染等)

参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值