什么是离屏渲染?
离屏渲染(offscreen-rendering)顾名思义为屏幕外的渲染,即渲染的结果不会直接呈现到当前屏幕上,而是等待合适的时机才会被显示。
正常情况下,在当前屏幕显示的内容,由 GPU 渲染完成后放到当前屏幕的帧缓存区,不需要额外的渲染空间。
假如 GPU 因为面临一些限制,无法把渲染结果直接写入frame buffer,而是先暂存在另外的内存区域,之后再写入frame buffer,那么这个过程被称之为离屏渲染。
离屏渲染的过程
通常的渲染流程是这样的
在正常情况下,经过CPU的计算以及GPU的渲染之后,不停地将内容渲染完成放入Frame Buffer
中帧缓存区,随后视频控制器会读取帧缓存区的数据,经过数模转换,再逐行显示到屏幕上
出现离屏渲染的渲染流程:
与普通情况下 GPU 直接将渲染好的内容放入Frame Buffer
中不同,在某些特殊情况下,需要先额外创建离屏渲染缓冲区 offscreen Buffer
,将提前渲染好的内容放入其中,等到合适的时机再将 offscreen Buffer 中的内容进一步叠加、渲染,最后将结果切换到 Frame Buffer 中。
离屏渲染的利弊
优势
- 特殊的渲染效果:使用额外的离屏缓冲区(offscreen butter)保存中间状态,最后叠加、处理后绘制在屏幕上,这样就不得不使用离屏渲染
- 效率优势:需要多次使用的效果,提前渲染存入离屏缓冲区,然后复用来提高效率。
劣势
- 内存开支:开辟离屏缓冲区(大小不超过2.5倍屏幕像素大小)
- 时间和性能开支:从离屏缓冲区拷贝数据到帧缓冲区,上下文切换耗性能,容易出现掉帧的情况
常见的触发离屏渲染的情况
- 使用了 mask 的 layer (layer.mask)
- 需要进行裁剪的 layer (layer.masksToBounds /view.clipsToBounds)
- 设置了组透明度为 YES,并且透明度不为 1 的layer (layer.allowsGroupOpacity/ layer.opacity)
- 添加了投影的 layer (layer.shadow*)
- 采用了光栅化的 layer (layer.shouldRasterize)
不过使用光栅化的时候需要注意以下几点:
- 如果layer不能被复用,则不必打开光栅化
- 如果layer不是静态的,需要被频繁修改,如处于动画中,那开启离屏渲染反而会影响效率
- 离屏渲染缓存内容有时间限制,缓存内容100ms内没有被使用,那么它就会丢弃,无法进行复用了
- 离屏渲染缓存空间有限,不能超过2.5倍屏幕像素大小
- 绘制了文字的 layer (UILabel, CATextLayer, Core Text 等)