线程同步和 TDR

下图显示了线程同步如何适用于 WDDM 中的内核模式显示微型端口驱动程序(KMD)。

WDDM 中线程同步的示意图。

如果发生硬件超时,系统将启动 超时检测和恢复(TDR) 进程。 GPU 计划程序调用驱动程序的 DxgkDdiResetFromTimeout 函数,这会重置 GPU:

  • DxgkDdiResetFromTimeout 与任何其他 KMD 函数同步调用,除了运行时电源管理功能 DxgkDdiSetPowerComponentFStateDxgkDdiPowerRuntimeControlRequest 之外。 也就是说,OS 保证 在 DxgkDdiResetFromTimeout 线程运行时,驱动程序中没有其他线程运行。
  • OS 还保证应用程序在调用 DxgkDdiResetFromTimeout 期间无法访问帧缓冲区。 因此,驱动程序可以重置内存控制器阶段锁定循环(PLL)等。

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

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

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

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

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

  • 驱动程序的 DxgkDdiReleaseSwizzlingRange 函数被调用,以释放一个不闪烁的光圈和段光圈范围。

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

清理期结束后,操作系统将调用驱动程序的 DxgkDdiRestartFromTimeout 函数,以通知驱动程序清理已完成,并且操作系统将继续使用适配器进行渲染。