喪失したデバイス (Direct3D 9)

Direct3D デバイスは、使用可能状態か喪失状態のどちらかです。使用可能状態は、デバイスが予想どおりにすべてのレンダリングを実行して表示するという、デバイスの通常の状態です。デバイスは、全画面モードのアプリケーションでキーボード フォーカスを失うなどの、レンダリングが不可能になるイベントが発生したときに、喪失状態へ移行します。喪失状態には、すべてのレンダリング操作が警告なしで失敗するという特徴があります。この状況では、エラー コード D3DERR_DEVICELOST が IDirect3DDevice9::Present によって返されます。

デバイスが失われる原因となるシナリオは、意図的に、すべては特定されていません。一般的な例では、ユーザーが Alt + Tab キーを押したときやシステム ダイアログが初期化されたときに、フォーカスを失うことなどがあります。デバイスは、電源管理イベントによって、または別のアプリケーションで全画面モードでの操作が前提となっている場合にも失われる可能性があります。IDirect3DDevice9::Reset からエラーが発生した場合にも、デバイスは喪失状態になります。

IUnknown から派生するすべてのメソッドは、デバイスが失われた後も機能することが保証されています。デバイスが失われた後の各関数には、一般的に、次の 3 つのオプションがあります。

  • D3DERR_DEVICELOST に失敗する : つまり、何かが予想どおりに起こっていないことをアプリケーションが確認できるように、アプリケーションで、デバイスが失われたことを認識しなければなりません。
  • 警告なく失敗し、S_OK かその他の任意のリターン コードが返される : 関数が警告なしで失敗した場合、アプリケーションは通常は "成功" と "警告なしで失敗" の結果を区別できません。
  • 関数によってリターン コードが返される

Direct3D 9 と Direct3D 9Ex の違い

Direct3D 9 デバイスでは、D3DERR_DEVICELOST が返されます。これが IDirect3DDevice9::Present から返されると、エミュレーション動作はもう行われなくなり、それ以降のすべての呼び出しは、デバイスが正しくリセットされるまで失敗することになります。

Direct3D 9Ex デバイスによって D3DERR_DEVICELOST が返されることはありませんが、新しいステータス メッセージが返される場合があります (「デバイスの動作の変更」を参照してください)。

喪失したデバイスへの対応

喪失したデバイスでは、リセット後にリソース (ビデオ メモリー リソースを含む) を再作成する必要があります。デバイスが失われた場合は、そのデバイスを使用可能状態に復元できるかどうかを確認するために、アプリケーションからそのデバイスにクエリします。復元できない場合、アプリケーションはそのデバイスを復元できるまで待機します。

デバイスを復元できる場合、アプリケーションでは、すべてのビデオ メモリー リソースと任意のスワップ チェーンを破棄することによって、そのデバイスを準備します。次に、アプリケーションによって IDirect3DDevice9::Reset メソッドが呼び出されます。Reset は、デバイスが失われた場合に効果のある唯一のメソッドであり、アプリケーションでデバイスを喪失状態から使用可能状態へ変更できる唯一のメソッドとなります。IDirect3DDevice9::CreateRenderTarget メソッドと IDirect3DDevice9::CreateDepthStencilSurface メソッドで作成されたものを含めて、D3DPOOL_DEFAULT に割り当てられたすべてのリソースがアプリケーションで解放されない限り、リセットは失敗します。

通常、高い頻度で発生する Direct3D の呼び出しでは、デバイスが失われたかどうかに関する情報は返されません。喪失したデバイスの通知を受信しなくても、引き続きアプリケーションで IDirect3DDevice9::DrawPrimitive などのレンダリング メソッドの呼び出しを行うことができます。これらの処理は、内部的に、デバイスがリセットされて使用可能状態になるまで破棄されます。

アプリケーションで IDirect3DDevice9::TestCooperativeLevel メソッドの戻り値をクエリすることによって、喪失したデバイスに直面したときの動作を決定できます。

操作のロック

Direct3D は、デバイスが失われた後も、ロック操作が成功するよう、内部的に十分に機能します。ただし、ロック操作中のビデオ メモリー リソースのデータが正しいかどうかは保証されません。エラー コードが返されないことは保証されます。これにより、アプリケーションで、ロック操作中にデバイスの喪失を意識せずに書き込むことができます。

リソース

リソースは、ビデオ メモリーを消費できます。喪失したデバイスは、アダプターによって所有されるビデオ メモリーから切断されるため、デバイスが失われた場合は、ビデオ メモリーの割り当てを保証できなくなります。その結果、すべてのリソース作成メソッドは、D3D_OK を返すことによって正しく実装されますが、実際には、ダミーのシステム メモリーしか割り当てられません。ビデオ メモリー リソースはデバイスがサイズ変更される前に破棄されなければならないため、ビデオ メモリーの過剰割り当ての心配はありません。これらのダミー サーフェスでは、アプリケーションで IDirect3DDevice9::Present が呼び出されて、デバイスが失われていることが発見されるまで、通常どおり機能しているように見えるよう、ロック操作とコピー操作が許可されます。

すべてのビデオ メモリーは、デバイスを喪失状態から使用可能状態にリセット可能になるまでに解放されなければなりません。つまり、アプリケーションでは、IDirect3DDevice9::CreateAdditionalSwapChain で作成されたスワップ チェーンと、D3DPOOL_DEFAULT メモリー クラスに配置されたリソースを解放する必要があります。アプリケーションで、D3DPOOL_MANAGED メモリー クラスや D3DPOOL_SYSTEMMEM メモリー クラス内のリソースを解放する必要はありません。その他のステート データは、使用可能状態への移行によって自動的に破棄されます。

デバイスの喪失に対応するためには、単一のコード パスを使用してアプリケーションを開発することをお勧めします。このコード パスは、起動時にデバイスの初期化に使用されたコード パスと、同一でない場合でもほぼ同じとなります。

取得データ

Direct3D を使用すると、アプリケーションで、IDirect3DDevice9::ValidateDevice を使用するハードウェアによって、単一パスのレンダリングに対してテクスチャー ステートとレンダリング ステートを検証できるようになります。アプリケーションの初期化中に呼び出されるのが一般的なこのメソッドでは、デバイスが失われている場合に D3DERR_DEVICELOST が返されます。

また、Direct3D によって、生成されたか以前書き込まれたイメージを、ビデオ メモリー リソースから不揮発性のシステム メモリー リソースへコピーできるようになります。このような転送の元のイメージは常に失われる可能性があるため、Direct3D では、デバイスが失われた場合のこのようなコピー操作の失敗は許可されています。

非同期クエリに関しては、FLUSH フラグが指定された場合は、IDirect3DQuery9::GetData で決して S_OK が返されないアプリケーションを示すために、IDirect3DQuery9::GetData で D3DERR_DEVICELOST が返されます。

デバイスが失われた場合、コピー操作 IDirect3DDevice9::GetFrontBufferData では、プライマリ サーフェスがないために D3DERR_DEVICELOST に失敗する可能性があり、IDirect3DDevice9::CreateAdditionalSwapChain では、バック バッファーを作成できないために、D3DERR_DEVICELOST に失敗する可能性があります。これらは、IDirect3DDevice9::Present メソッド、IDirect3DDevice9::TestCooperativeLevel メソッド、および IDirect3DDevice9::Reset メソッドを除く D3DERR_DEVICELOST の唯一の例であることに注意してください。

プログラム可能シェーダー

Direct3D 9 では、リセット後に頂点シェーダーとピクセル シェーダーを再作成する必要はありません。それらは保持されます。以前のバージョンの DirectX では、喪失したデバイスについては、シェーダーを再作成する必要がありました。