我正在从 this 链接阅读 Android 架构。
在第一次尝试时,我无法理解所有内容,只能理解一些零碎的东西。
我明白什么?
1)
有一种叫做“同步框架”的东西。 - 好的
2)
这个同步框架可以在进程之间以及用户空间和内核空间之间使用。 - 好的
3)
用于异步机制。 - 好的。
4)
假设没有同步框架。
void display_buffer(struct dma_buf *buf);
有一个显示系统显示给定的缓冲区。
while (1) {
-> Fill the buffer( buf)
-> call display_buffer(buf); -> Displays into the screen.
}
可能存在延迟,因为它是同步。
5)
假设我们有同步框架支持。 它是这样的:我会给显示系统缓冲区和startfence,当你在startfence上收到信号时,你需要显示缓冲区。同时,当你完成后,你需要用“donefence”来暗示我。显示系统为我提供了这些。 [我不完全理解,但是,我觉得它对异步模型有帮助],这样我就可以在系统渲染时填充缓冲区。
struct sync_fence* display_buffer(struct dma_buf *buf,
struct sync_fence *fence);
灰色区域:但是,我仍然无法编写伪代码来了解如何在异步模式下使用display_buffer?
从android官方链接阅读段落。
”大多数最新的 Android 设备都支持“同步框架”。这使得系统在与可以异步操作图形数据的硬件组件结合使用时可以做一些漂亮的事情。例如,制作者可以提交一系列 OpenGL ES 绘图命令并然后在渲染完成之前将输出缓冲区入队。缓冲区附带一个栅栏,当内容准备好时发出信号。当缓冲区返回到空闲列表时,第二个栅栏伴随着缓冲区,以便消费者可以在缓冲区被释放时释放缓冲区。内容仍在使用中。当缓冲区在系统中移动时,这种方法可以改善延迟和吞吐量。“
问题:
我对这个说法特别困惑。
“当缓冲区返回到空闲列表时,第二个栅栏伴随着缓冲区,以便消费者可以在内容仍在使用时释放缓冲区。当缓冲区在系统中移动时,这种方法可以改善延迟和吞吐量。”
同一缓冲区上的第二个栅栏?或不同的缓冲区?正如我所看到的,有两个缓冲区队列,一个是已填充列表,另一个是空列表。
如果您想更深入地了解同步框架,您还应该阅读本文档,尤其是本文档的“显式同步”部分。
您的描述很接近,但不太正确。每个缓冲区都有一个“获取”栅栏和一个“释放”栅栏。 “获取”栅栏指示生产者(例如 OpenGL ES)何时完成渲染。它不会告诉消费者(HardwareComposer,为显示提供数据)它需要显示缓冲区,而是现在“允许”显示缓冲区,因为渲染已完成。当显示硬件不再访问缓冲区时,HWC 会发出“释放”栅栏信号,这意味着生产者再次被允许对其进行写入。 延迟减少是由于未将缓冲区的状态与其在队列中的状态联系起来的结果。 BufferQueue 可以在渲染完成之前认为您已充满数据,并且可以在显示完成显示缓冲区之前将您置于“空闲”列表中。这使得 IPC 队列机制能够在不阻塞 GPU 或显示器的情况下完成任务。
一旦栅栏发出信号,它就永远不会变为未发出信号,因此您不能将单个栅栏用于多个事件。这就是为什么您需要两个不同的栅栏来表示“数据已准备好”和“不再需要数据”。
FWIW,“BufferQueue”这个名字有点误导。已填充的缓冲区位于队列中,空缓冲区位于池中。 (该池具有 FIFO 策略,因此它本质上是一个队列,但这并不能保证。)