c++ - 为什么在 Windows XP 中拔下显示器后 Direct3D 无法恢复?

标签 c++ windows-xp directx direct3d

出现了一个有趣的错误,但我没有运气。在使用 native 代码的窗口化 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,目前无法更新。有没有人以前遇到过这个问题,或者知道为什么我无法重置我的设备?

更新:我相信我有 found a solution ,但我仍然对上面列出的第二个代码段的失败感到困惑。在让DirectX Debug运行时在远程调试工作后,我意识到Reset函数一直失败的原因是因为有未释放的资源。然而,完全相同的发布代码,如答案所示应用时,解决了这个问题。我确实验证了程序在调用恢复函数之间没有创建 D3DPOOL_DEFAULT 对象。 Direct3D 的结构中是否有某些东西可能会导致问题,如果执行此问题的代码段中所示的重置?

最佳答案

我最终测试了一个使用 DirectX 处理图形的不同程序,只是想看看问题是否出在这个程序上。另一个应用程序从 Windows XP 中的显示器拔出或 KVM 切换中恢复,没有任何问题。这两个程序之间的主要区别在于,工作的那个使用 DXUT 来管理 Direct3d,而我在那个不起作用的那个中进行所有手动管理。梳理 DXUT 源代码后,我注意到他们使用单步方法进行设备恢复,不依赖于 D3DERR_DEVICENOTRESET 之前从 TestCooperativeLevel 返回的 D3DERR_DEVICELOST返回值。下面的代码似乎解决了这个问题:

void MyClass::RecoverFromDeviceLost(LPDIRECT3DDEVICE9 deviceToRecover, D3DPRESENT_PARAMETERS devicePresentParams )
{

    HRESULT hr = deviceToRecover->TestCooperativeLevel();
    if(hr == D3DERR_DEVICELOST ) { 
        //Device is lost and cannot be reset yet
        return;
    }


    //Code to shutdown all D3DPOOL_DEFAULT allocated objects

    hr=deviceToRecover->Reset(&devicePresentParams);
    if(SUCCEEDED(hr)){

        //Code to rebuild all D3DPOOL_DEFAULT objects

    }
}

如果显示器长时间未插电(或切换 KVM),此代码确实会产生多次重置的副作用。

关于c++ - 为什么在 Windows XP 中拔下显示器后 Direct3D 无法恢复?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1462078/

相关文章:

c++ - 获取窗口样式

linux - 代理设置不起作用

c# - C# 中的平滑视频渲染

c++ - 使用并行处理在 C++ 中制作游戏

c++ - linux中动态链接库的开源c++代码覆盖率

c++ - 减小 Qt GUI 应用程序的大小

c++ - 如何在Arduino上使用char数组实现函数

c++ - 保护应用程序的内存不被篡改

python - 将参数从批处理文件发送到 Python 脚本

c++ - 在 Directx 中加载纹理