Android GPU渲染SurfaceFlinger合成RenderThread的dequeueBuffer/queueBuffer与fence机制(2)

本文主要是介绍Android GPU渲染SurfaceFlinger合成RenderThread的dequeueBuffer/queueBuffer与fence机制(2),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Android GPU渲染SurfaceFlinger合成RenderThread的dequeueBuffer/queueBuffer与fence机制(2)

 

计算fps帧率

adb shell dumpsys SurfaceFlinger --list

查询当前的SurfaceView,然后有好多行,再把要查询的行内容完整的传给

adb shell dumpsys SurfaceFlinger --latency 窗口名

输出一堆数字,第一行数字是当前的 VSYNC 间隔,单位纳秒。如果屏幕是 60Hz ,就是 16.6ms,然后下面一堆数字,总共有 127 行,每一行有 3 个数字,每个数字都是时间戳,单位是纳秒。

Android 显示一帧大致分为几个步骤
1,App 接收到 vsync-app 信号后开始工作。
2,App 主线程被Message唤醒,执行onVsync。
3,App 执行 doFrame ,处理input、animation、traversal、draw等。
4,App UIThread 跟RenderThread sync 数据。
5,App 执行DrawFrame,从SurfaceFlinger(后续简称SF) 的 BufferQueue 中 dequeueBuffer,取出一个bufffer后,执行渲染绘制,接着将绘制好的Buffer 通过queueBuffer 放回到BufferQueue中给 SF消费。
6,App queueBuffer 后, SF 中对应的 app buffer 会增加 +1。
7,Vsync-sf 到来后,SF 从BufferQueue 中 acquireBuffer一个Buffer 进行消费, 对应SF 中的 app buffer 会减 - 1 , SF 消费处理后,通过 releaseBuffer 将buffer 归还到BufferQueue 中。
8,SF 通过 bind 跟 Hardware Composer HAL(HWC) 进行通信,通过一些处理后显示到手机屏幕上。

d48e7b7a06d948899b32b527b87c66e7.webp

dequeue(生产者发起) :
当生产者需要缓冲区时,它会通过调用 dequeueBuffer() 从 BufferQueue 请求一个可用的缓冲区,并指定缓冲区的宽度、高度、像素格式和使用标记。
queue(生产者发起):
生产者填充缓冲区并通过调用 queueBuffer() 将缓冲区返回到队列。
acquire(消费者发起) :
消费者通过 acquireBuffer() 获取该缓冲区并使用该缓冲区的内容。
release(消费者发起) :
当消费者操作完成后,它会通过调用 releaseBuffer() 将该缓冲区返回到队列。

b1693a8c24824eaf8e54b84d84dba931.png
 

App 绘制的图像内容是怎么最终显示到手机屏幕?

App 要显示的内容要绘制在 Buffer 里,这个 Buffer 是从 BufferQueue 通过 dequeueBuffer() 申请。申请到 Buffer 后,App 将内容填充到 Buffer ,通过 queueBuffer() 将 Buffer 还回去交给 SurfaceFlinger 去进行合成和显示。然后,SurfaceFlinger 开始合成时候,调用 acquireBuffer() 从 BufferQueue 里面拿一个 Buffer 合成,合成完以后通过 releaseBuffer() 将 Buffer 还给 BufferQueue。

a388fd254642416d8af4e726c88f3678.webp

RenderThread 的 dequeueBuffer
dequeue 出队,dequeueBuffer 就是从队列中拿出一个 Buffer,这个队列就是 SurfaceFlinger 中的 BufferQueue。app开始渲染前,首先需要通过 Binder 调用从 SurfaceFlinger 的 BufferQueue 中获取一个 Buffer。

a089a2ede3af44a8ba2924305633f5a3.jpeg

RenderThread 的 queueBuffer
queue 入队,queueBuffer 是把 Buffer 放回到 BufferQueue,App 处理完 Buffer 后,会把这个 Buffer 通过 eglSwapBuffersWithDamageKHR -> queueBuffer ,将 Buffer 放回 BufferQueue。

759d4f6f2ef3460a924d9af08c02c9dd.jpeg

上面流程有一个问题,在 App 绘制完通过 queueBuffer() 将 Buffer 还回时候,此时仅仅只是 CPU 侧完成,GPU 实际上有没有真正完成,CPU并不知道。因此如果此时GPU拿这个 Buffer 去合成/显示,就会有问题(Buffer 可能还没有完全绘制完)。由于 CPU 和 GPU 是异步的,因此CPU在代码里执行一系列绘图函数调用后,看上去函数已经返回,实际上,具体什么时候被GPU真正执行完毕 CPU 不知道,除非阻塞等待这些命令完全执行完,但这样会带来严重的性能问题,因为这样使得 CPU 和 GPU 的并行完全丧失,CPU 会在 GPU 完成之前一直处于空等状态。因此,需要一种机制,在不需要对 Buffer 进行读写时候,大家各干各的;当需要对 Buffer 进行读写时候,CPU可以知道此时 Buffer 在 GPU 的状态,必要时候等一下。

fence 是这样的同步机制——“栅栏”,把东西拦住。fence 要拦住什么东西呢?就是 Buffer。Buffer 在整个绘制、合成、显示过程中,一直在 CPU,GPU 和 HWC 之间传递,某一方要使用 Buffer 前,需要检查之前的使用者是否已经移交 Buffer 的“使用权”。而这里的“使用权”,就是 fence。当 fence 释放(即 signal)时候,说明 Buffer 的上一个使用者已经交出了使用权,对于 Buffer 进行操作是安全的。

Android 总共有三类 fence —— acquire fence,release fence 和 present fence。

•acquire fence
    App 将 Buffer 通过 queueBuffer() 还给 BufferQueue 的时候,此时该 Buffer 的 GPU 侧其实未必完成,此时会带上一个 fence,这个 fence 就是 acquire fence。当 SurfaceFlinger/ HWC 要读取 Buffer 以进行合成操作的时候,需要等 acquire fence 释放之后才行。
•release fence
    当 App 通过 dequeueBuffer() 从 BufferQueue 申请 Buffer,要对 Buffer 进行绘制时候,需要保证 HWC 已经不再需要这个 Buffer 了,即需要等 release fence signal 才能对 Buffer 进行写操作。
•present fence
    当前帧成功显示到屏幕的时候,present fence 就会 signal。

d80f0e75cf0e4332b213b47447829bd9.png

每一个buffer都一个Fence状态,代表这块buffer是否还在被上一个使用者使用完,并且在转移时都会携带当前Fence的fd,然后可以调用Fence的wait或者waitForever查询Fence状态,如果还在使用则等待,否则就可以使用。Fence按作用大体分两种:acquireFence和releaseFence。前者用于生产者通知消费者生产已完成,后者用于消费者通知生产者消费已完成。

Fence保证GraphicBuffer在App, GPU和HWC三者间流转时数据读写同步(不同进程 or 不同硬件间同步)。
从 SurfaceFlinger 的角度来看,App 部分主要负责生产 SurfaceFlinger 合成所需要的 Surface。
App 与 SurfaceFlinger 的交互主要集中在三点
1 Vsync 信号的接收和处理
2 RenderThread 的 dequeueBuffer
3 RenderThread 的 queueBuffer

384e0ea30071463c943b7132e063a0e3.jpeg
 

从 dumpsys SurfaceFlinger --latency 获取最新 127 帧的 present fence 的 signal time,当某帧 present fence 被 signal 时候,说明这一帧已经被显示到屏幕上。因此,可以通过判断1秒内有多少个 present fence signal ,反推出一秒内有多少帧被刷新(显示)到屏幕上,从而计算出 fps。

统计一秒内 App 往屏幕刷了多少帧,在 Android 里,每一帧显示到屏幕的标志是:present fence signal ,因此计算 App 的 fps 就可以转换为:一秒内 App 的 Layer 有多少个有效 present fence signal 。

 

 

 

Android adb shell命令捕获systemtrace_android 抓trace-CSDN博客文章浏览阅读1.7k次,点赞2次,收藏5次。Android ADB调试真机设备Android ADB(Andorid Debug Bridge),是Android开发中有用的测试和调试工具。使用Android ADB调试设备,直接在Windows的dos命令窗口输入命名adb即可,如图:为什么执行adb命令后是这样?Android ADB(Andorid Debug Bridge)调试真机设备_adb在线执行器_zhangphil的博客-CSDN博客。-t 时长,20s,20秒的trace文件。-o 保存文件路径。_android 抓tracehttps://blog.csdn.net/zhangphil/article/details/131249820

Android GPU渲染屏幕绘制显示基础概念(1)-CSDN博客文章浏览阅读696次,点赞20次,收藏12次。CPU返回后,会直接将GraphicBuffer提交给SurfaceFlinger,告诉SurfaceFlinger进行合成,但是这个时候GPU可能并未完成之前的图像渲染,这时候就牵扯到一个同步,Android中,用的是Fence机制,SurfaceFlinger合成前会查询Fence,如果GPU渲染没有结束,则等待GPU渲染结束,GPU结束后,会通知SurfaceFlinger进行合成,SF合成后,提交显示,最终完成图像的渲染显示。而对SF来说,只要有合成任务,它就得再去申请VSYNC-sf。https://blog.csdn.net/zhangphil/article/details/138585120Android性能:Double Buffer双缓冲/Triple Buffer三缓冲丢帧Jank与无丢帧No Jank-CSDN博客文章浏览阅读858次,点赞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

 

这篇关于Android GPU渲染SurfaceFlinger合成RenderThread的dequeueBuffer/queueBuffer与fence机制(2)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/978070

相关文章

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

Android里面的Service种类以及启动方式

《Android里面的Service种类以及启动方式》Android中的Service分为前台服务和后台服务,前台服务需要亮身份牌并显示通知,后台服务则有启动方式选择,包括startService和b... 目录一句话总结:一、Service 的两种类型:1. 前台服务(必须亮身份牌)2. 后台服务(偷偷干

Spring排序机制之接口与注解的使用方法

《Spring排序机制之接口与注解的使用方法》本文介绍了Spring中多种排序机制,包括Ordered接口、PriorityOrdered接口、@Order注解和@Priority注解,提供了详细示例... 目录一、Spring 排序的需求场景二、Spring 中的排序机制1、Ordered 接口2、Pri

Java实战之自助进行多张图片合成拼接

《Java实战之自助进行多张图片合成拼接》在当今数字化时代,图像处理技术在各个领域都发挥着至关重要的作用,本文为大家详细介绍了如何使用Java实现多张图片合成拼接,需要的可以了解下... 目录前言一、图片合成需求描述二、图片合成设计与实现1、编程语言2、基础数据准备3、图片合成流程4、图片合成实现三、总结前

MySQL 缓存机制与架构解析(最新推荐)

《MySQL缓存机制与架构解析(最新推荐)》本文详细介绍了MySQL的缓存机制和整体架构,包括一级缓存(InnoDBBufferPool)和二级缓存(QueryCache),文章还探讨了SQL... 目录一、mysql缓存机制概述二、MySQL整体架构三、SQL查询执行全流程四、MySQL 8.0为何移除查

一文详解Java Condition的await和signal等待通知机制

《一文详解JavaCondition的await和signal等待通知机制》这篇文章主要为大家详细介绍了JavaCondition的await和signal等待通知机制的相关知识,文中的示例代码讲... 目录1. Condition的核心方法2. 使用场景与优势3. 使用流程与规范基本模板生产者-消费者示例

Android kotlin语言实现删除文件的解决方案

《Androidkotlin语言实现删除文件的解决方案》:本文主要介绍Androidkotlin语言实现删除文件的解决方案,在项目开发过程中,尤其是需要跨平台协作的项目,那么删除用户指定的文件的... 目录一、前言二、适用环境三、模板内容1.权限申请2.Activity中的模板一、前言在项目开发过程中,尤

详解如何在React中执行条件渲染

《详解如何在React中执行条件渲染》在现代Web开发中,React作为一种流行的JavaScript库,为开发者提供了一种高效构建用户界面的方式,条件渲染是React中的一个关键概念,本文将深入探讨... 目录引言什么是条件渲染?基础示例使用逻辑与运算符(&&)使用条件语句列表中的条件渲染总结引言在现代

一文带你理解Python中import机制与importlib的妙用

《一文带你理解Python中import机制与importlib的妙用》在Python编程的世界里,import语句是开发者最常用的工具之一,它就像一把钥匙,打开了通往各种功能和库的大门,下面就跟随小... 目录一、python import机制概述1.1 import语句的基本用法1.2 模块缓存机制1.

Redis主从/哨兵机制原理分析

《Redis主从/哨兵机制原理分析》本文介绍了Redis的主从复制和哨兵机制,主从复制实现了数据的热备份和负载均衡,而哨兵机制可以监控Redis集群,实现自动故障转移,哨兵机制通过监控、下线、选举和故... 目录一、主从复制1.1 什么是主从复制1.2 主从复制的作用1.3 主从复制原理1.3.1 全量复制