处理错误
用户模式显示驱动程序实现的 Direct3D 版本 10 函数 通常具有返回参数类型的 VOID。 此规则的主要例外是 CalcPrivateObjTypeSize 类型函数 (例如 CalcPrivateResourceSize 函数) 。 此类型的函数返回一个SIZE_T参数类型,该参数类型指示驱动程序通过 CreateObjType 类型函数创建特定对象类型所需的内存区域的大小 (例如 CreateResource (D3D10) ) 。
返回 VOID 可防止用户模式显示驱动程序以传统方式通知 Direct3D 运行时错误 (,即通过用户模式显示驱动程序的函数返回参数) 。 相反,用户模式显示驱动程序必须使用 Direct3D 运行时的 pfnSetErrorCb 回调函数将此类信息传递回运行时。 运行时在调用 CreateDevice (D3D10 ) 函数时,向D3D10DDIARG_CREATEDEVICE结构的 pumCallbacks 成员指向的D3D10DDI_CORELAYER_DEVICECALLBACKS结构中的 pfnSetErrorCb 提供指针。
每个用户模式显示驱动程序函数的参考页指定该函数可以通过调用 pfnSetErrorCb 传递的错误。 这意味着,如果用户模式显示驱动程序使用当前用户模式显示驱动程序函数不允许的错误代码调用 pfnSetErrorCb ,则运行时将确定错误条件严重且行为适当。 由于运行时将在 pfnSetErrorCb 期间正常运行,因此不应期望通过调用 pfnSetErrorCb ( S_OK ) 之类的内容来扭转调用 pfnSetErrorCb ( E_FAIL ) 的影响。 事实上,运行时确定S_OK与E_FAIL一样无效或严重。 S_OK返回代码的概念等效于根本不调用 pfnSetErrorCb 的用户模式显示驱动程序函数。
如果 Direct3D 运行时确定错误条件严重,它将首先通过 Dr. Watson(默认事后 (实时) 调试器)记录错误来采取措施。 然后,运行时会故意丢失设备,从而模拟接收D3DDDIERR_DEVICEREMOVED错误代码的方案。 通过要求驱动程序调用 pfnSetErrorCb 回调函数,驱动程序发出的每个错误都有一个与之关联的有用调用堆栈的可能性要大得多。 使用与错误关联的调用堆栈可实现快速诊断和准确的 Dr. Watson 日志。
当驱动程序出现问题时,应在驱动程序代码中使用 pfnSetErrorCb ,即使返回运行时不允许特定驱动程序函数的错误代码由运行时确定为驱动程序 bug 或问题。 用户模式显示驱动程序吸收严重错误并继续操作会更糟。 用户模式显示驱动程序应尽可能靠近错误检测点调用 pfnSetErrorCb ,以便为事后调试提供有用的调用堆栈。
下表列出了 Direct3D 运行时允许来自特定驱动程序函数的错误类别。
错误类别 | 含义 |
---|---|
NoErrors |
驱动程序不应遇到任何错误,包括D3DDDIERR_DEVICEREMOVED。 运行时将确定对 pfnSetErrorCb 的任何调用都至关重要。 |
AllowDeviceRemoved |
驱动程序不应遇到除D3DDDIERR_DEVICEREMOVED以外的任何错误。 运行时将确定对 pfnSetErrorCb 的任何未传递D3DDDIERR_DEVICEREMOVED的调用都至关重要。 如果设备已被移除,则驱动程序不需要返回 DEVICEREMOVED。 但是,运行时允许驱动程序返回 DEVICEREMOVED,以防 DEVICEREMOVED 干扰驱动程序函数,这通常不应发生。 |
AllowOutOfMemory |
驱动程序可能内存不足。 因此,驱动程序可以通过 pfnSetErrorCb 传递E_OUTOFMEMORY和D3DDDIERR_DEVICEREMOVED。 运行时将确定任何其他错误代码是否严重。 |
AllowCounterCreationErrors |
驱动程序可能内存不足。 由于计数器的独占性,驱动程序也可能无法创建计数器。 因此,驱动程序可以通过 pfnSetErrorCb 传递E_OUTOFMEMORY、DXGI_DDI_ERR_NONEXCLUSIVE和D3DDDIERR_DEVICEREMOVED。 运行时将确定任何其他错误代码是否严重。 |
AllowMapErrors |
驱动程序应检查资源争用。 因此,如果将D3D10_DDI_MAP_FLAG_DONOTWAIT标志传递到驱动程序的 ResourceMap 函数中,驱动程序可以通过 pfnSetErrorCb 传递DXGI_DDI_ERR_WASSTILLDRAWING。 驱动程序还可以通过 pfnSetErrorCb 传递D3DDDIERR_DEVICEREMOVED。 运行时将确定任何其他错误代码是否严重。 |
AllowGetDataErrors |
驱动程序应检查查询完成。 因此,如果查询尚未完成,驱动程序可以通过 pfnSetErrorCb 传递DXGI_DDI_ERR_WASSTILLDRAWING。 驱动程序还可以通过 pfnSetErrorCb 传递D3DDDIERR_DEVICEREMOVED。 运行时将确定任何其他错误代码是否严重。 |
AllowWKCheckCounterErrors |
驱动程序的 CheckCounter 函数应指示它是否支持任何运行时定义的计数器。 因此,驱动程序可以通过 pfnSetErrorCb 传递DXGI_DDI_ERR_UNSUPPORTED。 运行时将确定任何其他错误代码是否严重。 驱动程序无法为任何检查类型函数返回D3DDDIERR_DEVICEREMOVED。 |
AllowDDCheckCounterErrors |
驱动程序应验证与设备相关的计数器标识符 (计数器 ID) ,以确保计数器 ID 在范围内,并且有足够的空间将每个计数器字符串复制到提供的缓冲区中。 当参数以这种方式不正确时,驱动程序可以通过 pfnSetErrorCb 传递E_INVALIDARG。 驱动程序无法为任何检查类型函数返回D3DDDIERR_DEVICEREMOVED。 |