ページ 1 / 1
デバイスロストを故意に起こす方法
Posted: 2016年2月15日(月) 17:34
by cattail
こんにちわ。cattailです。
また教えて頂きたいことがあるのです。
デバイスロストからの復帰プログラムを作っています。
Microsoft Visual C++ 2008
DirectX9
Windowモード専用
です。
コード:
if(pDevice->Present( NULL, NULL, NULL, NULL )==D3DERR_DEVICELOST)
{
//ここにReleaseとRecoverを書いています。
}
なかなかデバイスロストが起こらずトライアンドエラーが効率よくできません。
他のアプリを起動したり、IEを起動したり、ウィルスチェッカーを起動したりしますがデバイスロストは起こりません。
でも、放っておくと30分くらいで発生するときもあれば、4時間掛かるときもあって時間がもったいないのです。
何かが裏で動いたときに起こるのだと思いますが何かわかりません。
上記プログラムに入ってくるのでデバイスロストが起こっているのだと思います。
どうしたら、故意にデバイスロストを起こすことができるのでしょうか?
教えて頂けたらうれしいです。
よろしくお願いします。
Re: デバイスロストを故意に起こす方法
Posted: 2016年2月15日(月) 20:12
by cattail
また3時間ぶりにデバイスロスト発生しました!
でも、リリースまでいくのですがその後が行きません。
色々考えてる案はあるのですが、なかなか試せなくて進まないのです!
全画面切り替えやったら必ず起こるのでしょうか?
やってみるしかないかな?
Re: デバイスロストを故意に起こす方法
Posted: 2016年2月16日(火) 20:57
by cattail
すみません。
あれから色々やってまして、
デバイスロストを起こす方法ではなくて、
デバイスロストの処理についてお聞きしたいことが出てきまして、
教えて頂けたらと思います。
デバイスロストが発生して、
リストアが可能な状態を確認して、
Resetするのですが、ResetからD3D_OKが返らず、
そのまま、色々なデータを再読み込みしましたが、そのまま復帰して正常に動作しています。
Resetって何をしているのでしょうか?
d3dppをリセットしないと何か問題ありますでしょうか?
コード:
//デバイスは消失しているがリストア可能状態
if(pDevice->TestCooperativeLevel() == D3DERR_DEVICENOTRESET){
//デバイスがリセットされたので再構築する/////////////////////
HRESULT hr = pDevice->Reset( &d3dpp );
//if( hr != D3D_OK ){PostQuitMessage(0);}//ここをコメントして外すだけで問題なくゲームに戻れます。
という感じです。
どうでしょうか?
Re: デバイスロストを故意に起こす方法
Posted: 2016年2月17日(水) 04:09
by yuni
こんばんわ。
まず、すぐに危険と言うことはないでしょうが、危険なコードです。
D3D9のReset関数はそれまでに生成した
レンダーターゲット等のバッファのうち、
D3DPOOL_DEFAULT で作成したすべてのバッファを解放しない限り、かならず失敗します。
ソースがわからないので想像になってしまいますが、
ResetからD3D_OKが返らないのはこのためでしょう。
if文をコメントアウトしても動く、とありますが、
それはd3d9の安全装置のおかげと思われます。
その場合には本来ビデオメモリからとるべきバッファ等が
システムメモリから割り当てられたメモリをビデオメモリとして扱うことで
なんとか動いている状態のはずです。
まずは「IDirect3DDevice9::Reset」で調べてみましょう。
DirectXではMSDN、と書いてあるサイトが公式です。
Reset関数の中には 喪失したデバイス (Direct3D 9) という項目もあります。
そこにはデバイスロストするタイミング、そのとき何が起きているか、
どう対応すべきかが書かれています(書き方が多少小難しいかも知れませんが…)
その中でわからない単語などがあれば
また質問をするというながれで解決につながるかと思います。
Re: デバイスロストを故意に起こす方法
Posted: 2016年2月17日(水) 08:08
by cattail
yuniさん、ご返事ありがとうございます。
コードの説明不足でしたのでもう一度コードを載せました。
>D3DPOOL_DEFAULT で作成したすべてのバッファを解放しない限り、かならず失敗します。
ということですので、作成した全てを開放していないということになるのでしょうか?
やっているとは思いますが、もしかすると見落としがあるかもしれません。
見直してみたいと思います。
コード:
//レンダリング終了 及び デバイス消失への対応
if(pDevice->Present( NULL, NULL, NULL, NULL )==D3DERR_DEVICELOST)
{
//ここにスプライト、xfileなどのオブジェクトのリリースコードが呼ばれます。
//続いて下のRecoverDeviceが呼ばれます。
//上記2つはD3DERR_DEVICENOTRESETが返るまで待てるようにWM_APPから呼ばれるようにしてあります。
}
void RecoverDevice(){
//デバイスは消失しているがリストア可能状態
if(pDevice->TestCooperativeLevel() == D3DERR_DEVICENOTRESET){
//デバイスがリセットされたので再構築する/////////////////////
HRESULT hr = pDevice->Reset( &d3dpp );
//if( hr != D3D_OK ){PostQuitMessage(0);}//ここをコメントして外すだけで問題なくゲームに戻れます。
//ここからオブジェクトの再読み込みなどをしています。
}else{
PostMessage(hWnd,WM_APP,NULL,NULL);//WM_APPを呼び、そこで再度RecoverDeviceを呼ぶ
//(次々にポストされて呼ばれないように工夫しています)
}
}
Re: デバイスロストを故意に起こす方法
Posted: 2016年2月17日(水) 18:26
by ISLe
MSDNのIDirect3DDevice9::TestCooperativeLevelのページには
IDirect3DDevice9::TestCooperativeLevelがD3DERR_DEVICELOSTを返したらIDirect3DDevice9::Resetを試行できる
IDirect3DDevice9::Resetが成功したら必要なリソースを復元して通常の処理を再開できる
と書いてあります。
IDirect3DDevice9::Resetに一度失敗すると、成功するまで
IDirect3DDevice9::TestCooperativeLevelはD3DERR_DEVICENOTRESETを返すようになります。
IDirect3DDevice9::Resetが直ちに成功するとは限らないし
解放処理に問題があればIDirect3DDevice9::Resetは成功しないので
IDirect3DDevice9::Resetを何回か試行して成功するなら、問題はないはず。
Re: デバイスロストを故意に起こす方法
Posted: 2016年2月17日(水) 20:01
by cattail
ISLeさん、お久しぶりです!
お返事頂きありがとうございます。
実のところMSのHPを読んでもなかなか理解できなくて困っていたのです。
それは前の件でも一緒なので分かって頂けるとは思います…。
噛み砕いて説明して頂きありがたいです。
>IDirect3DDevice9::Resetが直ちに成功するとは限らないし
>解放処理に問題があればIDirect3DDevice9::Resetは成功しないので
>IDirect3DDevice9::Resetを何回か試行して成功するなら、問題はないはず。
わかりました。
開放処理を見直して、
再試行できるようにプログラムを変えて再挑戦してみます。
Re: デバイスロストを故意に起こす方法
Posted: 2016年2月18日(木) 07:59
by cattail
なかなかデバイスロストが起こらないので四苦八苦しています。
やっと、エラー戻り値を確認できました。(深夜に起きた模様)
D3DERR_INVALIDCALL
です。
どういうことでしょうか? わからないです。
Re: デバイスロストを故意に起こす方法
Posted: 2016年2月18日(木) 17:10
by ISLe
cattail さんが書きました:なかなかデバイスロストが起こらないので四苦八苦しています。
デバイスロストは他のプログラムがデスクトップを排他的に使用することで発生すると思います。
フルスクリーンで動作するゲームソフトとか。
Direct3Dのサンプルプログラムでも代用できるかと。
デバイスロストというのはデスクトップ画面の取り合いで発生します。
スワップチェーンとかのビデオメモリ内の見えない部分も含みますが。
Direct3D10からはデバイスロストがほとんど発生しない仕組みになったので、
その影響でDirect3D9でも発生しにくくなっているかもしれません。
cattail さんが書きました:やっと、エラー戻り値を確認できました。(深夜に起きた模様)
D3DERR_INVALIDCALL
です。
どういうことでしょうか? わからないです。
何の戻り値ですか?
Re: デバイスロストを故意に起こす方法
Posted: 2016年2月18日(木) 17:33
by cattail
ISLeさん、ご返事ありがとうございます。
D3DERR_INVALIDCALLは、
コード:
HRESULT hr = pDevice->Reset( &d3dpp );
で、hrに入ってきました。
フルスクリーン切り替えを自分でやってみたのですが、
うまくいかなかったもので、Direct3Dのサンプルプログラムを探してみようと思います。
あと、yuniさんがおっしゃっていた、
D3DPOOL_DEFAULTで作成した全てのバッファですが、
スプライト作成時に20枚分で使用したのみで他は使っていないのでそこではないような気がします。
それで、ネットを見ていましたらフォントの開放をしていないと、
ResetでD3DERR_INVALIDCALLが返るという情報がありましたので、
自分のソースを見ましたら全く開放せずに、フォントの大きさを変える度に初期化していました!
もちろん、デバイスロスト時にも開放していませんでした!
まだ、わかりませんが只今絶賛テスト中です!
Re: デバイスロストを故意に起こす方法
Posted: 2016年2月18日(木) 19:43
by cattail
やったやったーーー!キター!
yuni さん!
ISLeさん!
ありがとう!
やった!よかった!
フォントの開放でした。
めちゃめちゃ、ずーっと時間が掛かっていたので自分にはできないと思っていました。
でも、お二方と皆様のおかげで直せました。
あのブログの方もありがとうございます!
飛び上がって喜んでいます!
ほんとにありがとうございました!
でもまた教えて頂く時があると思います。
その時はよろしくおねがいします!