drm之dma-fence介绍

dma-fence介绍

上图是drivers/dma-buf/dma-fence.c的注释,翻译成人话就是:

dma-fence由结构体dma_fence表示,是用于DMA操作的内核内部同步原语,如GPU渲染、视频编码/解码或在屏幕上显示缓冲区。

fence使用dma_fence_init()初始化,并使用dma_fence_signal()完成。fence与上下文相关联,通过dma_fence_context_alloc()分配,同一个上下文上的所有fence都是完全排序的。

因为fences的目的是为了促进跨设备和跨应用的同步,所以可以通过多种方式来使用它:

  • 单独的fence可以作为sync_file公开,通过调用sync_file_create()创建,并从用户空间中作为文件描述符访问。这种通过用户空间传递显式同步点的方式,被称为explicit fence
  • 一些子系统也有自己的显式fencing原语,如drm_syncobj。与sync_file相比,drm_syncobj允许更新底层fence;
  • 还有一种隐式fence,同步点作为共享dma_buf实例的一部分隐式传递。这样的implicit fence通过dma_buf存储在结构体dma_resv.resv;

dma-fence提出背景

 同样的,翻译成人话是:

在dma fence提出之前,内核态缺乏一种硬件同步机制,无法让两个硬件单元(GPU和display)同步数据,因此只能返回用户态,让用户态程序来负责这两个事情,间接完成数据同步。 更高效的这做法是在内核空间一次性将渲染和显示做完,这样就可以节省一次内核态与用户态上下文切换的开销。

dma-fence的提出就是用于解决这类问题,它用来实现多个硬件之间共享buffer的同步,当用户态应用往Ring Buffer提交渲染命令后,将GPU处理的渲染buffer fd共享给显示设备,同时将一个dma-fence关联到这个buffer上并往dma-fence添加一个回调函数,当GPU处理完buffer之后,触发buffer关联的dma-fence上的回调函数,然后GPU将渲染完成的数据送给display显示。

fence设计原理

dma-fence设计有三个状态,一是初始化后的默认状态;二是使能状态(in-fence),通常在注册fence回调函数的时候被设置成这个状态;三是完成状态(out-fence),通常硬件的fence完成后在中断处理中设置。

dma-fence本身的实现和使用并不复杂,其只有两种状态signaled和unsigned。dma-fence是可以跨设备,跨进程的。fence 同步机制可以确保 buffer 在共享过程中,驱动程序或用户空间不会对一个正在被写入的 buffer 进行读操作,或对一个仍在被其他模块使用的 buffer 进行写操作。fence 确保了这些操作能够有序进行,即只会在 buffer 不被使用时才进行读写操作。

先上数据结构:

include/linux/dma-fence.h

 内核对这个数据结构的注释比较清晰,直接看对应的API。

 dma-fence的典型用法如下:

1)调用dma_fence_context_alloc(1)来分配1个fence上下文context;

2)调用dma_fence_init()函数来初始化dma_fence结构体,主要是对fence->ops,fence->context和fence->seqno,也就是将context,dma_fence_ops和dma_fence结构体关联起来;

3)然后调用dma_fence_wait()让进程睡眠,等待buffer使用结束;这个场景对应到APP准备好buffer,去交给GPU render;

4)GPU render完成后,就会调用dma_fence_signal_locked()去唤醒前面wait的进程,表明当前buffer已经render完成;

注意:dma-fence的使用还可以通过dma_fence_add_callback()函数添加一个或多个callback函数,当dma-fence调用signal时,会依次遍历callback list,并调用每个callback函数。当我们不使用dma_fence_add_callback()函数的话,调用wait函数时会把默认的一个callback函数加入到dma-fence中,而这个函数就起到唤醒的作用。

dma-fence在Display pipeline的使用场景中,通常是这样的。首先,user空间向 kernel空间 提交一个 buffer 用于 Display 显示,kernel空间会创建对应的dma-fence结构体,同时user空间还会收到一个新创建的 fence-fd(fence绑定到sync文件供user空间使用,其实就是文件描述符)。当该 buffer 不再需要被显示时,它所对应的 fence 就会被 signal,于是这块 buffer 就可以被另一个渲染 job 拿去重新使用了。一旦user空间拿到该 fence,它可以无需等待就向GPU提交一个新的渲染 job。GPU 驱动则在内核空间等待该 buffer 显示完成,一旦 fence 发出信号,buffer 的渲染工作就可以立即启动。

下面有一个图,把buffer的控制权流转画的特别好,直接引用:

dma-fence基本概念和原理都介绍完了。但是目前还看不到dma-fence是如何和KMS和DRM产生关联的。实际上DRM和dma-fence的关联是在drm_gem中,也就是dma_resv;和KMS的关联都是在atomic_commit流程中。鉴于篇幅问题,这些问题留到下一章再看深入挖掘一下其中的原理。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值