当前位置: 首页 > news >正文

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 图形稳定性的关键机制,驱动程序需正确处理重置和资源清理,以避免系统崩溃或图形异常

 

相关文章:

  • el-row el-col
  • GPU架构
  • 1. 视频基础知识
  • tinyrenderer笔记(上)
  • openssl 生成自签名证书实现接口支持https
  • chili3d调试笔记12 deepwiki viewport
  • kubeadm部署k8s
  • XSS ..
  • K8S有状态服务部署(MySQL、Redis、ES、RabbitMQ、Nacos、ZipKin、Sentinel)
  • K8S使用--dry-run输出资源模版和兼容性测试
  • Eigen矩阵的平移,旋转,缩放
  • 【SpringBoot教程】SpringBoot自定义注解与AOP实现切面日志
  • 深入解析二维矩阵搜索:LeetCode 74与240题的两种高效解法对比
  • C语言 指针(7)
  • 【工具变量】数字人民币试点城市DID(2007-2024年)
  • 【心海资源】0U攻击工具|一键模仿地址生成+余额归集+靓号生成系统
  • 神经网络:节点、隐藏层与非线性学习
  • Ubuntu 系统详解
  • Unable to determine the device handle for GPU0000:82:00.0: Unknown Error
  • 知乎前端面试题及参考答案
  • 巴国家安全委员会授权军方自主决定对印反击措施
  • 巴基斯坦军方:印度向巴本土及巴控克什米尔发射导弹
  • 新闻1+1丨多地政府食堂开放“舌尖上的服务”,反映出怎样的理念转变?
  • 9金收官!跳水世界杯总决赛朱子锋、程子龙包揽男子10米台冠亚军
  • 校方就退60件演出服道歉:承诺回收服装承担相关费用,已达成和解
  • 研究完蚂蚁搬家,我好像明白了为什么我们总是堵车