Fence同步

news2024/10/6 10:26:02

       在《Android图形显示系统》没有介绍到帧同步的相关概念,这里简单介绍补充一下。

     在图形显示系统中,图形缓存GraphicBuffer可以被不同的硬件来访问,如CPU、GPU、HWC都可以对缓存进行读写,如果同时对图形缓存进行操作,有可能出现意想不到的效果。由于GPU的执行是异步的,向GPU发命令,CPU是不知道命令什么时候执行完的,如果GPU渲染的内容还没完成,图形缓存的内容可能是空的或者不完整的,此刻CPU就开始对它进行消费,读取出来的图形数据是有问题的。因此需要协商一种机制,保证同一时间只有一个硬件对图形缓存进行访问,如果GPU正在使用,CPU只能同步等待。

    在图层合成的过程中,也使用了同步机制,否则也不能正常显示。使用的是Fence的同步机制,Fence,是栅栏的意思,在CPU使用缓存的地方设置一个栅栏挡住,等GPU对该缓存的操作完成后,再通知把栅栏撤了,CPU就可以开始对缓存进行操作。下面以图层的合成过程来说明栅栏的使用:

下面以时间轴从左到右来说明Fence是如何防止同时对缓存进行访问的:
1)生产者通过dequeue申请到一个缓存,获得缓存的所有权和使用权
2)生产者通过GPU开始生产内容
3)生产者通过queue把缓存放进队列,不再拥有所有权,但是GPU还在使用,仍然拥有使用权。
4)消费者通过acquire获得缓存的所有权,但是生产者还拥有使用权,消费者不能对缓存进行操作。
5)GPU完成了所有工作,生产者释放使用权,消费者获得使用权。

    通过上面的流程可以看到,生产者和消费者对于缓存的操作在时间轴上是没有重叠的,并且相隔很近。为了体现Fence同步机制的优势,下面再看不通过Fence来进行同步的情况:

同步过程如下:
1)生产者通过dequeue申请到一个缓存,生产者获得所有权和使用权。
2)生产者通过GPU开始生产内容。
3)生产者等待GPU完成工作,释放使用权,通过queue释放所有权。
4)消费者通过acqure获得所有权和使用权,可以开始对缓存进行操作。

 通过上面的对比可以看到:
使用fence进行同步,生产者生产完图形缓存,消费者立刻能够消费;
不使用fence进行同步,生产者在渲染的过程中,CPU要等待GPU完成工作后才把缓存的所有权和使用权交给消费者,中间有一个比较大的时间差,正是这个时间差可能导致缓存不能及时显示出来,导致显示的不够流畅。

下面再结合图层合成的源码看Fence是如何进行同步的:

void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip,
                         bool useIdentityTransform) const {
    status_t err = mConsumer->bindTextureImage();
}

status_t BufferLayerConsumer::bindTextureImage() {

    return bindTextureImageLocked();
}
status_t BufferLayerConsumer::bindTextureImageLocked() {
    mRE.bindExternalTextureImage(mTexName, mCurrentTextureImage->image());
    // Wait for the new buffer to be ready.
    return doFenceWaitLocked();
}

status_t BufferLayerConsumer::doFenceWaitLocked() const {
    if (!mRE.isCurrent()) {
        return INVALID_OPERATION;
    }
    if (mCurrentFence->isValid()) {
        if (SyncFeatures::getInstance().useWaitSync()) {
            base::unique_fd fenceFd(mCurrentFence->dup());
            if (!mRE.waitFence(std::move(fenceFd))) {
            }
        } 
    }
}

bool RenderEngine::waitFence(base::unique_fd fenceFd) {

    EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd, EGL_NONE};
    EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);

    (void)fenceFd.release();

    eglWaitSyncKHR(mEGLDisplay, sync, 0);
    EGLint error = eglGetError();
    eglDestroySyncKHR(mEGLDisplay, sync);

    return true;
}

    图形缓存绑定到纹理时并不马上返回,而是通过waitFence进入等待。Fence可以看成一个文件句柄,通过eglCreateSyncKHR创建同步对象,eglWaitSyncKHR开始等待。GPU完成所有指令,发出通知,eglWaitSyncKHR收到通知后返回,绘制流程可以继续往下走了。

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

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

相关文章

数据结构--循环队列

1.队列的定义: 和栈相反,队列(queue)是一种先进先出(first in first out,缩写为FIFO)的线性表.它只允许在表的一端进行插入,而在另一端删除元素. 在队列中,允许插入的一端叫做队尾(rear),允许删除的一端则称为队头(front). 2.循环队列的设计图示: 3.循环队列的结构设计: ty…

napi系列学习进阶篇——NAPI生命周期

什么是NAPI的生命周期 我们都知道,程序的生命周期是指程序从启动,运行到最后的结束的整个过程。生命周期的管理自然是指控制程序的启动,调用以及结束的方法。 而NAPI中的生命周期又是怎样的呢?如下图所示: 从图上我们…

foreach无法修改数组值解决方案

效果展示: 解决办法: this.sportList.forEach((item,index) >{let that this;if(item.idinfo.id) {that.sportList[index].sportTime e.detail.value} }) 这里小编解释下,将this赋值给that通常是为了在回调函数或者异步代码中保持对Vu…

C++11 设计模式4. 抽象工厂(Abstract Factory)模式

问题的提出 从前面我们已经使用了工厂方法模式 解决了一些问题。 现在 策划又提出了新的需求:对于各个怪物,在不同的场景下,怪物的面板数值会发生变化, //怪物分类:亡灵类,元素类,机械类 …

Unity让地图素材遮挡人物

点击编辑/项目设置/图形,透明度排序模式设置自定义轴,透明度排序轴Y设置为1其他为0。 此时人物和地图素材的图层排序相等,当人物的高度大于地图素材时,人物则被遮挡。

使用ArrayList.removeAll(List list)导致的机器重启

背景 先说一下背景,博主所在的业务组有一个核心系统,需要同步两个不同数据源给过来的数据到redis中,但是每次同步之前需要过滤掉一部分数据,只存储剩下的数据。每次同步的数据与需要过滤掉的数据量级大概在0-100w的数据不等。 由…

【C语言】字符串函数和内存函数及其模拟实现

文章目录 前言 一、常见字符串库函数1.strlen函数2.长度不受限制的字符串函数2.1 strcpy2.2 strcat2.3 strcmp 3.长度受限制的字符串函数3.1 strncpy3.2 strncat3.3 strncmp 二、字符串查找函数strstrstrtok 三、strerror函数四、内存操作函数1.memcpy2.memmove3.memcmp 五、字…

Unity之Unity面试题(三)

内容将会持续更新,有错误的地方欢迎指正,谢谢! Unity之Unity面试题(三) TechX 坚持将创新的科技带给世界! 拥有更好的学习体验 —— 不断努力,不断进步,不断探索 TechX —— 心探索、心进取…

简单工厂模式大解析:让代码创造更高效、更智能!

个人主页: danci_ 🔥系列专栏:《设计模式》《MYSQL应用》 💪🏻 制定明确可量化的目标,坚持默默的做事。 🚀 转载自热榜文章:探索设计模式的魅力:简单工厂模式 简单工厂模式&#x…

【零基础学数据结构】双向链表

1.双向链表的概念 1.1头节点 1.2带头双向循环链表 注意: 哨兵位创建后,首尾连接自己 1.3双链表的初始化 // 双向链表的初始化 void ListInit(ListNode** pphead) {// 给双链表创建一个哨兵位*pphead ListBuyNode(-1); } 2.双向链表的打印 // 双向…

PE文件的分析和构造超详细过程

本文详细讲述如何从0构造一个PE文件,运行该文件会弹出一个HelloPE的窗口 目录 预备知识 1. 构造DOS头IMAGE_DOS_HEADER 1.1 构造DOS_MZ头 1.2 构造DOS_STUB 2、构造PE头IMAGE_NT_HEADERS 248字节 2.1 signature 2.2 IMAGE_FILE_HEADER 2.3 IMAGE_OPTI…

MOS管电路的应用及注意事项

1,buck电路的上下桥死区时间多少合适 死区时间由驱动芯片控制的,外围电路增加阻容会导致上升沿时间变长 死区时间从单片机PWM到驱动电路再到MOS管的栅极都有一定的硬件延时,所以具体时间需要根据调试确定。 例如充电芯片的buck电路,有死区配置…

mysql8.0高可用集群架构实战

MySQL :: MySQL Shell 8.0 :: 7 MySQL InnoDB Cluster 基本概述 InnoDB Cluster是MySQL官方实现高可用读写分离的架构方案,其中包含以下组件 MySQL Group Replication,简称MGR,是MySQL的主从同步高可用方案,包括数据同步及角色选举Mysql Shell 是InnoDB Cluster的管理工具,用…

数据库系统概论(超详解!!!)第四节 数据库安全性

问题的提出: 数据库的一大特点是数据可以共享 数据共享必然带来数据库的安全性问题 数据库系统中的数据共享不能是无条件的共享。 1.数据库的安全概述 数据库的安全性是指保护数据库以防止不合法使用所造成的数据泄露、更改或破坏 。 系统安全保护措施是否有效…

基于ssm的土家风景文化管理平台(java源码+文档)

项目简介 土家风景文化管理平台实现了以下功能: 土家风景文化管理平台的主要使用者分为管理员:管理员使用本平台涉到的功能主要有:首页,个人中心,用户管理,景点分类管理,热门景点管理&#xf…

深度学习学习日记4.7

1.梯度下降 w 新 w旧 - 学习率梯度 训练的目的就是让 loss 减小 2.前向传播进行预测, 反向传播进行训练(每一个参数通过梯度下降进行更新参数),(1前向传播 2求 loss 3反向传播 4梯度更新) 能够让损失下降的参数,就是更好的参数。 损失…

基于SSM物业管理系统

摘要 进入二十一世纪以来,计算机技术蓬勃发展,人们的生活发生了许多变化。很多时候人们不需要亲力亲为的做一些事情,通过网络即可完成以往需要花费很多时间的操作,这可以提升人们的生活质量。计算机技术对人们生活的改变不仅仅包…

单列模式1.0

单列模式 单例模式能保证某个类在程序中只存在唯⼀⼀份实例, ⽽不会创建出多个实例 1.饿汉模式 只要程序一启动就会立即创建出一个对象 class Signleton{private static Signleton instancenew Signleton();//防止在以后的代码中再创建对象,我们将构造方法private,…

FreeFileSync|本地自动备份设置教程,终于可以不用手动同步了

前言 昨天小白给各位小伙伴分享了FreeFileSync软件,由于篇幅过长,所以整个教程中并没有教小伙伴们如何设置自动同步的办法。 今天小白就来唠唠:如何让FreeFileSync自动同步。 教程分为几种: 开机自动同步 开机之后自动执行一次…