EvtIddCxMonitorAssignSwapChain 错误处理

EvtIddCxMonitorAssignSwapChain 错误处理中的更改

在版本 1903 之前的 Windows 10 版本中,其余桌面组合不知道 EvtIddCxMonitorAssignSwapChain 是否失败。 它继续呈现间接显示适配器未处理的帧,导致 IddCx 在一段时间后终止间接显示驱动程序(IDD)。

从 Windows 10 版本 1903(IddCx 1.4 开始),此回调的 IddCx 错误处理已针对所有驱动程序版本进行了更改,并引入了 STATUS_GRAPHICS_INDIRECT_DISPLAY_ABANDON_SWAPCHAIN 状态代码。 有关详细信息,请参阅 EvtIddCxMonitorAssignSwapChain

处理帧处理循环线程中的错误

IDD 成功从 EvtIddCxMonitorAssignSwapChain 返回后,它拥有 hSwapChain 对象。 如果驱动程序遇到阻止它继续处理帧的错误,则可以调用 WdfObjectDelete 来释放所有权。 OS 将检测删除,并导致创建新的交换链。

如果驱动程序知道无法从此错误中恢复,则应调用 IddCxReportCriticalError 停止设备。

处理交换链错误的建议方法

EvtIddCxMonitorAssignSwapChain 回调或处理帧时失败的原因有多种。 失败分类包括:

  • 特定于解决方案的暂时性问题,例如硬件的临时问题。 可以使用轻型恢复机制来修复此类问题,这些机制不会影响用户体验,因为恢复速度很快(通常在第二秒以下)且不会影响屏幕上的视觉内容(例如,没有闪烁)。
  • 特定于解决方案的永久问题,例如驱动程序中的死锁或硬件的严重问题。 通常,如果根本无法从快速恢复此类问题。
  • 由驱动程序外部的事件导致的 DirectX API 错误。 例如,驱动程序无法控制事件,例如,当 D3D 设备处理桌面映像的适配器处于 PnpStopped 或出现 GPU 范围的故障并重置时。
  • 驱动程序导致的 DirectX API 错误。 驱动程序 bug 可能会导致 D3D 设备出错或挂起。 例如,使用纹理边界外的坐标调用 CopySubResource 会将设备置于错误状态。
  • 由另一个 IHV GPU 驱动程序导致的 DirectX API 错误。 这些错误可能是 IDD 中触发 IHV GPU 驱动程序 bug 的正确调用模式的结果。

驱动程序很难准确区分不同的 DirectX 错误。 主要区别在于,外部 DirectX 组件导致的错误可能是暂时性的,系统将恢复到稳定状态:而如果错误是由间接显示或 GPU 驱动程序引起的,则 bug 可能会再次发生。

有关如何 将这些错误传播回 OS 的详细信息,请参阅 EvtIddCxMonitorAssignSwapChain ,以便 OS 将重试。

下面是有关如何处理驱动程序中每种错误类型的指南。

特定于解决方案的暂时性问题

驱动程序在处理帧时应修复此问题。 此操作可能会导致处理帧时出现较小的延迟。 如果错误定期发生,驱动程序可以考虑将错误抢占到永久性问题。

特定于解决方案的永久问题

驱动程序应使用等于或高于0x100的主要代码调用 IddCxReportCriticalError ,并使用唯一的主要/次要代码来表示错误类型以帮助客户/遥测调查。

DirectX 错误

处理 DirectX 错误的最简单方法是将它们传播回 OS,以便再次重试。 驱动程序应从 EvtIddCxMonitorAssignSwapChain 返回STATUS_GRAPHICS_INDIRECT_DISPLAY_ABANDON_SWAPCHAIN,或者,如果在处理帧时出错,驱动程序应通过调用 WdfObjectDelete 释放交换链。

这种简单的方法处理外部事件触发的错误,因为 OS 会稳定下来并创建新的交换链(可能位于新的 Dxgi 适配器上)。 如果驱动程序使用 DirectX 受到限制,则此方法非常有效。

对于可能因 IDD 中的 bug 或旧版 DirectX 驱动程序上运行的驱动程序而导致的 DirectX 错误的更复杂的驱动程序,此方法可能会以无休止的 ID 交换链故障循环结束。 为了避免无休止的循环,IDD 可以监视这些错误的频率,并在给定阶段达到足够的错误周期时经历恢复阶段。 如果遇到 DirectX 错误,驱动程序必须销毁 DX 设备并创建新设备,因为一旦 DX 设备处于错误状态,它永远不会恢复,需要重新创建。

当前阶段 如果驱动程序检测到连续交换链 DirectX 错误过多,则执行驱动程序操作
EvtIddCxMonitorAssignSwapChain提供的呈现适配器 LUID 是硬件适配器 使用 Dxgi 查找软件适配器的 LUID,并调用 IddCxAdapterSetRenderAdapter 来请求 OS 使用软件适配器来呈现桌面。
EvtIddCxMonitorAssignSwapChain提供的呈现适配器 LUID 是软件适配器 驱动程序应使用等于或高于0x100的主要代码调用 IddCxReportCriticalError ,并使用唯一的主要/次要代码来表示错误类型以帮助客户/遥测调查

例如,驱动程序可以考虑在 EvtIddCxMonitorAssignSwapChain连续出现五次 DirectX 故障,或者在处理帧时,使用 1 分钟作为条件来处理上表中当前阶段的恢复操作。