運が悪かった面白いバグが出てきました。ネイティブコードを使用するウィンドウ化された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を使用していますが、現時点では更新できません。誰かが以前にこの問題を見たことがありますか、またはデバイスをリセットできない理由を知っていますか?
更新:私は解決策を見つけたと思いますが、それでも上記の2番目のコードセグメントの失敗に困惑しています。DirectXデバッグランタイムをリモートデバッグで動作させるようにした後、リセット機能が失敗し続ける理由は、解放されていないリソースがあったためであることに気付きました。ただし、回答に示されているように適用すると、まったく同じリリースコードで問題が解決しました。プログラムがrecover関数の呼び出しの間にD3DPOOL_DEFAULTオブジェクトを作成していないことを確認しました。この質問のコードセグメントに示されているように、リセットを実行すると問題を引き起こす可能性のあるDirect3Dの構造に何かがありますか?