iOS离屏渲染

源代码 2024-9-2 02:49:27 88 0 来自 中国
屏幕体现完整流程

1.jpg

团体渲染流程可以分为三个阶段:
1、CPU阶段: CPU的盘算重要是通过CoreAnimation来处理处罚,通过OpenGL ES/Metal将数据传递给GPU。
2、GPU阶段: GPU渲染重要是将吸收到的渲染数据举行一系列渲染之后将帧数据存储在帧缓存(Frame Buffer)内里,供视频控制器调用。
3、屏幕体现: 视频控制器从帧缓存中获取到帧数据体如今屏幕上。
屏幕体现图像原理

CRT体现器原理


4.jpg
CRT体现器原理重要是通过【电子束】引发屏幕表里貌的荧光粉来体现图像,由于荧光粉点亮后很快就会熄灭,以是【电子枪】须要不停的【从上到下】举行扫描,扫描完成后体现器就出现一帧画面,电子枪回到【初始位置】开始下一次的扫描。
程度同步信号:当电子枪换行扫描时会发出一个程度同步信号。
垂直同步信号:当一帧完成绘制后,电子枪规复到原来的位置预备扫描下一帧时体现器会发出一个垂直同步信号。
GPU渲染完成后将渲染结果存入帧缓存区,视频控制器根据【垂直同步信号】逐帧读取帧缓冲区的数据,颠末数据转换之后由体现器举行体现。
帧缓存(Frame Buffer)

1、屏幕革新频率
Refresh Rate,单位hz,指的是装备革新屏幕的频率,这个频率一样平常是60hz,以是每隔16.67ms屏幕会革新一次。
2、帧率
Frame Rate,单位fps,指的是GPU天生帧的速率。
3、帧缓存
也叫显存,它是屏幕所体现画面的一个直接映像,也叫做位映射图(bitmap)或光栅,帧缓存的每一存储单位对应屏幕上一个像素,整个帧缓存对应一帧图像。
理想环境下,屏幕革新频率和帧率完全同等,也就是说当屏幕体现完一帧的时候刚好下一帧画面也天生直接体如今屏幕上,但现实上这两个频率并不完全同等,为了办理这个题目,引入的【帧缓存】的概念。
图像扯破

图像扯破征象


缘故原由分析
当【帧率】大于【屏幕革新频率】时,当视频控制器刚读完一帧的上半部分时,GPU已经把下一帧预备好并提交到帧缓存,如许视频控制器就会读到下一帧的下半部分在屏幕体现。
办理方案
苹果使用的是【双缓存】和【垂直同步信号】。
垂直同步信号包管GPU的渲染只有等到体现器发出【垂直同步信号】之后才会举行下一帧的渲染。
双缓存包管体现器会交织读取两个缓存区的内容,相当于是拿空间换时间的一种策略。
利益在于

  • 不浪费CPU、GPU资源,包管提前渲染好的位图有一个缓存区来生存,如许GPU可以就可以举行下一帧的处理处罚。
  • 镌汰掉帧的出现。

    6.jpg
卡顿

当体现器的【垂直同步信号】发出的时候,GPU没有完成相应的渲染就会出现【卡顿】的征象,这也是为了办理画面扯破的题目带来的副作用,如下图所示:

7.jpg
增补

  • 掉帧指的是重复渲染同一帧数据而不是指某一帧丢掉了不渲染。
  • 为了镌汰【掉帧】的环境,有的会引入【三缓存】+【垂直同步信号】,好比安卓装备。
离屏渲染

什么是离屏渲染?

当GPU无法直接把渲染结果存放到帧缓存中,而是先是暂时把中心的一个暂时状态存放在别的的地区。之后再存放到帧缓存,这个过程叫离屏渲染。
便是说:GPU须要再当前屏幕缓存区以外开辟一个新的缓冲区举行利用。
缘故原由
GPU渲染采用的是【画家算法】,只能一层一层的输出,以是当一层不能直接天生图片的话就须要额外开辟新的缓冲区来存放这些暂时图层直到末了天生了一张完整的图片之后再写入帧缓存内里。
如下:

9.jpg 当前屏幕渲染和离屏渲染

离屏渲染的性能消耗

离屏渲染在当前屏幕缓冲区外新开辟一个缓冲区举行渲染利用,造成其性能消耗的重要缘故原由在于:创建离屏渲染和上下文切换。
切换上下文重要是当发生离屏渲染时,渲染上下文需从当前屏幕缓冲区切换到屏幕外缓冲区然后再完成渲染。
如果一屏元素都发生离屏渲染,这个从当前屏幕缓冲区切换到屏幕外的缓冲区就会发生多次,自然就会有肯定的性能消耗。
常见的离屏渲染场景

设置圆角

结论
满足以下条件的就会发生离屏渲染:

  • clipsToBounds开启,圆角 > 0,contents上有内容
  • 同时修改了contents+backgroundColor 或 contents+border(iOS9之后)
优化

  • 直接让UI提供带圆角的图片
  • 使用UIBezierPath和CAShapeLayer
  • 使用UIBezierPath和CoreGraphics
设置遮罩

12.jpg
设置遮罩的流程如下

  • 渲染layer的mask纹理
  • 渲染layer的content纹理
  • 归并利用:归并mask 和 content纹理
结论
满足以下条件的都会触发离屏渲染:
设置了mask + 恣意contents(好比设置UILabel笔墨、配景颜色、图片等)
设置阴影(shadow)

13.jpg
结论
阴影的本质和layer类似,都是在layer下一层多添加一层,根据前面提到的【画家算法】无法一次性天生,以是会发生离屏渲染。
优化
使用UIBezierPath给视图添加一个阴影路径,相当于提前告诉GPU这个阴影的多少形状,如许阴影就可以独立渲染。
光栅化(shouldRasterize)

光栅化
光栅化是一种缓存机制,开启后会缓存这个图片的bitmap,如果对应的layer和sublayers没有发生厘革,就可以直接使用缓存而不用GPU再举行渲染,从而进步性能。
注意
光栅化只能缓存100ms,而且只能存储屏幕巨细2.5倍的数据,缓存空间非常有限。
组不透明(allowsGroupOpacity)

allowsGroupOpacity
alpha并不是分别应用到每一层上,而是整个layer图层树完成之后,再同一加上alpha,然后和底下其他像素举行融合。
注意:
iOS7之后allowsGroupOpacity默以为YES,如许做的缘故原由是为了保持子视图和父视图保持同样的透明度。
allowsGroupOpacity触发离屏渲染的条件

  • 当视图上有其他子视图
  • 视图View的alpha值在0 ~ 1之间
  • 视图view.layer.allowsGroupOpacity = YES
总结

离屏渲染的处理处罚仅仅是我们日常所关注的性能中的此中一个点,在处理处罚的时候也要根据具体场景具体分析,要注意并不是所有的离屏渲染都是必须要去制止的,开辟额外的帧缓存固然有肯定的性能消耗,但是生存渲染结果并举行终极的视图体现也是为了保持视图的流通性。
更多技能文章接待移步Sunny的个人技能博客。
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-11-21 21:09, Processed in 0.150726 second(s), 35 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表