GPU preemption
一种新的GPU 抢占模型从Windows 8开始使用。在这种模型下OS不在允许禁用用于抢占的GPU DMA(direct memory access)包,即保障了在TDR(Timeout Detection and Recovery)过程开始之前抢占请求会被发送到GPU。
Minimum Windows Display Driver Model (WDDM) version | 1.2 |
Minimum Windows version | 8 |
Driver implementation—Full graphics and Render only | Mandatory |
WHCK requirements and tests | Device.Graphics…Preemption Test Device.Graphics…FlipOnVSyncMmIo |
如果需要长时间运行的DMA packets不能被更高优先级成功抢占,则类似DWM需要进行的操作将会被延迟,结果就是导致窗口的过渡和动画产生撕裂。同样,需要长时间运行的DMA packets如果不能被抢占,则会引起TDR过程,其会不断尝试重置GPU而最终引发OS BSOD。
Note All 所有WDDM 1.2的KMD必须支持Windows 8的抢占模型。但是,WDDM 1.2 驱动能拒绝使用Windows 8的抢占模型而继续保持Windows 7的行为,其由DXGK子系统Scheduler控制。
GPU preemption device driver interfaces (DDIs)
KMD可用下列DDI实现Windows 8 GPU抢占模型
- DxgkCbCreateContextAllocation
- DxgkCbDestroyContextAllocation
- pfnSetPriorityCb
- Dxgkrnl Interface
- DXGKRNL_INTERFACE
- D3DKMDT_COMPUTE_PREEMPTION_GRANULARITY
- D3DKMDT_GRAPHICS_PREEMPTION_GRANULARITY
- D3DKMDT_PREEMPTION_CAPS
- D3DKMT_QUERYADAPTERINFO
- DXGK_DRIVERCAPS
- DXGK_SUBMITCOMMANDFLAGS
- DXGK_VIDSCHCAPS
- DXGKARGCB_CREATECONTEXTALLOCATION
Display miniport driver implementation
下列时在KMD中实现Windows 8 GPU 抢占模型的基础步骤:
- 编译含有DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN8 语句的头文件。
- 通过设置DXGK_VIDSCHCAPS成员 PreemptionAware and MultiEngineAware 为1来表明驱动支持Windows 8 GPU 抢占模型。要支持Windows 7的抢占模型则设置 PreemptionAware 为0。
- 通过D3DKMDT_PREEMPTION_CAPS结构来指定驱动所支持的抢占粒度,其接受枚举D3DKMDT_GRAPHICS_PREEMPTION_GRANULARITY和D3DKMDT_COMPUTE_PREEMPTION_GRANULARITY的常量值。
- 如果硬件支持 lazy context 切换,通过DxgkDdiSubmitCommand提交一个非零长度的buffer然后设置pSubmitCommand->Flags->ContextSwitch 为1开启该特性。这里的ContextSwitch 是DXGK_SUBMITCOMMANDFLAGS中的成员。
- 通过DxgkCbCreateContextAllocation方法中可以设置GPU Context allocation和Device Context allocation。具体的指令和限制在DxgkCbCreateContextAllocation的Remark中列出。
- 调用DxgkCbDestroyContextAllocation来销毁GPU context allocation 和 device context allocation,这两种allocation由DxgkCbCreateContextAllocation创建。
- 当DxgkDdiBuildPagingBuffer中准备DMA buffer时会通过填充DXGKARG_BUILDPAGINGBUFFER成员InitContextResource 来初始化context资源。如果context资源被evict或relocat,VMM将保存保存context资源的内容。
- 驱动必须支持下一代V SYNC中的memory-mapped I/O flip特性。在Windows 8中,GPU Scheduler尝试抢占硬件,即使flip处于pending状态。因此,为了保持正常渲染工作及避免撕裂, 驱动必须支持memory-mapped I/O flip模型,这需要设置DXGK_FLIPCAPS中FlipOnVSyncMmIo成员为1,并在FlipOnVSyncMmIo成员中描述所支持的操作。
Memory mapping considerations in your implementation
创造一个健壮并且提供良好用户体验的拥有Windows 8 GPU 抢占模型的驱动,需要遵守下列规则
- 当DXGK(Dxgkrnl) Scheduler发送抢占命令时,能抢占请求GPU执行 mid-DMA buffer抢占 。支持mid-DMA buffer粒度抢占的硬件设备会给用户更好的体验。
- 允许paging命令fence IDfence ID重用:如果抢占请求导致抢占硬件队列中的paging命令,Dxgkrnl Scheduler会使用和先前同样的fence id重新提交被抢占的paging命令,随后该paging命令会比在其引擎上的其他命令优先调度。非Paging命令会被使用新的fence ID进行重新提交。
- 需要为分割的DMA buffer提供patch location list - 参考 Splitting a DMA Buffer
- 一种叫绑定泄露检测(binding leak detection)验证模式能够用来遍历patch location list和拒绝未绑定的packets或未reprogram allocation得分割packet。有些硬件支持VA,允许更多的间接层级,就可以不进行验证。这种情况下需要指定驱动不进行驱动验证模式,可设置DXGK_VIDSCHCAPS中NoDmaPatching为1。
- 在Windows 7中,Dxgkrnl Scheduler保证所有对应相同的渲染命令的分割DMA包都被连续执行而不会被切换到其他渲染context。在Windows 8的抢占模型中,Scheduler能够在属于同一个渲染命令的两个分割DMA包之间执行另一个Context的渲染包。因此,支持抢占的驱动应该像处理其他普通的完整包提交一样处理分割/局部的DMA提交。特别是要能在类似提交的边界上进行GPU状态必须保存或恢复。
- 当分割DMA buffer的内容在LDA模式中多个显卡间广播时,支持抢占的驱动不能改变分割DMA buffer的内容。LDA中多个物理GPU被连接形成单个更快的虚拟GPU。因为Windows 8 抢占模型中,Dxgkrnl Scheduler不在保证分割包序列的执行同步而不被切换到其他的context。修改了分割包的内容的驱动会在数据的完整性上有妥协,因为如果这些包在其他引擎上被执行,包中的命令会操作同样的DMA buffer的数据。
- 在Windows 8 GPU抢占模型中,Dxgkrnl Scheduler允许抢占包关联"signal on submit "同步原语。如果一个设备在同步时使用"signal on submit"同步原语处于基于硬件的等待状态,这个设备必须支持在等待状态被满足之前有能力抢占一个等待命令(PS: 即本来正在执行等待指令,然后该等待指令被抢占了,也就让GPU重新恢复了运行)。
Hardware certification requirements
如果设备硬件需要实现该特性硬件设备需要达到的要求可以参见相关的WHCK documentation 主题的Device.Graphics…Preemption Test 和 Device.Graphics…FlipOnVSyncMmIo.
参见WDDM 1.2 features 查看Windows 8中加入的新特性