我遇到了一个有趣的 bug,但是一直找不到解决办法。在一个使用本地代码的窗口化 Direct3D9 程序中,我使用类似于以下的处理方式来处理设备丢失:
void MyClass::RecoverFromDeviceLost(LPDIRECT3DDEVICE9 deviceToRecover, D3DPRESENT_PARAMETERS devicePresentParams )
{
HRESULT hr = deviceToRecover->TestCooperativeLevel();
if(hr == D3DERR_DEVICELOST ) {
//Code to shutdown all D3DPOOL_DEFAULT allocated objects
}else if(hr == D3DERR_DEVICENOTRESET){
hr = deviceToRecover->Reset(&devicePresentParams);
if(SUCCEEDED(hr))
{
//Code to rebuild all D3DPOOL_DEFAULT objects
}
}
}
这在Vista上运行良好,但在XP上似乎存在严重问题。如果监视器被拔掉或通过KVM切换到PC之外,我从未收到过 D3DERR_DEVICELOST
。我收到的唯一的TestCooperativeLevel返回值是 D3DERR_DEVICENOTRESET
。每次调用Reset都会给出一个D3DERR_INVALIDCALL。我尝试通过以下方式强制程序使用关闭代码:
...
else if(hr == D3DERR_DEVICENOTRESET){
hr = deviceToRecover->Reset(&devicePresentParams);
if(SUCCEEDED(hr))
{
//Code to rebuild all D3DPOOL_DEFAULT objects
}else {
//Duplicate of code to shutdown all D3DPOOL_DEFAULT objects
}
}
...
但是没有任何变化。这个问题似乎只影响Windows XP(到目前为止已在SP2、SP3上测试)。我正在使用2007年8月的DXSDK,目前无法更新。有人之前见过这个问题吗?或者有什么想法,为什么我不能重置我的设备?
更新: 我相信我已经找到了解决方案,但仍然对此问题中列出的第二个代码段的失败感到困惑。通过远程调试使DirectX调试运行时正常工作后,我意识到Reset函数一直失败的原因是存在未释放的资源。然而,完全相同的释放代码,按照答案所示应用,解决了这个问题。我确保程序在调用恢复函数之间没有创建D3DPOOL_DEFAULT对象。在Direct3D的结构中是否有什么可能导致像本问题中展示的代码段执行重置时出现问题的因素?