离屏渲染
离屏渲染(offscreen-rendering)指的GPU在当前屏幕缓冲区以外开辟一个缓冲区进行渲染操作,渲染的结果不会直接呈现到当前屏幕上,而是等待何时的实际才会被显示。
正常情况下,GPU渲染完成后,就会将渲染好的图像放入帧缓存区中。屏幕根据它的刷新率(如:60Hz),从帧缓存区中扫描图片显示内容。
GPU如果无法完成一帧内更新的结果到帧缓存区,那么屏幕读取到的就是上一帧的内容,导致界面卡顿。
苹果对于页面流畅度的要求是非常苛刻的,所以引入了离屏渲染机制,触发比较消耗性能的视图提前渲染。
一直以来,以为离屏渲染不是一个很好的东西。当然那时候只是从网上看到不要消耗性能,尽量避免离屏渲染。现在感觉其实离屏渲染是把双刃剑,用对场景就是好;用不对场景当然不好喽
常见的几种触发离屏渲染的情况
1、使用了 mask 的 layer (layer.mask)
2、需要进行裁剪的 layer (layer.masksToBounds /view.clipsToBounds)
3、设置了组透明度为 YES,并且透明度不为 1 的layer (layer.allowsGroupOpacity/ layer.opacity)
4、添加了投影的 layer (layer.shadow*)
5、采用了光栅化的 layer (layer.shouldRasterize)
6、绘制了文字的 layer (UILabel, CATextLayer, Core Text 等)
触发原因
有两种触发离屏渲染的方式,分别是被动触发和主动触发。
主动触发的方式利用CALayer.shouldRasterize属性,开启光栅化。
光栅化是一个抽象概念,它的作用是强制 layer 以bitmap的形式进行缓存,等价于屏幕外的缓存,也属于离屏渲染的概念
被动触发的方式,都有一个共同的特性,就是包含透明度。几个带有透明度的视图叠在一块,中间重叠的那块需要GPU对他进行混合计算。如果这些视图是完全不透明的话直接显示最上面的视图,就不会有混合计算开销。
造成后果
离屏渲染需要在屏幕外开辟内存空间,提前使用CPU渲染复杂的视图,保证视频控制器能及时地从缓存区读取到新的渲染结果。它在GPU需要性能瓶颈,将压力转移一部分分给比较空闲的CPU,然而CPU渲染能力远没有GPU高效。这是一种空间换区时间的策略。
其次视屏控制器读取离屏渲染的结果时,需要将上下文环境切换到离屏缓存区,当腰显示非离屏数据时候又要换回来。这样的来回切换代价是非常昂贵的。
离屏渲染使用和注意事项
如果我们需要绘制一些复杂的、不会频繁发生变化,又重复出现的视图的时候,就可以利用离屏渲染来保证界面流畅度。利用 CALayer.shouldRasterize 开启光栅化,将离屏渲染的内容以位图的形式缓存,减少复杂视图频繁渲染的开销。
光栅化的建议:
1、如果layer不能被复用,则没必要打开;
2、如果layer不是静态的,需要被频繁修改,比如处于动画之中,那么开启离屏渲染反而影响效率了。
3、离屏渲染缓存内容有时间限制,缓存内容100ms内容入锅没有被使用,那么它就会丢弃;无法进行复用了。
4、离屏渲染缓存空间有限,超过2.5倍屏幕像素大小的话,也会失效,且无法进行复用了。
作者:洋蔥没有泪goodboy
链接://www.greatytc.com/p/2bc159848fdc
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
项目中如何检测离屏渲染
打开你的模拟器,在工作栏中选中debug->Color Off-screen Rendered。模拟器中就会出现如下图黄色区域块,说明这就是离屏渲染。
参考文章
//www.greatytc.com/p/24dac847cfc4