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 错误。 驱动程序错误可能会导致 D3D 设备进入错误状态或挂起。 例如,使用纹理边界外的坐标调用 CopySubResource 会将设备置于错误状态。
- 由另一个 IHV GPU 驱动程序导致的 DirectX API 错误。 这些错误可能是由 IDD 中触发 IHV GPU 驱动程序错误的正确调用模式所致的结果。
驱动程序很难准确区分不同的 DirectX 错误。 主要区别在于,外部 DirectX 组件导致的错误可能是暂时性的,系统将恢复到稳定状态:而如果错误是由间接显示或 GPU 驱动程序引起的,则 bug 可能会再次发生。
有关如何将这些错误传播回操作系统以使其进行重试的详细信息,请参阅EvtIddCxMonitorAssignSwapChain。
下面是有关如何处理驱动程序中每种错误类型的指南。
您的解决方案特有的暂时性问题
驱动程序在处理帧时应修复此问题。 此作可能会导致处理帧时出现较小的延迟。 如果错误定期发生,驱动程序可以考虑在问题变得永久前加以预防。
与你的解决方案相关的永久问题
驱动程序应使用等于或高于0x100的主要代码调用 IddCxReportCriticalError ,并使用唯一的主要/次要代码来表示错误类型以帮助客户/遥测调查。
DirectX 错误
处理 DirectX 错误的最简单方法是将它们传播回 OS,以便再次重试。 驱动程序应从EvtIddCxMonitorAssignSwapChain返回STATUS_GRAPHICS_INDIRECT_DISPLAY_ABANDON_SWAPCHAIN,或者,如果在处理帧时出错,驱动程序应通过调用WdfObjectDelete来释放交换链。
这种简单的方法处理外部事件触发的错误,因为 OS 会稳定下来并创建新的交换链(可能位于新的 Dxgi 适配器上)。 如果驱动程序使用 DirectX 受到限制,则此方法非常有效。
对于可能因 IDD 中的错误或旧版/有缺陷的 DirectX 驱动程序上的驱动程序而导致 DirectX 错误的更复杂的驱动程序,此方法可能会导致 ID 交换链出现无休止的故障循环。 为了避免无休止的循环,IDD 可以监视这些错误的频率,并在一个阶段的错误次数达到一定数量时依次进入多个恢复阶段。 如果遇到 DirectX 错误,驱动程序必须销毁 DX 设备并创建新设备,因为一旦 DX 设备处于错误状态,它永远不会恢复,需要重新创建。
| 当前阶段 | 如果驱动程序检测到连续的交换链 DirectX 错误过多,将采取相应措施。 |
|---|---|
| EvtIddCxMonitorAssignSwapChain 中提供的渲染适配器 LUID 是硬件适配器 | 使用 Dxgi 查找软件适配器的 LUID,并调用 IddCxAdapterSetRenderAdapter 来请求 OS 使用软件适配器来呈现桌面。 |
| EvtIddCxMonitorAssignSwapChain 中提供的呈现适配器 LUID 是软件适配器 | 驱动程序应使用等于或高于0x100的主要代码调用 IddCxReportCriticalError ,并使用唯一的主要/次要代码来表示错误类型以帮助客户/遥测调查 |
例如,驱动程序可以考虑在EvtIddCxMonitorAssignSwapChain中连出现五次 DirectX 故障,或在处理帧时失败五次,并以 1 分钟为标准来决定进行上表中当前阶段的恢复行动。