window 显示驱动开发-线程同步和 TDR

下图显示了 Windows 显示驱动程序模型 (WDDM) 中显示微型端口驱动程序的线程同步的工作原理

如果发生硬件超时,则会启动 超时检测和恢复 (TDR) 进程。 GPU 计划程序调用驱动程序的 DxgkDdiResetFromTimeout 函数,这将重置 GPU。 DxgkDdiResetFromTimeout 与任何其他显示微型端口驱动程序函数同步调用,运行时电源管理功能 DxgkDdiSetPowerComponentFState 和 DxgkDdiPowerRuntimeControlRequest 除外。 也就是说, 在 DxgkDdiResetFromTimeout 线程运行时,驱动程序中没有其他线程运行。 操作系统还保证在调用 DxgkDdiResetFromTimeout 期间,任何应用程序都无法访问帧缓冲区;因此,驱动程序可以重置内存控制器相位锁定循环 (PLL) 等。

当恢复线程执行 DxgkDdiResetFromTimeout 时,可以继续调用中断和延迟过程调用 (DPC) 。 KeSynchronizeExecution 函数可用于将重置过程的某些部分与设备中断同步。

驱动程序从 DxgkDdiResetFromTimeout 返回后,可以再次调用大多数驱动程序函数,并且操作系统开始清理不再需要的资源。 在清理期间,出于指示的原因调用以下驱动程序函数:

  • 调用驱动程序以通知正在逐出分配。

例如,如果分配是在内存段中分页的,则会调用驱动程序的 DxgkDdiBuildPagingBuffer 函数,并将 DXGKARG_BUILDPAGINGBUFFER 结构的 Operation 成员设置为 DXGK_OPERATION_TRANSFER,Transfer.Size 成员设置为零,以通知驱动程序有关逐出的信息。 请注意,由于内容在重置期间丢失,因此不涉及内容传输。

如果分配是在光圈段中分页的,则会调用驱动程序的 DxgkDdiBuildPagingBuffer 函数,并将 DXGKARG_BUILDPAGINGBUFFER 的 Operation 成员设置为 DXGK_OPERATION_UNMAP_APERTURE_SEGMENT,以通知驱动程序取消映射光圈中的分配。

  • 调用驱动程序的 DxgkDdiReleaseSwizzlingRange 函数来释放不重排光圈和段光圈范围。

除非绝对必要,否则驱动程序不应在上述调用期间访问 GPU。

清理期结束后,操作系统调用驱动程序的 DxgkDdiRestartFromTimeout 函数,以通知驱动程序清理已完成,操作系统将恢复使用适配器进行呈现。

 1. TDR 触发条件

  • GPU 长时间未响应(通常由于 命令队列卡死、硬件故障 或 驱动死锁)。
  • Windows GPU 调度器检测到超时,并启动恢复流程。

2. TDR 核心流程

(1) 调用 DxgkDdiResetFromTimeout(GPU 重置)
同步性:

  • 此函数是 完全同步调用,即在执行期间:
  • 禁止其他任何驱动线程运行(除了 DxgkDdiSetPowerComponentFState 和 DxgkDdiPowerRuntimeControlRequest)。
  • 应用程序无法访问帧缓冲区(确保内存安全)。
  • 操作系统保证 GPU 处于 可安全重置 的状态。

驱动职责:

  • 重置 GPU 硬件(如寄存器、PLL、内存控制器等)。
  • 清理 GPU 内部状态(如命令队列、缓存)。

可调用 KeSynchronizeExecution 与设备中断同步(避免竞争条件)。

(2) 中断和 DPC 处理
中断和 DPC(延迟过程调用)仍可继续执行,但驱动程序需确保:

  • 不会与 DxgkDdiResetFromTimeout 冲突(如使用自旋锁保护关键代码)。

(3) 重置完成后的资源清理
在 DxgkDdiResetFromTimeout 返回后,操作系统开始 清理无效资源,并调用以下驱动函数:

驱动函数调用原因参数说明
DxgkDdiBuildPagingBuffer通知分配被逐出Operation = DXGK_OPERATION_TRANSFERTransfer.Size = 0):表示内存段分配被逐出(无数据传输,因内容已丢失)。
Operation = DXGK_OPERATION_UNMAP_APERTURE_SEGMENT:取消映射光圈段(Aperture Segment)中的分配。
DxgkDdiReleaseSwizzlingRange释放 Swizzling Range清理所有不再需要的重排范围(Swizzling Range)。

关键注意事项:

  • 驱动程序应避免访问 GPU,除非绝对必要(如释放硬件资源)。
  • 不涉及数据传输(因为 GPU 重置后显存内容已丢失)。

(4) 调用 DxgkDdiRestartFromTimeout(恢复呈现)
清理完成后,操作系统调用 DxgkDdiRestartFromTimeout,通知驱动:

  • TDR 恢复流程结束。
  • GPU 可以重新用于图形渲染。

驱动应:

  • 重新初始化必要的硬件状态(如默认分辨率、颜色格式)。
  • 恢复 GPU 调度器工作(允许提交新命令)。

3. 驱动开发注意事项

(1) 线程安全性
DxgkDdiResetFromTimeout 运行期间,禁止其他驱动线程运行,但仍需:

  • 保护共享硬件资源(如 MMIO 寄存器)。
  • 避免死锁(如不等待可能被阻塞的锁)。

(2) 内存管理
显存内容在重置后丢失,因此:

  • 驱动不应尝试恢复旧数据。
  • 应用程序需重新提交丢失的资源(如纹理、缓冲区)。

(3) 错误恢复
如果 DxgkDdiResetFromTimeout 失败:

  • 系统可能 完全禁用 GPU(降级到基本显示模式)。
  • 用户可能需要 重启系统 恢复功能。

(4) 调试支持
在 DxgkDdiCollectDbgInfo(Reason = VIDEO_TDR_TIMEOUT_DETECTED)中:

  • 记录足够信息(如最后提交的命令、GPU 状态)。
  • 确保代码可分页(PASSIVE_LEVEL)。

4. 典型 TDR 时序图

1. GPU 超时发生
   │
2. WDDM 检测超时,暂停 GPU 调度
   │
3. 调用 DxgkDdiResetFromTimeout (同步执行)
   │   ├─ 重置 GPU 硬件
   │   └─ 清理内部状态
   │
4. 操作系统清理资源:
   │   ├─ DxgkDdiBuildPagingBuffer (逐出分配)
   │   └─ DxgkDdiReleaseSwizzlingRange (释放范围)
   │
5. 调用 DxgkDdiRestartFromTimeout
   │
6. GPU 恢复工作,应用程序重新提交命令

5. 总结

阶段关键动作驱动职责
检测超时GPU 无响应无(系统自动触发)
重置 GPUDxgkDdiResetFromTimeout重置硬件,避免竞争
清理资源BuildPagingBuffer / ReleaseSwizzlingRange释放无效分配
恢复工作DxgkDdiRestartFromTimeout重新初始化 GPU

 TDR 是 Windows 图形稳定性的关键机制,驱动程序需正确处理重置和资源清理,以避免系统崩溃或图形异常

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值