搜索
简帛阁>技术文章>iOS 渲染

iOS 渲染

https://xiaozhuanlan.com/topic/9273604158

先来张渲染的流程图:

这张图其实有很多误导,我的更改如下:

可以看到整个流程是一个pipeline(一次pipeline要跨越三帧)形式的,下面对每个步骤都做一个解释:

1.Handle Events: 处理事件,比如点击事件,这个过程中有可能会需要改变页面的布局和界面层次。(在runloop层面看,就是唤醒runloop,比如source1/0、定时事件等,然后经过一轮或多轮runloop后,就到了beforeWaiting的observers监听事件了,也就下面的2部分执行的内容


2.Commit Transaction: 此时 app 会通过CPU 处理显示内容的前置计算,比如布局计算、图片解码等任务,接下来会进行详细的讲解。之后将计算好的图层进行打包(这里的打包其实就是Encode编码,所以对应了下面的Decode解码)发给 Render Server (这一步对应到代码就是CA::Transaction:commit(),里面会调用UIView的layoutSubviews和CALayer的displayLayer等方法,具体可见我的另一篇博客为什么说重写了drawRect:后会增加内存开销


3.Decode: 打包好的图层被传输到 Render Server 之后,首先会进行解码。注意完成解码完并没有直接 Draw Calls(这里的Calls是指call openGL/Metal),这是有目的的下面会讲


4.Draw Calls: 渲染服务器必须等待下一次重新同步,以便等待缓冲区从 它们实现渲染的显示器 返回,然后最终开始为 GPU 绘制,这里调用的是 OpenGL or metal接口。这里和iOS的双缓冲机制相辅相成,Draw Calls 并不会在 Decode结束就马上进行,而是等上一帧显示完成了、buffer空出来了再调用openGL/Metal来在空出的buffer里渲染,此时显示器显示另一个buffer里的内容


5.Render:这一阶段主要由 GPU 进行渲染(渲染成bitmap,存放在render buffer


6.Display:显示阶段,需要等 render 结束的下一个 RunLoop 触发显示

  1. 上面有一点值得注意的是,正常渲染过程是在GPU中进行的,CPU只是在第2步提供好了图元信息(也就是每个CALayer的位置、大小、父子Layer的关系等);而如果重写drawRect等代理,渲染会在CPU进行,同时还会另外申请一块backing strore同等大小的内存
  2. 注意:重写drawRect在CPU中进行渲染在一些博客中也称为离屏渲染,这个我认为是不准确的,行业普遍认为的离屏渲染是在GPU中渲染的,注意这个术语问题。打开Xcode模拟器的“Color Offscreen rendered Yellow”,可以看到即使是重写了drawRect:方法的View也不会标黄

上面3、4、5步骤的详细流程在下面这个图:

这里顺便提下用户卡顿感知的原因:

首先人眼能够感觉到流畅的最低要求是24帧,当然帧率越高人眼感知的流畅读越高(这里有兴趣可以看下这篇文章的介绍),理论上iOS刷新率是60Hz,完全能保持流畅。但当Display显示屏显示一个render buffer 16.67ms后,由于双缓冲机制会转而去显示另一个render buffer,但可能由于其他步骤(比如Handle Events等)卡了一段时间,导致这个render buffer还没有被GPU更新,所以这一帧的内容没有变化,用户的感知就是卡住了。

动画渲染

动画渲染流程:

关于动画有个优化,应用程序一次性把动画参数打包给Render进程,然后Render进程一帧一帧渲染,这里优化了应用程序和Render Server之间的多次进程间通信的消耗

参考文章

我网上关于iOS渲染的博客看的挺多了,但是内容都比较同质化,下面的链接是我认为有自己想法的博客

    1. https://joakimliu.github.io/2019/03/02/wwdc-2014-419/
    2. https://zhuanlan.zhihu.com/p/72653360
       
https://xiaozhuanlancom/topic/9273604158先来张渲染的流程图:这张图其实有很多误导,我的更改如下:可以看到整个流程是一个pipeline(一次pipeline要跨
GPU屏幕渲染有以下两种方式:OnScreenRendering意为当前屏幕渲染,指的是GPU的渲染操作是在当前用于显示的屏幕缓冲区中进行。OffScreenRendering意为离屏渲染,指的是G
iOS控件设置圆角,避免离屏渲染。离屏渲染:指GPU(图形处理器)在当前屏幕缓冲区外新开辟一个渲染缓冲区进行工作。这会给我们带来额外的性能损耗,如果这样的操作达到一定数量,会触发缓冲区的频繁合并和上
2屏幕成像与卡顿在图像渲染流程结束之后,接下来就需要将得到的像素信息显示在物理屏幕上了。GPU最后一步渲染结束之后像素信息,被存在帧缓冲器(Framebuffer)中,之后视频控制器(VideoCon
前言APP页面优化对小编来说一直是难题,最近一直在不断的学习和总结,发现APP页面优化说到底离不开view的绘制和渲染机制。本文将详细给大家介绍关于iOS布局渲染之UIView方法调用时机的相关内容,
给图片增加滤镜有这两种方式:CoreImage/openGLES下面先说明如何使用CoreImage给图片添加滤镜,主要为以下步骤:1导入CIImage格式的原始图片2创建CIFilter滤镜3用CI
pp1{margin:0;font:14pxMenlo;color:rgba(0,132,0,1);backgroundcolor:rgba(255,255,255,1)}pp2{margin:0;f
前言本文主要给大家介绍了关于iOS图片压缩、滤镜、剪切及渲染的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧主要内容:1、图片基础知识的介绍2、图片压缩简单的回顾一下从相册获
iOS给图片添加滤镜使用openGLES动态渲染图片给图片增加滤镜有这两种方式:CoreImage/openGLES下面先说明如何使用CoreImage给图片添加滤镜,主要为以下步骤:1导入CIIma
iOSwebsocket最近在开发一个直播应用,需要用到弹幕功能,后台说要用websocket来实现,所以学习了一下一、RocketSocket搜索了一下发现,用的最多的还是Facebook的Rock