マルチスレッド処理の問題 (Direct3D 9)
フルスクリーンの Direct3D アプリケーションは、Direct3D ランタイムにウィンドウ ハンドルを提供します。このウィンドウはランタイムによってフックされます。これは、アプリケーションのウィンドウ メッセージ プロシージャに渡されたすべてのメッセージが、まず、Direct3D ランタイム独自のメッセージ処理プロシージャによって調べられることを意味します。
ディスプレイ モードの変更は、下位のオペレーティング システムに組み込まれたサポート ルーチンによって影響を受けます。モードが変更されると、システムは複数のメッセージをすべてのアプリケーションに送信します。Direct3D アプリケーションでは、メッセージはウィンドウ プロシージャ スレッドで受信します。このスレッドは、IDirect3DDevice9::Reset または IDirect3D9::CreateDevice (またはディスプレイ モードを変更する場合がある IDirect3DDevice9 の最後の Release) を呼び出したスレッドと必ずしも同じではありません。Direct3D ランタイムは、複数のクリティカル セクションを内部で保持します。少なくとも 1 つのクリティカル セクションが、IDirect3DDevice9::Reset または IDirect3D9::CreateDevice によるモード切り替えの後も保持されるので、これらのクリティカル セクションは、アプリケーションがモード変更に関連するウィンドウ メッセージを受信した後も保持されます。
この設計は、暗にマルチスレッド アプリケーションを意図しています。特に、アプリケーションはウィンドウ メッセージ処理スレッドを Direct3D スレッドから完全に分離しなければなりません。1 つのスレッドでモード変更を行いながら、別のスレッドで Direct3D の呼び出しを行うアプリケーションは、デッドロックの危険性があります。
このような理由から、Direct3D では、IDirect3DDevice9::Reset、IDirect3D9::CreateDevice、IDirect3DDevice9::TestCooperativeLevel、または IDirect3DDevice9 の最後の Release の各メソッドは、ウィンドウ メッセージを処理するスレッドと同じスレッドからのみ呼び出すことができるように設計されています。