1. 引言:显式同步的兴起
1.1 为什么需要显式同步
传统的隐式同步虽然简化了应用开发,但在现代图形应用中暴露出明显的局限:
性能问题
- 驱动无法知晓应用的真实意图,只能保守地插入同步点
- 过度同步导致GPU流水线停顿
- 难以实现细粒度的并行优化
延迟问题
- VR应用需要严格控制每一帧的时序
- 关键路径上的隐式等待增加不可预测的延迟
灵活性问题
- 应用无法表达复杂的依赖关系(如多GPU渲染)
- 无法跨进程高效传递同步信息
- 难以与专用硬件(如视频编码器)协同
显式同步(Explicit Synchronization)应运而生,将同步点的控制权交还给应用。
1.2 显式 vs 隐式对比
| 维度 | 显式同步 | 隐式同步 |
|---|---|---|
| 同步点管理 | 应用显式创建和传递 | 驱动自动管理 |
| fence可见性 | 用户态可见(fd/handle) | 仅驱动可见 |
| API支持 | Vulkan、Metal、DX12 | OpenGL、X11 |
| 性能 | 可精细优化 | 保守,易过度同步 |
| 复杂度 | 高,易出错 | 低,自动化 |
| 跨进程 | 高效(传递fd) | 通过dma-buf间接 |
| 典型对象 | sync_file、drm_syncobj | dma_resv |
1.3 Linux中的显式同步对象
Linux内核提供两种主要的显式同步对象:sync_file和drm_syncobj。
2. sync_file
sync_file是Linux内核中用于显式同步的核心机制之一,最初由Android引入用于解决图形系统中的同步问题,后来被合并进主线内核。它提供了一种基于文件描述符的轻量级同步原语,允许用户空间显式地管理GPU工作的依赖关系。
2.1 核心结构
struct sync_file {
struct file *file; // 关联的文件对象
char user_name[32]; // 用户指定的名称
wait_queue_head_t wq; // 等待队列
unsigned long flags; // 标志位(如POLL_ENABLED)
struct dma_fence *fence; // 封装的dma_fence
struct dma_fence_cb cb; // fence完成时的回调
};
设计要点
-
文件抽象:利用Linux文件系统基础设施,自动引用计数(通过
struct file),poll/select支持(通过wait_queue)以及跨进程传递(通过fd); -
单一fence:每个sync_file封装一个fence,可能是单个fence,也可能是fence_array(合并多个fence);
-
只读语义:创建后fence不可变,这章设计简化了生命周期管理,避免竞态条件。
3. drm_syncobj
drm_syncobj是DRM子系统中用于显式同步的核心机制,最初为实现Vulkan的fence和semaphore而设计。与一次性的sync_file不同,drm_syncobj提供了可更新、可重置的同步原语,并支持复杂的时间线语义。
3.1 核心结构
struct drm_syncobj {
struct kref refcount; // 引用计数
struct dma_fence __rcu *fence; // RCU保护的fence指针
struct list_head cb_list; // fence更新时的回调列表
struct list_head ev_fd_list; // eventfd通知列表
spinlock_t lock; // 保护cb_list和fence
struct file *file; // 关联的文件对象
};
设计要点
- 可重用性:同一个syncobj可以在多次GPU提交中重复使用
- 时间线支持:通过fence_chain实现类似Vulkan timeline semaphore的功能
- 灵活更新:支持替换、重置、信号等多种操作
- 跨进程共享:通过DRM handle或fd机制在进程间传递
- 高效等待:支持主机端等待、eventfd通知等多种机制
4. sync_file与drm_syncobj 的区别
| 特性 | sync_file | drm_syncobj |
|---|---|---|
| 创建方式 | 从fence创建 | 显式创建后设置fence |
| 可变性 | 不可变 | 可重置/更新 |
| 标识符 | fd(文件描述符) | handle(DRM对象) |
| 生命周期 | 绑定文件 | 显式创建/销毁 |
| 时间线 | 不支持 | 支持(通过fence_chain) |
| 回调 | 仅内部使用 | 支持用户回调 |
初看这两个结构体的定义,长得很像。单看本节有点理论,还是要结合用户态如何使用的场景来理解。后面两节分开专讲。
734

被折叠的 条评论
为什么被折叠?



