Triple Buffer介绍
-
Buffer Queue介绍
- 上图主要是 dequeue、queue、acquire、release ,在这个例子里面,App 是生产者,负责填充显示缓冲区(Buffer);SurfaceFlinger 是消费者,将各个进程的显示缓冲区做合成操作。
- dequeue(生产者发起) : 当生产者需要缓冲区时,它会通过调用 dequeueBuffer() 从 BufferQueue 请求一个可用的缓冲区,并指定缓冲区的宽度、高度、像素格式和使用标记。
- queue(生产者发起):生产者填充缓冲区并通过调用 queueBuffer() 将缓冲区返回到队列。
- acquire(消费者发起) :消费者通过 acquireBuffer() 获取该缓冲区并使用该缓冲区的内容。
- release(消费者发起) :当消费者操作完成后,它会通过调用 releaseBuffer() 将该缓冲区返回到队列。
-
引入triple buffer原因
在一个典型的显示系统中,一般包括CPU、GPU、display三个部分, CPU负责计算数据,把计算好数据交给GPU,GPU会对图形数据进行渲染,渲染合成好后放到buffer里存起来,然后display。
-
Single Buffer
理想情况下,cpu、gpu在16.67ms(1000ms/60帧=16.67ms/帧)内完成。但是很不幸,理想情况我们也就想一想,这期间如果 App 渲染或者 SurfaceFlinger 合成在屏幕显示刷新之前还没有完成,那么屏幕刷新的时候,拿到的 Buffer 就是不完整的,在用户看来,就有种撕裂的感觉。于是引入了Double Buffer。
-
Double Buffer
- 第一个Vsync周期,App执行Buffer A的生产,Surface Flinger合成,消费Buffer B
- 第二个Vsync周期,App执行Buffer B的生产,Surface Flinger合成,消费BufferA
- 第三个Vsync周期,App执行Buffer A的生产,Surface Flinger合成,消费Buffer B
- 第四个Vsync周期,App执行Buffer B的生产,Surface Flinger合成,消费Buffer A
- 第五个Vsync周期,App执行Buffer A的生产,Surface Flinger合成,消费Buffer B
但如果cpu、GPU连续两帧生产都超过 Vsync 周期(准确的说是错过 SurfaceFlinger 的合成时机) ,就会出现掉帧情况
- 第一个Vsync周期里面,App执行渲染超过了一个Vsync周期
- 第二个Vsync开始的时候,由于Buffer A还没有完成,Buffer B还在使用,所以这里没有可操作的Buffer,这一帧就没有生产,这里掉了一帧
- 第三个Vsync周期里面,Surface Flinger才开始合成Buffer A,Buffer B在消费buffer A时被释放,App此时可以拿到Buffer B进行生产
- 第四个Vsync周期里,由于Buffer B的生产时间也超过了一个Vsync周期(错过了Surface Flinger的Vsync),Buffer A还在使用,所以这里也没有可操作的Buffer,这一帧也没有生产,这里又掉了一帧
- 第五个Vsync周期里,Surface Flinger开始合成Buffer B,Buffer A在消费buffer B时被释放,此时App可以拿Buffer A进行生产
为解决这种由于buffer满导致的掉帧情况,引入Triple Buffer。
-
Triple Buffer
Triple Buffer 中,又加入了一个 BackBuffer ,这样的话 BufferQueue 里面就有三个 Buffer 可以轮转了,当 FrontBuffer 在被使用的时候,App 有两个空闲的 Buffer 可以拿去生产,就算生产过程中有 GPU 超时,CPU 任然可以拿到新的 Buffer 进行生产(即 SurfaceFling 消费 FrontBuffer,GPU 使用一个 BackBuffer,CPU使用一个 BackBuffer)
- 第一个Vsync周期里面,App执行渲染超过了一个Vsync周期
- 第二个Vsync开始的时候,由于Buffer A还没有完成,Buffer B还在使用,所以这里使用Buffer C进行生产,但是由于Buffer A和Buffer C都没有生产完成,所以这里还是掉了一帧
- 第三个Vsync周期里面,Surface Flinger才开始合成Buffer A,Buffer B在消费buffer A时被释放,App此时可以拿到Buffer B进行生产
- 第四个Vsync周期里,Surface Flinger开始合成Buffer C,Buffer A在消费buffer C时被释放,App此时可以拿Buffer A进行生产
- 第五个Vsync周期里,Surface Flinger开始合成Buffer B,Buffer C在消费buffer B时被释放,此时App可以拿Buffer C进行生产
大家看到这里也出现了一次掉帧,但这次掉帧是由于cpu(或者GPU)超时导致的,不是由于buffer满导致的。和Double Buffer比减少了一次由于buffer满导致的掉帧。