在Windows XP中拔下监视器后,为什么Direct3D无法恢复? [英] Why won't Direct3D recover after unplugging a monitor in Windows XP?

查看:153
本文介绍了在Windows XP中拔下监视器后,为什么Direct3D无法恢复?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

出现了一个有趣的错误,我没有运气。在使用本机代码的Direct3D9窗口化程序中,我使用类似于以下内容的方法处理丢失的设备:

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


HRESULT hr = deviceToRecover-> TestCooperativeLevel();
if(hr == D3DERR_DEVICELOST){
//关闭所有D3DPOOL_DEFAULT分配对象的代码

}否则if(hr == D3DERR_DEVICENOTRESET){

hr = deviceToRecover-> Reset(& devicePresentParams);
if(SUCCEEDED(hr))
{
//重建所有D3DPOOL_DEFAULT对象的代码

}

}

}

在Vista上运行良好,但在XP上似乎存在重大问题。如果断开显示器的连接,或者通过KVM将显示器从PC上断开,我将永远不会收到 D3DERR_DEVICELOST 。我曾经从TestCooperativeLevel收到的唯一返回值是 D3DERR_DEVICENOTRESET 。每次调用Reset都会得到一个D3DERR_INVALIDCALL。我试图通过执行以下操作来强制程序使用关闭代码:

  ... 
else if(hr = = D3DERR_DEVICENOTRESET){

hr = deviceToRecover-> Reset(& devicePresentParams);
if(SUCCEEDED(hr))
{
//重建所有D3DPOOL_DEFAULT对象的代码

} else {
//要关闭的重复代码所有D3DPOOL_DEFAULT对象
}

}
...

但是没有变化。此问题似乎仅影响Windows XP(到目前为止已在SP2,SP3上进行了测试)。我正在使用2007年8月的DXSDK,目前无法更新。有没有人见过这个问题,或者有任何想法为什么我无法重置设备?



更新:我相信我有找到了解决方案,但是上面列出的第二个代码段的失败仍然让他们感到困惑。在使DirectX Debug运行时可以通过远程调试工作之后,我意识到Reset函数一直失败的原因是因为存在未释放的资源。但是,按照答案中的说明使用完全相同的发行版代码可以解决此问题。我确实验证了该程序没有在调用recovery函数之间创建D3DPOOL_DEFAULT对象。如果执行本问题的代码段所示的重置操作,Direct3D的结构中是否存在可能导致问题的问题?

解决方案

我最终测试了另一个使用DirectX进行图形处理的程序,只是看问题是否出在一个程序上。从Windows XP中的监视器拔出或KVM切换中,其他应用程序都恢复正常。这两个程序之间的主要区别在于,可以运行的程序使用DXUT来管理Direct3d,而我正在使用不起作用的程序进行所有手动管理。梳理完DXUT源代码后,我注意到他们使用了一步恢复设备的方法,该方法不依赖于 D3DERR_DEVICELOST 在<$之前从TestCooperativeLevel返回。 c $ c> D3DERR_DEVICENOTRESET 返回值。以下代码似乎已解决了该问题:

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

HRESULT hr = deviceToRecover-> TestCooperativeLevel();
if(hr == D3DERR_DEVICELOST){
//设备丢失并且无法重置,但是
返回;
}


//关闭所有D3DPOOL_DEFAULT分配对象的代码

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

//用于重建所有D3DPOOL_DEFAULT对象的代码

}
}

如果监视器长时间不插电(或KVM切换),此代码的确会产生多次重置的副作用。 / p>

An interesting bug came up that I'm having no luck with. In a windowed Direct3D9 program using native code, I handle a device lost using something similar to the following:

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

        }

    }

}

This works fine on Vista, but seems to have major problems on XP. If the monitor is unplugged, or switched away from the PC via a KVM, I never receive the D3DERR_DEVICELOST. The only return value from TestCooperativeLevel I ever receive is D3DERR_DEVICENOTRESET. And every call to Reset gives a D3DERR_INVALIDCALL. I tried forcing the program to use the shutdown code by doing this:

...
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
        }

    }
...

But there was no change. This problem only seems to affect Windows XP (so far tested on SP2, SP3). I am using the August 2007 DXSDK, and can't update at this time. Has anyone seen this problem before, or have any idea why I can't reset my device?

UPDATE: I believe I have found a solution, but am still perplexed by the failure of the second code segment listed above. After getting the DirectX Debug runtime to work over remote debugging, I realized the reason that the Reset function kept failing was because there were unreleased resources. However, the exact same release code, when applied as shown in the answer, resolved the issue. I did verify that the program was not creating D3DPOOL_DEFAULT objects between calls to the recover function. Is there something in the structure of Direct3D that could cause a problem if performing a reset as shown in the this question's code segments?

解决方案

I ended up testing a different program that uses DirectX for graphics, just to see if the problem was just with the one program. The other application recovered with no problems from a monitor unplug or KVM switchover in Windows XP. The main difference between the two programs was that the working one used DXUT to manage the Direct3d, whereas I was doing all manual management in the one that didn't work. After combing through the DXUT source code, I noticed that they used a single step approach to device recovery that didn't rely on a D3DERR_DEVICELOST being returned from TestCooperativeLevel prior to the D3DERR_DEVICENOTRESET return value. The following code seems to have fixed the problem:

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

    }
}

This code does have the side effect of resetting multiple times if the monitor is unplugged (or KVM switched) for an extended period of time.

这篇关于在Windows XP中拔下监视器后,为什么Direct3D无法恢复?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆