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

news/2024/5/21 2:21:07

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.mrgr.cn/p/78280063

相关文章

开源RAG框架汇总

前言 本文搜集了一些开源的基于LLM的RAG(Retrieval-Augmented Generation)框架,旨在吸纳业界最新的RAG应用方法与思路。如有错误或者意见可以提出,同时也欢迎大家把自己常用而这里未列出的框架贡献出来,感谢~ RAG应用框架RAGFlow项目地址:https://github.com/infiniflow/…

kali中arp欺骗,连上校园网断舍友的网

首先kali的配置: 参考网站:https://jingyan.baidu.com/article/2c8c281d145cf44108252a97.html 然后下载arpspoof插件: apt-get install dsniff然后一条命令: arpspoof -i eth0 -t 受害者的ip 网关//这个网关是你自己连上校园网的那个网关

Scrum冲刺4--5.10

Scrum冲刺4--5.10这个作业属于哪个课程 软件工程这个作业要求在哪里 团队项目这个作业的目标 进行敏捷冲刺,熟悉团队合作开发前端仓库 前端后端仓库 后端每次冲刺日志索引时间 博客5.7 Day1ᕙ(`▿)ᕗ5.8 Day2ᕙ(• ॒ ູ•)ᕘ5.9 Day3(˚ ˃̣̣̥᷄⌓˂̣̣̥᷅ )5.10 Day4 (…

Navicat Data Modeler Ess for Mac:强大的数据库建模设计软件

Navicat Data Modeler Ess for Mac是一款专为Mac用户设计的数据库建模与设计工具,凭借其强大的功能和直观的界面,帮助用户轻松构建和管理复杂的数据库模型。 Navicat Data Modeler Ess for Mac v3.3.17中文直装版下载 这款软件支持多种数据库系统&#x…

敏捷冲刺day3--数字工匠队

这个作业属于哪个课程 软件工程这个作业的要求是什么 项目冲刺这个作业的目标 冲刺日志3站立式会议照片工作困难 处理任务时遇到一些问题需要上网学习花费时间 昨日完成工作 部分登录界面前后端处理代码 今日计划工作 继续完成登录界面前后端处理 项目燃尽图每日总结 邹嘉伟:继…

中国地面气候资料日值数据获取方式

数据简介 环境气象数据服务平台提供了全国大约2100个点位,2000年至2023年的逐日数据。包括气温、气压、湿度、风、降水等要素。 数据基于ECMWF reanalysis-era5-land、reanalysis-era5-single-levels 以及中国2100站点地面气候资料日值观测数据,使用机器…

第 3 篇 Scrum 冲刺博客

每天举行站立式会议 昨天已完成的工作: 今天计划完成的工作: 工作中遇到的困难: 项目燃尽图代码/文档签入记录项目展示每日每人总结 李健宇:明天加油。 陈彦煤:尽力完成,克服困难。

如何使用client-go构建pod web shell

代码示例及原理 原理是利用websocket协议实现对pod的exec登录,利用client-go构造与远程apiserver的长连接,将对pod容器的输入和pod容器的输出重定向到我们的io方法中,从而实现浏览器端的虚拟终端的效果消息体结构如下 type Connection stru…

【c++算法篇】双指针(下)

🔥个人主页:Quitecoder 🔥专栏:算法笔记仓 朋友们大家好啊,本篇文章我们来到算法的双指针的第二部分 目录 1.有效三角形的个数2.查找总价格为目标值的两个商品3.三数之和4.四数之和5.双指针常见场景总结 1.有效三角形…

移动机器人系统与技术:自动驾驶、移动机器人、旋翼无人机

这本书全面介绍了机器人车辆的技术。它介绍了道路上自动驾驶汽车所需的概念。此外,读者可以在六足机器人的构造、编程和控制方面获得宝贵的知识。 这本书还介绍了几种不同类型旋翼无人机的控制器和空气动力学。它包括各种旋翼推进飞行器在不同空气动力学环境下的模…

ThreeJS:本地部署官网文档与案例

部署方式 部署之前请确保已经配置好node.js环境。 1. 下载ThreeJS源码 ThreeJS的GitHub地址:GitHub - mrdoob/three.js: JavaScript 3D Library.,可以简单查看ThreeJS当前版本:r164, 我们可以选择对应的版本(此处为r1…

10秒以上无错误!猫态量子比特稳定性达到新水平

内容来源:量子前哨(ID:Qforepost) 文丨 浪味仙 排版丨沛贤 深度好文:1200字丨5分钟阅读 摘要:与涉及超导电路的其他量子比特设计相比,使用猫态量子比特可能会“将用于纠错的量子比特数量减少到…

SpringBoot整合Mybatis时mapper文件和xml文件的位置

xml文件放在resources下看下我的项目目录2.由于放在resurces下就无法扫描到xml文件,所以就需要在配置文件配置--mapper文件位置 mybatis.mapper-locations=classpath:mapper/*.xml 或 mybatis.mapper-locations=classpath:/mapper/*.xmlxml和mapper文件放在一起我的项目目录但…

Flume进阶

目录 第1关:拦截器的使用 第2关:自定义拦截器 第1关:拦截器的使用 代码文件: # Define source, channel, sink #agent名称为a1# Define source #source类型配置为avro,监听8888端口,后台会自动发送数据到该端口 #拦截后…

论文阅读:《Sequence can Secretly Tell You What to Discard》,减少推理阶段的 kv cache

目前各类大模型都支持长文本,例如 kimi chat 以及 gemini pro,都支持 100K 以及更高的上下文长度。但越长的上下文,在推理过程中需要存储的 kv cache 也越多。假设,数据的批次用 b 表示,输入序列的长度仍然用 s 表示&a…

聚观早报 | 苹果新款iPad Pro发布;国产特斯拉4月交付量

聚观早报每日整理最值得关注的行业重点事件,帮助大家及时了解最新行业动态,每日读报,就读聚观365资讯简报。 整理丨Cutie 5月9日消息 苹果新款iPad Pro发布 国产特斯拉4月交付量 iOS 18新功能爆料 真我GT Neo6续航细节 三星Galaxy Z F…

#Scurm冲刺第五天

Scurm冲刺第五天 1. 站立式会议内容昨日已完成任务 今日计划完成任务前端UI设计代码编写(收藏页面,商品详情页,个人中心页) 前端UI设计代码编写(购物车页面,订单页面,订单详情页,搜索后商品展示页),前端界面合理跳转功能实现后端管理员模块功能实现(登录注册功能,用户…

m1_day7

课程内容:数组的排序引用数据类型的数组面向对象封装继承多态数组的排序:手动排序 冒泡排序 *自动排序Arrays.sort(数组对象);只能升序排序import java.util.*;引用数据类型的数组:当我们创建一个引用数据类型的数组的时候 其实里面一个对象都没有 里面都是默认值null 为了防…

数据分析:基于sparcc的co-occurrence网络

介绍 Sparcc是基于16s或metagenomics数据等计算组成数据之间关联关系的算法。通常使用count matrix数据。 安装Sparcc软件 git clone gitgithub.com:JCSzamosi/SparCC3.git export PATH/path/SparCC3:$PATHwhich SparCC.py导入数据 注:使用rarefy抽平的count ma…

『先进技术助力』Kompas AI:智能AI代理在工作中的应用与效率提升

『智能化未来』Kompas AI如何改变我们的工作方式? 在这个信息时代,利用AI聊天机器人来处理机械性的工作已经成为一种趋势。ChatGPT作为一种智能助手,不仅能够提高工作效率,还可以帮助我们更明智地做出决策,从而释放出更…