日別アーカイブ: 2008年11月7日

Direct3D11 の遅延描画、スレッド対応機能、シェーダー命令

Direct3D11 (DirectX11) はマルチスレッドを意識した設計が行われています。
この場合のスレッドとは CPU 側の話で、複数 core CPU が効率よく D3D API を
使用できるようになっています。

D3D10 以前のスレッド対応機能は、複数のスレッドから呼び出してもとりあえず
問題が起こらない、というレベルのものでした。
ハードウエアスレッドでの速度効率はあまり考えられていなかったといえます。

D3D11 では次の点が改良されています。

・描画やステート変更などの命令発行を複数持てる。CommandList と呼ばれる。
 Push バッファをコンテキスト毎に複数持てる。(deferred context)

・描画スレッド以外でも GPU リソースを作成できる。

従来は単一のコマンドバッファに API 単位で同期しつつアクセスが行われていた
ためスレッド間でブロックします。D3D11 はバッファリングで不要なブロッキングと
コンテキストの矛盾を回避します。

個別の CommandList (Display List) の実行には新しい GPU やドライバの機能を
必要としますが、命令の記録を API でエミュレートできるため、低い FeatureLevel
でも動作するようです。エミュレートは実行時にメモリコピーが発生する可能性が
あるため、single core CPU の場合はおそらくあまりメリットがないと思われます。
実際 D3D11_CREATE_DEVICE_SINGLETHREADED を指定すると
CreateDeferredContext() は失敗するようです。

これらの機能に対応するため D3D の Device Interface は Context が分離されました。

(1) ID3D11Device
(2) ID3D11DeviceContext

(1) の ID3D11Device 自体は Create 命令だらけになっています。
描画やステート変更は (2) の ID3D11DeviceContext に移動しました。

言ってしまえば、スレッドセーフでシェア可能な API とスレッドローカルな API に
分かれたわけです。
ID3D11Device を使ったリソースの作成はスレッドセーフであり特別な管理は不要です。
ID3D11DeviceContext は API 呼び出しを行うスレッド毎に所有する必要があります。

ID3D11DeviceContext の生成には次の命令を使います。

ID3D11Device::GetImmediateContext()
ID3D11Device::CreateDeferredContext()

ImmediateContext は従来の API 呼び出しと同等で、プッシュバッファに記録された
命令は必要に応じて kick されます。
DeferredContext の呼び出しは CommandList (ID3D11CommandList) に記録され、
ExecuteCommandList() を実行するまで保留します。
ExecuteCommandList() の呼び出しは、ImmediateContext() が行います。

●描画メインスレッド
 1. GetImmediateContext() で作成した ID3D11DeviceContext を使う。
 2. 他のスレッドが作成した CommandList を ExecuteCommandList() する。

●サブスレッド
 1. CreateDeferredContext() で作成した ID3D11DeviceContext を使用する。
 2. FinishCommandList() で ID3D11CommandList を受け取る。

シェーダーの種類も増えたので、ID3D11DeviceContext の命令も増えています。

CS~ CoputeShader
DS~ DomainShader
GS~ GeometryShader
HS~ HullShader
IA~ InputAssembler
OM~ OutputManager
PS~ PixelShader
RS~ Rasterizer
VS~ VertexShader
SO~ StreamOutput
OM~ OutputManager

HS DS GS VS PS の 6種類のシェーダーそれぞれに次の 8命令が用意されています。

~GetConstantBuffers()
~SetConstantBuffers()
~GetSamplers()
~SetSamplers()
~GetShader()
~SetShader()
~GetShaderResource()
~SetShaderResource()

CS のみ CSGetUnorderdAccessViews()/CSSetUnorderdAccessViews() の特殊な
2命令があります。
これだけで 6 x 8 + 2 = 50命令

関連エントリ
Direct3D11 Technical Preview D3D11の互換性、WARP Driver