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

Direct3D デバイスは、稼働状態または喪失状態に設定できます。 稼働状態は、デバイスが実行され、期待どおりにすべてのレンダリングが表示される、デバイスの通常の状態です。 全画面表示のアプリケーションでキーボード フォーカスが失われるなどのイベントによって、レンダリングが不可能になると、デバイスは喪失状態に移行します。 喪失状態には、すべてのレンダリング操作のサイレント エラーという特徴があります。つまり、レンダリング操作に失敗しても、レンダリング メソッドが成功コードを返すことがあります。 このような場合、エラー コード D3DERR_DEVICELOSTは IDirect3DDevice9::P resent によって返されます。

仕様上、デバイスが喪失になる可能性があるあらゆるシナリオ セットが定められているわけではありません。 一般的な例には、ユーザーが Alt + Tab を押した場合やシステム ダイアログが初期化された場合など、フォーカスの喪失が含まれます。 電源管理インベントや、別のアプリケーションが全画面操作を引き受けた場合などのためにデバイスが喪失することもあります。 さらに、 IDirect3DDevice9::Reset のエラーが発生すると、デバイスは失われた状態になります。

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

  • D3DERR_DEVICELOSTで失敗する - これは、アプリケーションがデバイスが失われたことを認識して、アプリケーションが何かが予期したとおりに発生していないことを識別する必要があることを意味します。
  • サイレント エラー、S_OKまたはその他のリターン コードを返す - 関数がサイレント で失敗した場合、アプリケーションでは通常、"成功" と "サイレント エラー" の結果を区別できません。
  • この関数は戻りコードを返します。
Direct3D 9 と Direct3D 9Ex の違い:
Direct3D 9 デバイスは、D3DERR_DEVICELOSTを返します。 IDirect3DDevice9::P resent から返されると、エミュレーション動作は動作しなくなり、デバイスが正常にリセットされるまで、今後のすべての呼び出しは失敗します。
Direct3D 9Ex デバイスはD3DERR_DEVICELOSTを返しませんが、新しいステータス メッセージを返すことができます ( デバイスの動作の変更を参照)。

 

喪失デバイスへの対応

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

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

ほとんどの場合、Direct3D を高頻度で呼び出すと、デバイスが喪失したかどうかに関する情報が返されません。 アプリケーションは、紛失したデバイスの通知を受け取ることなく、 IDirect3DDevice9::D rawPrimitive などのレンダリング メソッドを引き続き呼び出すことができます。 内部では、デバイスが動作状態にリセットされるまでこれらの操作は破棄されます。

アプリケーションは、 IDirect3DDevice9::TestCooperativeLevel メソッドの戻り値に対してクエリを実行することで、デバイスが失われた場合の処理を決定できます。

ロック操作

内部では、デバイスが喪失した後にロック操作を成功させるための処理を Direct3D は十分に行いません。 ただし、ロック操作中にビデオ メモリ リソースのデータが正確であることは保証されません。 エラー コードが返されないことは保証されます。 このため、ロック操作中にデバイスが喪失することを気にせずにアプリケーションを記述できます。

リソース

リソースは、ビデオ メモリを消費する可能性があります。 喪失デバイスはアダプターが所有するビデオ メモリから切断されるため、デバイス喪失したときにビデオ メモリの割り当てを保証することはできません。 その結果、すべてのリソース作成メソッドは、D3D_OKを返すことで成功するように実装されますが、実際にはダミー システム メモリのみを割り当てます。 デバイスをサイズ変更する前にビデオ メモリ リソースを破棄する必要があるため、ビデオ メモリの過剰割り当ての問題は発生しません。 これらのダミー サーフェスを使用すると、アプリケーションが IDirect3DDevice9::P resent を呼び出してデバイスが失われたことが検出されるまで、ロック操作とコピー操作が正常に機能するように見えます。

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

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

取得されたデータ

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

さらに、Direct3D を使うと、アプリケーションは生成されたイメージや以前に書き込まれたイメージをビデオ メモリ リソースから不揮発性システム メモリ リソースにコピーできます。 そのような転送のソース イメージはいつでも失われる可能性があるため、Direct3D ではデバイスが喪失するとそのコピー操作を失敗させることができます。

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

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

プログラミング可能なシェーダー

Direct3D 9 では、頂点シェーダーとピクセル シェーダーをリセット後に再作成する必要はありません。 これらは記憶されます。 以前のバージョンの DirectX では、デバイスが失われた場合、シェーダーを再作成する必要があります。

Direct3D デバイス