无法理解有助于异步显示的 BufferQueue 同步逻辑

Unable to understand BufferQueue sync logic that helps for async display

我正在阅读 android 来自 this link 的架构。

在第一次尝试时,我只能理解零零碎碎的东西。

我明白了什么?

1)

有个东西叫做 'sync framework'。 - 好的

2)

此同步框架可以在进程之间以及用户 space 和内核 space 之间使用。 - 好的

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 官方 link 的段落。

"最近的 Android 设备支持 "sync framework"。这允许系统在与可以异步操作图形数据的硬件组件结合时做一些漂亮的事情。例如,生产者可以提交一系列 OpenGL ES 绘图命令,然后在渲染完成之前将输出缓冲区加入队列。缓冲区伴随着栅栏,在内容准备就绪时发出信号。第二个栅栏伴随着缓冲区,当它准备好时返回到空闲列表,以便消费者可以在内容仍在使用时释放缓冲区。随着缓冲区在系统中移动,这种方法提高了延迟和吞吐量。"

问题:

我对这个说法特别困惑。

"A second fence accompanies the buffer when it is returned to the free list, so that the consumer can release the buffer while the contents are still in use. This approach improves latency and throughput as the buffers move through the system."

同一缓冲区上的第二个栅栏?。或不同的缓冲区?如我所见,有两个缓冲区队列,一个是填充列表,另一个是空列表。

如果您想更深入地了解同步框架,您还应该阅读 this document and especially the "explicit synchronization" section of this document

您的描述很接近,但不太正确。每个缓冲区都有一个 "acquire" 栅栏和一个 "release" 栅栏。 "acquire" 围栏指示生产者(例如 OpenGL ES)何时完成渲染。它不会告诉消费者(HardwareComposer,它提供显示器)它 需要 来显示缓冲区,而是现在 允许 显示缓冲区,因为渲染已完成。当显示硬件不再访问缓冲区时,HWC 会发出 "release" 栅栏信号,这意味着再次允许消费者写入它。

延迟减少是未将缓冲区的状态与其在队列中的状态联系起来的结果。 BufferQueue 可以在渲染完成之前认为您已充满数据,并且可以在显示完成显示缓冲区之前让您进入 "free" 列表。这允许 IPC 队列机制在不阻塞 GPU 或显示器的情况下完成它们的工作。

围栏一旦发出信号,就永远不会变为未发出信号,因此您不能将单个围栏用于多个事件。这就是为什么 "data is ready" 和 "data is no longer needed".

需要两个不同的栅栏

FWIW,名称 "BufferQueue" 有点误导。填充的缓冲区在队列中,空缓冲区在池中。 (池有一个 FIFO 策略,所以它本质上是一个队列,但不能保证。)