Microsoft DirectX 8.0 (C++)

マルチスレッド処理の問題

フルスクリーンの Microsoft® Direct3D® アプリケーションは、Direct3D ランタイムにウィンドウ ハンドルを提供する。このウィンドウはランタイムによってフックされる。これは、アプリケーションのウィンドウ メッセージ プロシージャに渡されたすべてのメッセージが、まず、Direct3D ランタイム独自のメッセージ処理プロシージャによって調べられたことを意味する。

ディスプレイ モードの変更は、下位のオペレーティング システムに組み込まれたサポート ルーチンによってもたらされる。モードが変更されると、システムは複数のメッセージをすべてのアプリケーションにある要素を全要素にコピーする。Direct3D アプリケーションでは、メッセージはウィンドウ プロシージャ スレッドで受信される。このスレッドは、IDirect3DDevice8::Reset または IDirect3D8::CreateDevice (またはディスプレイ モードを変更する場合がある IDirect3DDevice8 の最後の IUnknown::Release) を呼び出したスレッドと必ずしも同じではない。Direct3D ランタイムは、複数のクリティカル セクションを内部で保持する。少なくとも 1 つのクリティカル セクションが、Reset または CreateDevice によるモード切り替えの後も保持されるので、これらのクリティカル セクションは、アプリケーションがモード変更に関連するウィンドウ メッセージを受信した後も保持される。

この設計は、暗にマルチスレッド アプリケーションを意図している。特に、アプリケーションはウィンドウ メッセージ処理スレッドを Direct3D スレッドから完全に分離しなければならない。1 つのスレッドでモード変更を行いながら、別のスレッドで Direct3D の呼び出しを行うアプリケーションは、デッドロックの危険性がある。

このような理由から、Direct3D では、ResetCreateDeviceTestCoorperativeLevel、または IDirect3DDevice8 の最後の Release の各メソッドは、ウィンドウ メッセージを処理するスレッドと同じスレッドからのみ呼び出すことができるように設計されている。