美文网首页
渲染和iOS的离屏渲染

渲染和iOS的离屏渲染

作者: 那些喧嚣 | 来源:发表于2020-07-08 16:43 被阅读0次

iOS下的渲染流程

1.png

知识点:

  • 整个渲染流程,可以分为OpenGL client(客户端)和OpenGL server(服务端)
  • client是在CPU里面执行,不断的驱动数据传递给server
  • server是在GPU里面执行,直接操作GPU绘制图形
  • Vertex Shader(顶点着色器),由client从三个通道:Attributes(ins)、Uniforms、Texture Data将数据传递进来
  • Fragment Shader(片元着色器),由client从两个通道:Uniforms、Texture Data传递数据进来,Attribute只能通过定点着色器传递进来
  • 顶点着色器不能直接操作片元着色器,需要由顶点着色器输出数据(开发者无法干涉)到下一个阶段(Primitive Assembly:图元装配/光栅化),将数据拷贝到着色器中
  • render 渲染图形

离屏渲染

On-Screen Rendering (当前屏幕渲染)

  • GPU的渲染操作是在当前用于显示的屏幕缓冲区进行

Off-Screen Rendering (离屏渲染)

  • GPU在当前屏幕缓冲区以外开辟的一个缓冲区进行渲染操作

Off-Screen Rendering 和 On-Screen Rendering的比较

  • 创建新的缓冲区
  • 上下文切换,即:从当前屏幕切换到离屏,离屏渲染结束后,讲渲染结果显示到屏幕上,需要将上下文环境从离屏切换到当屏(更耗性能)

触发离屏渲染的方式

主要出现在处理图层操作较多的情况下会发生离屏渲染(以下包含不仅限于)

1、layer的mask

2、layer的投影(layer.Shadow)

3、layer的光栅化(layer.ShouldRasterize)

4、layer.masksToBounds = true 可能会产生离屏渲染

  • 打开该属性,如果只设置了背景色或者图片,也不会产生离屏渲染,即:图层只有一层时,不触发离屏渲染
func demo1() {
        /// 设置了背景色+圆角:无离屏渲染
        let imgView1 = UIImageView.init(frame: CGRect(x: 30, y: 80, width: 100, height: 100))
        imgView1.backgroundColor = .gray
        imgView1.layer.cornerRadius = 10
        view.addSubview(imgView1)
        
        /// 设置了背景色+圆角+图片:无离谱渲染
        /// 打开masksToBounds属性:出现离谱渲染
        let imgView2 = UIImageView.init(frame: CGRect(x: 30, y: 200, width: 100, height: 100))
        imgView2.layer.masksToBounds = true
        imgView2.image = UIImage.init(named: "user_image")
        imgView2.layer.cornerRadius = 10
        imgView2.backgroundColor = .gray
        view.addSubview(imgView2)
        
        /// 设置了背景色+圆角+多张只设置背景色叠加:无离谱渲染
        /// 设置了背景色+图片+圆角+多张设置背景色+图片叠加:无离谱渲染
        /// 打开masksToBounds属性:出现离谱渲染
        let imgView3 = UIImageView.init(frame: CGRect(x: 30, y: 320, width: 100, height: 100))
        imgView3.layer.cornerRadius = 10
        imgView3.image = UIImage.init(named: "user_image")
        imgView3.backgroundColor = .gray
        view.addSubview(imgView3)
        
        let imgView3_1 = UIImageView.init(frame: CGRect(x: 0, y: 0, width: 80, height: 80))
        imgView3_1.backgroundColor = .red
        imgView3_1.image = UIImage.init(named: "user_image")
        imgView3.addSubview(imgView3_1)
        
        let imgView3_2 = UIImageView.init(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
        imgView3_2.backgroundColor = .green
        imgView3_2.image = UIImage.init(named: "user_image")
        imgView3_1.addSubview(imgView3_2)
        
        let imgView3_3 = UIImageView.init(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
        imgView3_3.backgroundColor = .blue
        imgView3_3.image = UIImage.init(named: "user_image")
        imgView3_2.addSubview(imgView3_3)
    }
    
    func demo2() {
        /// 设置了图片+圆角:无离屏渲染
        let imgView1 = UIImageView.init(frame: CGRect(x: 30, y: 80, width: 100, height: 100))
        imgView1.image = UIImage.init(named: "user_image")
        imgView1.layer.cornerRadius = 10
        view.addSubview(imgView1)
        
        /// 设置了圆角+图片:无离谱渲染
        /// 只设置图片,不设置背景色,打开masksToBounds属性:无离谱渲染
        /// 设置图片,设置背景色,打开masksToBounds属性:出现离谱渲染
        let imgView2 = UIImageView.init(frame: CGRect(x: 30, y: 200, width: 100, height: 100))
        imgView2.layer.masksToBounds = true
        imgView2.backgroundColor = .blue
        imgView2.image = UIImage.init(named: "user_image")
        imgView2.layer.cornerRadius = 80
        view.addSubview(imgView2)
        
        /// 设置了圆角+多张只设置图片叠加:无离谱渲染
        /// 设置了图片+圆角+多张图片叠加:无离谱渲染
        /// 打开masksToBounds属性:出现离谱渲染
        let imgView3 = UIImageView.init(frame: CGRect(x: 30, y: 320, width: 100, height: 100))
        imgView3.layer.cornerRadius = 10
        imgView3.image = UIImage.init(named: "user_image")
        view.addSubview(imgView3)
        
        let imgView3_1 = UIImageView.init(frame: CGRect(x: 0, y: 0, width: 80, height: 80))
        imgView3_1.image = UIImage.init(named: "user_image")
        imgView3.addSubview(imgView3_1)
        
        let imgView3_2 = UIImageView.init(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
        imgView3_2.image = UIImage.init(named: "user_image")
        imgView3_1.addSubview(imgView3_2)
        
        let imgView3_3 = UIImageView.init(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
        imgView3_3.image = UIImage.init(named: "user_image")
        imgView3_2.addSubview(imgView3_3)
    }
  • 使用了mask的layer(layer.mask)
  • masksToBounds

卡顿产生的原因和解决方案

从上述的一些知识点可知,屏幕产生卡顿的原因,主要还是在CPU和GPU上。
接下来我们看下显示过程:


26.jpg

在VSync信号到来后,系统图形服务会通过CADisplayLink等机制通知APP,APP主线程再CPU中计算显示内容,如计算布局、图片解码、文本绘制等。CPU计算好的内容再提交到GPU中,由GPU进行交换、合成、渲染。然后GPU就把结果提交到帧缓冲区,等待下一次VSync信号到来时显示到屏幕上。由于垂直同步的机制,如果再一个Vsync时间内,CPU或者GPU没有完成内容提交,则那一帧就会丢失,等待下一次机会在显示,而这个时候显示屏会保留之前的内容不变。这就是界面的卡顿原因。

从上图可以看到,无论是CPU还是GPU,只要有阻碍,都会造成掉帧现象。所以开发时,也需要分别对CPU和GPU进行评测。


相关文章

  • iOS离屏渲染的检测和优化

    在iOS离屏渲染介绍了离屏渲染的逻辑和原理,我们知道离屏渲染对于性能会有较大的消耗,那么开发中怎么避免产生离屏渲染...

  • iOS离屏渲染

    iOS-离屏渲染详解关于iOS离屏渲染的深入研究关于离屏渲染这两片文章分析的很详细。 渲染过程 根据渲染流水线示意...

  • 三、iOS离屏渲染

    iOS离屏渲染 圆角不一定会造成离屏渲染 GPU屏幕渲染方式 On-Screen Rendering 当前屏幕渲染...

  • iOS圆角的离屏渲染,你真的弄明白了吗

    iOS圆角的离屏渲染,你真的弄明白了吗iOS圆角的离屏渲染,你真的弄明白了吗

  • iOS离屏渲染解析

    iOS离屏渲染解析

  • iOS-离屏渲染探索

    iOS项目性能优化时,不得不提到离屏渲染,为了提升性能,我们要求尽量减少离屏渲染的发生。 那,什么是离屏渲染?离屏...

  • iOS离屏渲染相关值得看的博客

    博客链接 iOS离屏渲染优化 绘制像素到屏幕上 关于iOS离屏渲染的深入研究 https://texturegro...

  • UI视图及UITableView流畅性优化

    一.离屏渲染 1. 在屏渲染和离屏渲染 在屏渲染是指在当前用于显示的屏幕缓冲区进行GPU渲染操作 离屏渲染是指在当...

  • 关于UIImageView和UIView 圆角、阴影离屏渲染相关

    iOS圆角和阴影,离屏渲染相关文章的整理以下是否会造成离屏渲染的结果于 Simulator 勾选 Color Of...

  • 离屏渲染

    离屏渲染是在iOS开发过程中脱离不了的话题,那么什么是离屏渲染以及哪些情况会导致离屏渲染呢?以及离谱渲染有哪些优势...

网友评论

      本文标题:渲染和iOS的离屏渲染

      本文链接:https://www.haomeiwen.com/subject/rpbccktx.html