Android GPU渲染屏幕绘制显示基础概念(1)

Android GPU渲染屏幕绘制显示基础概念(1)

 

Android中的图像生产者OpenGL,Skia,Vulkan将绘制的数据存放在图像缓冲区中,Android中的图像消费SurfaceFlinger从图像缓冲区将数据取出,进行加工及合成。

SurfaceFlinger是Android最重要的图像消费者,Activity绘制的界面,都会传递到SurfaceFlinger,SurfaceFlinger的作用是接收图像缓冲区数据,然后交给HWComposer或者OpenGL做合成。

SurfaceFlinger是如何接收图像缓冲区的数据呢?先了解Layer(层)概念,一个Layer包含一个Surface,一个Surface对应一块图形缓冲区,而一个界面是由多个Surface组成的,所以它们会一一对应到SurfaceFlinger的Layer中。SurfaceFlinger通过读取Layer的缓冲数据,就相当于读取界面上Surface的图像数据。

f6311d4ad8a746239681165015c398af.webp

图像数据→CPU→显卡驱动→显卡(GPU)→显存(帧缓冲)→显示器

App绘制及SF的合成分别由对应的软件VSYNC驱动:VSYNC-app驱动App绘制;VSYNC-sf驱动SF进行合成。
VSYNC-app与VSYNC-sf按需发射,如果App要更新界面,它申请VSYNC-app,如果没有App申请VSYNC-app,那么VSYNC-app不发射。同样,当App更新界面,它会把对应的Graphic Buffer放到Buffer Queue中。Buffer Queue通知SF进行合成,此时SF申请VSYNC-sf。如果SF不申请VSYNC-sf,VSYNC-sf将不再发射。如果App持续不断的更新,它就得不断申请VSYNC-app;而对SF来说,只要有合成任务,它就得再去申请VSYNC-sf。Choreographer 可以接收系统的 VSYNC 信号,统一管理应用的输入、动画和绘制等任务的执行时机

VSYNC-app与VSYNC-sf相互独立。VSYNC-app触发App绘制,Vsync-sf触发SF合成。App绘制与SF合成都会加大CPU负载,为避免绘制与合成造成性能问题,VSYNC-app可与VSYNC-sf稍微错开。

  • Vsync offset机制: Vsync-app、Vsync-sf并不是同时通知的,Vsync-sf相对晚些,但对于App来说,可认为大约同时发生。

硬件VSYNC同步信号发送周期是固定的,既然都相互独立在自己进程里等待VSync信号到来,然后各司其职做自己的工作,那通过更改偏移量的方式把“APP进程”和“sf进程”接收到VSync信号的时间错开就可以实现:在一个硬件VSync信号周期内完成“渲染”和“合成”两件事,具体方案如下:

VSyncPhaseOffsetNs = 0,硬件VSync发生后,直接转发给app进程,让它开始绘制;
sfVSyncPhaseOffsetNs ≥1,硬件VSync发生后,延迟几毫秒再转发给sf进程,因为app已经渲染完成,sf合成刚刚渲染的图层;
好了,在一个硬件VSync周期(如熟知的16ms)内“渲染”和“合成”的工作都已经完成了,并且由于GPU性能过于快速,距离下次硬件VSync信号发送甚至还有14ms...等下一次硬件VSync信号到来时,显示框架完成,画面切换,和之前的方案比,同样是60HZ的屏幕,用户从按下按钮到看到画面更新,只需要等待1个VSync信号周期,也就是约16ms。

6f47c5129abf4a298fafadd2849a4ed9.png

SF合成的是App的上一帧,而App当前正在绘制的那一帧,要等到下一个VSYNC-sf来临再进行合成。Choreographer用于实现CPU/GPU的绘制是在VSYNC到来时开始。

GPU(Graphics Processin Unit,图形处理器),是一种专门用于图像运算的处理器,在计算机系统中通常被称为 "显卡"的核心部件就是 GPU。

2653b93885ae4a43a90f4d1569bb94d6.webp

 

UI 组件在绘制到屏幕之前,都需要经过 Rasterization(栅格化)操作,而栅格化又是一个非常耗时的操作。Rasterization 栅格化是绘制那些 Button、Shape、Path、String、Bitmap 等显示组件最基础的操作。栅格化将这些 UI 组件拆分到显示器的不同像素上进行显示。这是一个非常耗时的操作,GPU 的引入就是为了加快栅格化。

Android APP而言,GPU硬件加速绘制可以分为:

第一阶段:APP在UI线程构建渲染的命令及数据.
第二阶段:CPU将数据上传(共享或者拷贝)给GPU,PC一般有显存,但ARM嵌入式设备内存一般是GPU-CPU共享内存.
第三阶段:通知GPU渲染,CPU一般不会阻塞等待GPU渲染结束,效率低,CPU通知结束后就返回继续执行其他任务,Fence辅助GPU CPU同步.
第四阶段:swapBuffers,通知SurfaceFlinger图层合成.
第五阶段:SurfaceFlinger合成图层,如果之前提交的GPU渲染任务没结束,则等待GPU渲染完成,再合成(Fence机制),合成依然是依赖GPU,不过这作为下一个任务.

第一阶段主要是CPU工作,这个阶段前期运行在UI线程,后期部分运行在RenderThread(渲染线程),第二个阶段主要运行在渲染线程,CPU将数据同步(共享)给GPU,之后,GPU进行渲染,CPU一般不会阻塞等待GPU渲染完毕,而是通知结束后就返回。CPU返回后,会直接将GraphicBuffer提交给SurfaceFlinger,告诉SurfaceFlinger进行合成,但是这个时候GPU可能并未完成之前的图像渲染,这时候就牵扯到一个同步,Android中,用的是Fence机制,SurfaceFlinger合成前会查询Fence,如果GPU渲染没有结束,则等待GPU渲染结束,GPU结束后,会通知SurfaceFlinger进行合成,SF合成后,提交显示,最终完成图像的渲染显示。

a73dbc500b5b47a9a725f331471a47e3.webp

GraphicBuffer是整个图形系统的核心,渲染操作都将在此对象上进行,包括同步给GPU和HWC,每当应用有显示需求时,应用会向系统申请一块GraphicBuffer内存,这块内存将会共享给GPU用于渲染工作,接着会同步给HWC用于合成和显示,可以把每一个GraphicBuffer对象看做是一个个渲染完成的图层。

在Android里,GraphicBuffer的同步主要借助Fence同步机制,最大特点是能处理GPU、CPU、HWC的同步。GPU处理一般是异步的,CPU命令并不是即刻被GPU执行的,而是被缓存在缓冲区中,而CPU可能不知道执行时机,除非CPU阻塞等待,但毫无疑问会使CPU、GPU并行处理效率降低,至少,渲染线程是被阻塞,所以,CPU提交命令后就返回,不等待GPU处理。SurfaceFlinger图形合成,SurfaceFlinger需要知道什么时候GraphicBuffer被GPU处理填充完毕,这个时候就是Fence机制发挥作用的地方。

一个GraphicBuffer对象的生命周期:

渲染阶段:应用有绘图需求了,系统分配一块内存给应用,应用调用GPU执行绘图,此时使用者是GPU。
合成阶段:GPU渲染完成后将图层传递给sf进程,sf进程决定由谁来合成,hwc或者GPU,如果使用GPU合成,那么此时GraphicBuffer的使用者依旧是GPU,如果使用hwc合成,那么此时GraphicBuffer的使用者是hwc。
显示阶段:所有的GraphicBuffer在此阶段使用者都是hwc,因为hwc控制着显示芯片。
从生命周期可以看出GraphicBuffer对象在流转的过程中,会被GPU、CPU、DPU三个不同的硬件访问。如果同一块内存能够被多个硬件设备访问,就需要一个同步机制,Android图形系统中,Fence机制就是用来不同模块访问时的数据安全,Fence的逻辑实现可参考Java的synchronized互斥锁,可把Fence理解为一把硬件的互斥锁,每个需要访问GraphicBuffer的角色,在使用前都要检查这把锁是否unlock了才能进行操作,否则就要等待(waitForever)。

BufferQueue

它是一个封装了GraphicBuffer的队列,BufferQueue对外提供了GraphicBuffer对象出列/入列的接口。BufferQueue生产者/消费者模式,大多数情况,APP作为GraphicBuffer的生产者,sf进程作为GraphicBuffer的消费者,共同操作一个buffer队列。

生产者:APP进程

1、producer->dequeueBuffer()

​ 从队列取出一个状态为“FREE”的buffer,此时该buffer状态变化为:FREE->DEQUEUED

2、producer->queueBuffer()

​ 将渲染完成的buffer入列,此时该buffer状态变化为:DEQUEUED->QUEUED

消费者:sf进程

1、consumer->acquireBuffer()

​ 从队列中取出一个状态为“QUEUED”的渲染完的buffer准备去合成送显,此时该buffer的状态变化为:QUEUED->ACQUIRED

2、consumer->releaseBuffer()

​ buffer内容已经显示过了,可以重新入列给APP使用了,此时该buffer的状态变化为:ACQUIRED->FREE

每个Buffer的一生,就是在不断地循环FREE->DEQUEUED->QUEUED->ACQUIRED->FREE这个过程,这中间有任何一个环节出现延迟,反应到屏幕上就是应用出现了卡顿。

无论App使用哪种API进行图形开发绘制,在绘制流程结束后,APP作为图层的生产者总是会调用BufferQueue的queueBuffer()方法将GraphicBuffer入列,一旦有新的图层加入队列,就意味着作为图层消费者的SF进程可以开始工作了。

当APP端的Surface发生变化以后,Layer的onFrameAvailable()方法会被调用,经过层层转发,最终由MessageQueue#requestNextVSync()执行VSync信号的请求。
APP进程中的每一个Surface对象,对应SF进程当中的一个Layer对象,它俩共享一个BufferQueue,
Surface作为图层的生产者,封装了出列入列的操作,
Layer作为图层的消费者,封装了获取渲染图层和释放图层的操作。

 

一个APP完整的显示流程大致分为三个阶段
app-请求
APP页面元素一旦发生变化,调用invalidate()/requestLayout()方法请求下一次VSync信号,此时sf什么都不做。
app-VSync & sf-请求
app-VSync信号到来后,APP进程执行绘图三部曲,绘图流程结束后,sf收到onFrameAvailable(),sf进程请求VSync。
sf-VSync
sf-VSync信号到来,sf进程执行合成,接着将结果提交给hwc,等待下次硬件VSync信号发生,切换Framebuffer展示给用户。

 

 

 

 

Android性能:Double Buffer双缓冲/Triple Buffer三缓冲丢帧Jank与无丢帧No Jank-CSDN博客文章浏览阅读850次,点赞6次,收藏13次。Android ADB调试真机设备Android ADB(Andorid Debug Bridge),是Android开发中有用的测试和调试工具。使用Android ADB调试设备,直接在Windows的dos命令窗口输入命名adb即可,如图:为什么执行adb命令后是这样?_android 抓trace。三Buffer轮转情况下,基本不会有这种情况的发生,渲染线程一般在 dequeueBuffer 时,都可以顺利拿到可用的 Buffer (如果 dequeueBuffer 本身耗时那就也会拉长时间)。https://blog.csdn.net/zhangphil/article/details/138213964

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/9080.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenMVS学习笔记(一):WSL编译安装测试

1.CUDA和CUDNN安装 [1] WSL版本cuda安装: >> wget https://developer.download.nvidia.com/compute/cuda/repos/wsl-ubuntu/x86_64/cuda-wsl-ubuntu.pin >> sudo mv cuda-wsl-ubuntu.pin /etc/apt/preferences.d/cuda-repository-pin-600 >> wg…

Vue 数据校验

使用 插件 和 mixin进行数据校验 使用mixin 进行数据校验 <script>// plugin 插件 数据校验// 创建 vue实例const app Vue.createApp({data() {return{name:dell,age: 28}},methods: {handleClick() {this.show !this.show;}},// 数据校验 agerules: {age: {validat…

7个AI驱动的3D模型生成器

老子云AI生成3D模型https://www.laozicloud.com/aiModel 在快速发展的技术世界中&#xff0c;人工智能 (AI) 已经改变了游戏规则&#xff0c;尤其是在 3D 对象生成领域。 AI 驱动的 3D 对象生成器彻底改变了我们创建和可视化 3D 模型的方式&#xff0c;使该过程更加高效、准确…

Star-CCM+通过将所有部件创建一个区域的方式分配至区域后子区域的分离,子区域材料属性的赋值,以及物理连续体的创建方法介绍

前言 上次介绍了将零部件分配至区域的方法与各个方法之间的区别&#xff0c;本文将继续上次的讲解&#xff0c;将其中的“将所有部件分配至一个区域”的应用进行补充。 如下图所示&#xff0c;按照将所有部件创建一个区域的方式分配至区域后&#xff0c;在区域下就会有一个区域…

toB、toC、toD、B2B、C2C、O2O、B2C、P2P到底是什么?

toB、toC、toD到底是什么&#xff1f; toB&#xff08;Business&#xff09;&#xff1a;面向企业用户&#xff0c;例如OA办公系统 toC&#xff08;Consumer&#xff09;&#xff1a;主要是面向个人、客户&#xff0c;例如王者荣耀 toD&#xff08;Developer&#xff09;&…

WPF中ObservableCollection

在WPF&#xff08;Windows Presentation Foundation&#xff09;中&#xff0c;ObservableCollection<T> 是一个非常重要的类&#xff0c;它用于实现动态数据绑定功能。这个类位于 System.Collections.ObjectModel 命名空间中&#xff0c;是 ICollection<T>, IList…

初识微前端

微前端&#xff1a;微前端是一种软件架构模式&#xff0c;旨在解决大型前端应用程序开发和维护中的复杂性问题。它将前端应用程序拆分成更小的、独立的部分&#xff0c;每个部分可以由不同的团队开发、测试、部署和维护。这些独立的部分可以是单独的应用程序或者功能模块&#…

java:遍历目录文件

/*** 通过递归遍历目录下的所有内容&#xff0c;并把所有文件的绝对路径输出在控制台** 思路&#xff1a;* 1.根据给定的路径创建一个File对象* 2.定义一个方法&#xff0c;用于获取给定目录下所有内容&#xff0c;参数为第一步创建的file对象* 3.获取给定的File目录下的文件或…

若依集成mybatis-plus 超详细教程(亲测可用)

文章目录 简介步骤第一步第二步第三步第四步第五步第六步 使用QueryWrapperservice层impl 实现接口类层Mapper层 简介 话不多说 直接跟着下面的教程操作&#xff0c;如果有报错私信我&#xff0c;或者通过博文下面的微信名片加我微信&#xff0c;免费解答哦&#xff01; 步骤 …

代码随想录Day 42|Leetcode|Python|121. 买卖股票的最佳时机 ● 122.买卖股票的最佳时机II

121. 买卖股票的最佳时机 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 返回你可以从…

如何处理Django项目中表数据的排序问题

如何处理Django项目中表数据的按时间排序问题 当我们在写一些项目如购物平台 , 图书管理系统等都会不可避免的遇到排序问题 , 因为作者正在完成一个购物系统的项目 , 所以该文就以电商购物系统来举例说明 在utils文件夹中新建一个modle.py文件 , – utils文件夹主要存放一些非…

opencv图片的旋转-------c++

图片的旋转 /// <summary> /// 图片的旋转 /// </summary> /// <param name"img"></param> /// <param name"angle">旋转角度:正数&#xff0c;则表示逆时针旋转;负数&#xff0c;则表示顺时针旋转</param> /// <…

【吊打面试官系列】Java高并发篇 - 什么是线程调度器(Thread Scheduler)和时间分片(TimeSlicing )?

大家好&#xff0c;我是锋哥。今天分享关于 【什么是线程调度器(Thread Scheduler)和时间分片(TimeSlicing )&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; 什么是线程调度器(Thread Scheduler)和时间分片(TimeSlicing )&#xff1f; 线程调度器是一个操作系统…

深入理解nginx中的signal处理机制

1. 引言 在计算机系统中&#xff0c;信号处理是一项重要的任务&#xff0c;它允许操作系统和应用程序之间进行通信和协调。在网络服务器软件中&#xff0c;如Nginx&#xff0c;信号处理机制起着关键作用&#xff0c;它能够捕获和处理各种类型的信号&#xff0c;从而实现服务器的…

2024中国植物资源化妆品创新展在国家植物园成功举办

2024中国植物资源化妆品创新展&#xff08;简称国植美妆展&#xff09;于今年05月06日在北京国家植物园圆满落下帷幕。国植美妆展由中国广告协会化妆品工作委员会与中国抗衰老促进会化妆品产业分会指导&#xff0c;北京华晟德观文化科技发展有限公司主办&#xff0c;于03月30日…

安卓模拟器访问主机局域网

误打误撞能够访问主机局域网了 但是不太懂是因为哪一部分成功的 先记录一下 PC&#xff1a;mac系统 安卓编译器&#xff1a;Android Studio 步骤 只需要在PC上进行设置 1. 在【设置】中&#xff0c;打开已连接的Wi-Fi的【详细信息】 2. TCP/IP --> 配置IPv6&#xff0c;修…

前端组件库之ant-design-vue

在这里记录一个这个组件库我之前没有发现最近才发现的一个很好用的功能&#xff08;应该叫功能吧&#xff1f;&#xff09; 就是 这个flex弹性布局&#xff0c;之前在开发时&#xff0c;一直使用elementUI,是第一次使用这个组件库&#xff0c;所以没有发现这个功能这么好用 你…

第21天 反射

反射概述 想象一下&#xff0c;你在一个房间里边&#xff0c;但你看不见自己&#xff0c;也不知道自己是谁。这时候你面前有一个镜子&#xff0c;你可以通过镜子的反射来观察自己。反射就像这面镜子。它让你能够检查、分析、修改Java中的对象、类、方法等 使用情况&#xff1…

WPF控件之StackPanel布局控件

StackPanel别名堆栈panel 使其子元素按照一定方式进行布局&#xff0c;子元素排布方式要么设置为水平排布&#xff0c;要么垂直排布。 属性 Orientation设置排列方式(默认的是垂直排布) : Horizontal水平排布 Vertical 垂直排布 实例 <StackPanel Orientation"Vert…

视频号小店怎么做?店铺运营详细步骤讲解,全网独家

大家好&#xff0c;我是电商笨笨熊 视频号小店作为今年的电商黑马&#xff0c;下一个站在风口的项目&#xff0c;自是吸引了不少的玩家&#xff1b; 先不说视频号自身庞大的流量体系&#xff0c;单单是高客单的市场就值得尝试一把&#xff1b; 且当前视频号小店刚刚推出不久…