C++ 为什么赢了';在Windows XP中拔下显示器后是否恢复Direct3D?

C++ 为什么赢了';在Windows XP中拔下显示器后是否恢复Direct3D?,c++,windows-xp,directx,direct3d,C++,Windows Xp,Directx,Direct3d,一个有趣的错误出现了,我没有运气。在使用本机代码的带窗口Direct3D9程序中,我使用以下类似的方法处理丢失的设备: void MyClass::RecoverFromDeviceLost(LPDIRECT3DDEVICE9 deviceToRecover, D3DPRESENT_PARAMETERS devicePresentParams ) { HRESULT hr = deviceToRecover->TestCooperativeLevel(); if(hr

一个有趣的错误出现了,我没有运气。在使用本机代码的带窗口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从电脑上切换开,我将永远不会收到
D3DERR\u DEVICELOST
。我从TestCooperativeLevel收到的唯一返回值是D3DERR\u 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调试运行时在远程调试上工作之后,我意识到重置函数一直失败的原因是因为存在未释放的资源。但是,当按照答案中所示应用时,完全相同的发布代码解决了问题。我确实验证了该程序没有在对recover函数的调用之间创建D3DPOOL_默认对象。如果按照此问题的代码段所示执行重置,Direct3D的结构中是否存在可能导致问题的内容

不久前,开发了一款多显示器应用程序。拔下显示器时,不会将其本身视为丢失的DX设备——“设备”是操作系统级的软件抽象,并且在拔下显示器时不会丢失

如果出于任何原因需要在运行时检测监视器的拔出,即使Win32 API EnumDisplayMonitors也无法满足要求。如中所述,此API查询默认情况下仅在“启动、登录或打开显示属性控制面板”时更新的驱动程序缓存。现在,我们只使用nVidia,它们通过NvCplRefreshConnectedDevices(链接到NvCpl.dll以使用它)公开强制缓存更新功能。无法说明ATI是否公开了类似的功能,或者是否需要公开


更重要的是,你确定某个裁判事件会迫使你恢复你的资源吗??我猜不是。我最后测试了另一个使用DirectX进行图形处理的程序,只是想看看问题是否只出在一个程序上。另一个应用程序在Windows XP中通过监视器拔出或KVM切换恢复,没有问题。这两个程序之间的主要区别在于工作程序使用DXUT管理Direct3d,而我在不工作的程序中执行所有手动管理。在梳理了DXUT源代码之后,我注意到他们使用了一种单步的设备恢复方法,它不依赖于在返回值之前从TestCooperativeLevel返回的
D3DERR\u 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)显示器,此代码确实会产生多次重置的副作用。

没错,拔出事件不会强制恢复Vista中的资源。我需要支持非NVIDIA卡,但我会查看驱动程序缓存,看看这是否会将我带到某个地方。我遇到了类似的情况,TestCooperativeLevel()返回了D3DERR_DEVICENOTRESET,但调用Reset()将失败。当TestCooperativeLevel()返回D3DERR_DEVICELOST时,我正在释放D3DPOOL_默认对象。解决方案是等待TestCooperativeLevel()返回D3DERR_DEVICENOTRESET;