ここらでちょっと真面目な話をします。Direct3Dを利用するときにはデバイスを使いますよね?(「Device」のことですよ)これについてのお話です。
デバイスの消失とはデバイスが利用できなくなる状態の事をさします。どういったときに起こるかというと、
おおざっぱにあげるとこういう感じですが、これ以外の場合でもデバイスは消失する可能性があります。つまりデバイスの消失は常に起こる可能性があるという事です。
まず、特定のメソッドを呼び出すと、例外が起きます。今まで使ったメソッドの中では「Present」がデバイス消失時に、例外を出します。
さらに、一時的にビデオメモリへの接続がたたれるため、管理されていないリソースを作り直す必要があります。
リソースを作るときにはよく「Pool」という列挙型を使います。その中に「Pool.Default」という定数があります。このPoolというのはデータをどのメモリに置くのかを示しています。そして、Defaultというのはデータを最適な位置(つまり、もっとも高速にアクセスできる位置…大抵はビデオメモリ)に配置します。よって、ビデオメモリとの接続が切れたときどうなるか分からないデータと言う事で「管理されていないリソース」という事になるのです。
リセットします。Deviceには「Reset」というメソッドがあります。デバイスが消失したときはこれを呼び出します。
しかし、これを呼び出すためにはデバイスがリセット可能な状態になっている必要があるのです。
とりあえず、一回ソースコードをみてください。
try { //更新 device_.Present(); } catch(DeviceLostException ex) { int result; if(!device_.CheckCooperativeLevel(out result)) { if(result ==(int)ResultCode.DeviceLost) { //まだリセットできないので //ちょっと待つ System.Threading.Thread.Sleep(10); } else if(result ==(int)ResultCode.DeviceNotReset) { //管理されていないリソースを解放する //code device_.Reset(presentParam_); //管理されていないリソースを再構築する //code } } }
始まりは、リソースが消失するところからです。
リソースが消失すると、Presentメソッドが失敗。「DeviceLostException」例外を出します。
プログラムはリセットできるかどうかを知るために「CheckCooperativeLevel」を呼び出します。このメソッド珍しい事に「out」を使っています。
public bool CheckCooperativeLevel( out int result );
返り値はデバイスが消失しているときは「false」になります。そういうわけで一応ifで判定を入れています。
重要なのはもう一つの情報「result」です。この値が列挙型「ResultCode」のどの状態に一致するかでこれからの動作が決まります。と言ってもここで重要なのは次の二つです。
もし「DeviceLost」の場合はSleepします。このようにしないとループがすごい勢いで回り出します。
もう一方の「DeviceNotReset」の時はリセットできます。しかし、まだ条件があって特定のリソースについては、解放を行わなければいけません。とりあえず今はまだ解放すべきリソースがないので行いません。リセットを行うだけです。
駆け足になりましたが、エラーに対応する事は重要です。趣味なら良いですが、人に渡すときによく落ちるプログラムなんてあげられませんからね。
デバイスの消失については、MSDNにも載っているので、しっかり読む方が良いです。でも、結構わかりにくいです。ちなみに私はDirectX9(C++)のコードや情報でここの記事書いています。C++でも内容は特に変化がないので十分勉強できます。