首先从WDDM驱动的框架图中来看看Driver是需要做什么事情的。下图中的带有灰色背景的就是GPU厂商提供的Driver需要实现的内容。 2.jpg

以一个简单的例子来看他们具体是怎么工作的: 1.jpg

1. Rendering Device 的创建

1、APPlication申请创建渲染设备时,display minport driver会接收到DxgkDdiCreateDevice的一个调用。 display minport driver通过返回的DXGK_DEVICEINFO结构体指针(包含在DXGKARG_CREATEDEVICE结构体中)来初始化DMA

2、如果DxgkDdiCreateDevice调用成功了,D3D runtime就会调用User Mode Driver的 CreateDevice函数。

3、在CreateDevice函数中,User Mode Driver必须显式地调用pfnCreateContextCb函数,用来创建一个或者多个context(运行在新创建的设备的上的GPU线程)。D3D runtime通过D3DDDICB_CREATECONTEXT结构体中的pCommandbuffer和CommandBufferSize两个成员。

2. surface的创建

4、在应用程序申请Create Surface之后,D3D runtime就会调用user mode driver中的CreateResource函数。

5、user mode driver中的CreateResource函数调用Runtime提供的pfnAllocateCb函数。

6、display miniport driver接收一个DxgkDdiCreateAllocation的调用,调用里面指定了创建和分配的数量和类型。DxgkDdiCreateAllocation返回结构体DXGKARG_CREATEDALLOCATION结构体中的DXGK_ALLOCATIONINFO。

3.渲染命令发送给Kernel Mode

7、AP申请绘制一个surface之后,D3D runtime 调用User mode driver中与绘制相关的调用,比如DrawPrimitive。

8、为了提交command buffer到kernel mode driver,D3D runtime调用User mode里面的Present或者是Flush函数。或者在command buffer内容满了的时候也会向Kernel mode进行提交。

9、user mode driver调用runtime中提供的pfnPrensentCb或者pfnFlushCb,分别对应上述中Present或者是Flush函数。

10、如果上述中的pfnPrensentCb运行,display minport driver就会接收到DxgkDdiRender的调用。display minport driver验证command buffer,以硬件所需要的格式将内容写到DMA里面。并且生成一个描述绘制表面的清单。

4. DMA bufffer提交给硬件

11、DirectX graphics kernel 子系统调用display minport driver中的DxgkDdiBuildPagingBuffer用来创建特定功能的DMA buffer(称为paging buffer,它将表面清单移动到GPU的内存中)。

12、DirectX graphics kernel 子系统调用display minport driver中的DxgkDdiSubmitCommand函数,将paging buffer排列到GPU的执行单元中。

13、DirectX graphics kernel 子系统调用display minport driver中的DxgkDdiPatch函数,将物理地址赋值到DMA的资源buffer中。

14、DirectX graphics kernel 子系统调用display minport driver中的DxgkDdiSubmitCommand函数,将paging buffer排列到GPU的执行单元中。每一个向GPU提交的DMA缓冲区包含一个标识符(是一个数字),GPU完成对DMA缓冲区的处理之后生成一个中断。

15、DxgkDdiInterruptRoutine函数会通知display minport driver去从GPU中读取刚刚完成的DMA缓冲。

16、display minport driver应该调用DxgkCbNotifyInterrupt函数来通知DirectX graphics kernel 子系统读取DMA缓冲已经完成,display minport driver还将调用DxgkCbQueueDpc函数来对排队一个延期过程调用(DCP,deferred procedure call)。