SurfaceFlinger Fence 介绍
简介
本节内容会简单介绍一下fence,仅仅是为了后续我们在看SurfaceFlinger这个章节的时候,遇到fence相关的内容不会觉得不知道这是在干嘛,所以并不会很深入的介绍fence的驱动实现原理,侧重于介绍它的作用。
fence的作用
fence的作用和多线程中的锁类似,只不过他是跨进程,跨设备的。我们这里生产者需要gpu来渲染,消费者拿到buffer可能需要hwc来合成,所以需要跨设备。
举个具体的例子:
我们在渲染之前需要获取一个Buffer,然后渲染完成后会把这个Buffer传递给SurfaceFlinger去合成,这个流程中必然会用到cpu,而渲染现在一般使用gpu来渲染,合成可能同时用到gpu和hwc,这里就涉及了多个硬件。而这里渲染一般是由app进行渲染,合成是SurfaceFlinger,所以涉及多个进程。
进一步解释这个例子:
我们渲染时,要从队列中取出一个Buffer,然后通过cpu执行一些opengel指令告诉gpu怎么渲染,cpu执行完后,gpu不可能立刻完成渲染。这时候cpu有两种方案,一个是等gpu执行完,然后再把这个buffer给出去,但是这样会浪费这个cpu的资源;第二种方案,就是通过fence,cpu可以继续执行其他任务,到需要使用这个buffer的时候,再通过fence来确认gpu任务是否完成。
fence的原理
fence需要能够跨设备,所以真正的实现是在驱动层的,fence也有软件实现的,但是也是在内和态完成的。我们这里不会太关心实现的具体代码,只介绍一些实现的框架概念。
其中有三个重要的概念:
- Sync Timeline
- Sync Point
- Sync Fence
Sync Timeline
本质就是一个单调递增的计算器,但是每一个需要fence同步的硬件的驱动上下文都会有Sync Timeline
比如gpu需要渲染一个buffer,它的驱动上下文就必然有一个Sync Timeline,并且每次使用完成一个buffer后就会将Sync Timeline++,结合Sync Point可以判断特定的buffer它是否使用完成了。简单理解就是一个序列号,比这个序列号小的buffer都是以前用好的。
Sync Point
Sync Point是Sync Timeline上特定的点,同步时间点,会以树的形式挂在Sync Ponit上面,有三种状态
- Active 刚创建
- Signal 使用完成
- Error
当Sync Timeline还没有到Sync Point的点时,代表还需要等待。简单理解就是一个id,buffer在特定驱动上限文中的序列号
Sync Fence
本质是一个文件,Android中fd可以通过binder跨进程传输,所以就具备了跨进程的能力。
内部包含一系列Sync Point,每一个驱动都有自己的Sync Timeline,所以一个buffer在不同的驱动中,序列号是不同的(即Sync Point不同)。
Sync Fence一般可以简单认为是一个Buffer在不同驱动上下问题中的Sync Point合集,只有所有Sync Point都Signal状态了,这个fence才无需wait,表示这个Buffer彻底可用。
这些概念看着有点复杂,其实只谈原理很简单,举个例子说明:
gpu当前的Sync Timeline是8,这个时候下一个要消费的buffer的Sync Point就是9,hwc当前的Sync Timeline是1,下一个要消费的buffer的Sync Point就是2。这时候一个buffer需要经过gpu渲染,再需要hwc合成,我们得到的最终的Sync Fence里面就会包含这两个信息,gpu的9和hwc的2,其实他们都是在消费一个buffer,我们需要等这两个条件都满足才能断定这个buffer是可以用的。
小结
由于Fence的上册接口都比较简单,基本就是构造Fence后,wait之类的方案就会让当前线程阻塞,等到fence准备就绪后阻塞线程就会被唤醒,这里就不介绍了。
本节主要是介绍了fence的作用,就是一个跨进程跨设备的锁。以及简单的描述了以下它的原理,这些足够后续我们阅读SurfaceFlinger代码了。