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

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

Direct3D11 Technical Preview D3D11の互換性、WARP Driver

DirectX SDK Novemver 2008 には DirectX11 (D3D11) の beta SDK が含まれています。
Direct3D11 API の機能や詳細が明らかになってきました。

Direct3D10 で大幅に変更された API の路線は継承されていますが
さらに現実的な改良がいくつも施されています。
中でも驚いたのが、D3D10 の時よりも間口を広げたこと。

手持ちの RADEON HD4850 でも D3D11 サンプルが動作しました。
(Windows Vista x64 + HD4850 CATALYST 8.10)
サンプルによっては、Reference でなくアクセラレートが利いているものもあります。
D3D9 GPU では一切動かなかった D3D10 とはえらい違いです。
信じられないくらい。

■D3D9 → D3D10 の場合

・Preview SDK が出ても当時は Vista 発売前だったため Reference Driver ですら
 動かなかった。
・D3D10 専用 GPU (ShaderModel 4.0 以上) が無いと一切ハードウエアアクセラレータ
 が利かなかった。(Reference のみ)

■D3D10 → D3D11 の場合

・Vista 上なら旧ビデオカードでも Reference Device で動く。
・D3D10 GPU でも D3D11 API が使えた。Feature Level が制限されるだけで API
 自体は置き換えられる。未対応の機能さえ使わなければアクセラレートされるらしい。
・さらに WARP Driver (WARP Device) が使える。(詳細は後述)

D3D9 以前は CAPS 情報があったため、旧 GPU でも使えない機能が判別できました。
D3D10 はデバイスの性能を特定する仕組みが無く、D3D10 の全機能が必須となり
 旧 GPU は切り捨てられました。
D3D10.1 では FeatureLevel が導入され、10.0 と同居可能となりました。
D3D11 では同じように FeatureLevel で各 GPU のレベルを判別します。

Feature Level
  11.0 = ShaderModel 5.0
  10.1 = ShaderModel 4.1
  10.0 = ShaderModel 4.0
   9.3 = ShaderModel 3.0
   9.2 = ShaderModel 2.0
   9.1 = ShaderModel 2.0

上記 FeatureLevel の定義を見ると、D3D10 GPU どころか D3D9 世代、
ShaderModel 2.0~3.0 にも対応しているように見えます。
もしこれが本当なら、Direct3D10 よりも Direct3D11 の方が対応 GPU の範囲が広い
ことになります。
Direct3D10 は動かないけど Direct3D11 なら動く可能性があるということ。

Direct3D9 の固定パイプライン(HW T&L) が使えないだけで、従来の D3D9Ex も
D3D11 API に統合可能なのかもしれません。

互換性を保った API の置き換えは D3D9 以前の DirectX では当たり前だったため、
元に戻っただけともいえます。
それでも D3D10 の仕様を考えると非常に大きな路線変更です。

Direct3D10 へ移行するのはものすごい骨が折れるし敷居も高かったので良い傾向です。

FeatureLevel 9.2 と 9.1 の違いは不明です。
ShaderModel は vs3.0/vs2.0 ではなく、vs_4_0_level_9_1 等 4.0 の制限版と
なるようです。

●Device Type (Driver Type)

Device Type が増えました。
目新しいのは Null Reference Device と WARP Device です。

・Hardware Device (HAL)
・Null Reference Device
・Reference Device
・Software Device
・WARP Device

Null Reference Device は Reference Device 同様ソフトウエア動作しますが
レンダリング機能が無いようです。API 呼び出しだけソフトウエアでシミュレート
することで、現実的な速度でデバッグを行うのが目的のようです。

WARP Device (Windows Advanced Rasterizer) は高速なソフトウエアラスタライザ
のようです。Multi Core CPU が当たり前になり GPU との差が埋まりつつあるため、
ソフトウエアラスタライザが復活といったところでしょうか。
WARP Device は D3D11/D3D10.1 の置き換えが出来るそうです。
詳しい説明がないため中身はわかりませんが、RAMP とか MMX RGB Driver が存在
していた D3D5~D3D6 あたりを思い出します。

実際に D3D_DRIVER_TYPE_WARP を使ってみたところ、D3D10WARP_beta.dll が
読み込まれているのを確認しました。
Dual Core CPU で試したためあまり参考にならないかもしれませんが、確かに動作は
REFERENCE Driver より高速でした。
Reference で 0.3fps 程度のサンプルが、数fps 程度には向上しています。
Quad 以上ならもっと効果が顕著だと思われます。

これから CPU の core 数は増加していきます。例えば Core i7 は Quad + HT で
ハードウエア 8 スレッドらしいので、今後はさらに期待できそうです。

DirectX11 に関しては下記関連エントリも参考にしてください。

関連エントリ
Direct3D11 シェーダーの動的リンクやテクスチャ
Direct3D11 マルチスレッドのための機能
Direct3D11 テセレータとシェーダー
Direct3D11 のパイプライン
Direct3D11 Compute Shader など
Gamefest2008 と Direct3D 11

LittleBigPlanet 製品版 機械式ゲームのエミュレータ

βの時にアップロードしたステージデータが残っていました。
同じアカウントならダウンロード(コピー)出来るので再編集も可能です。

ベータとの違いで大きいのが、ジェットパックのはずしかた。
○ボタンだけで簡単に外せるようになってます。
その他気がついたところ

・ジェットパックがボタンだけで簡単に外せる(ベータはコントローラを振る)
・コミュニティのページが増えている(ベータは10ページだった)
・アップロードできるステージ上限が4倍に増えている
・テンプレートはストーリーモードのステージをクリアして手に入れる必要あり

ジェットパックでシェイク不要になったので、センサーが無くても基本操作は
可能となりました。これで純正以外のコントローラも使えるかと思ったけど、
手持ちの PC 向け USB コントローラは XMB では使えるのに LBP では
動きませんでした。

発売直後はサーバーの不調かネットにログインできないことが何度かありました。
それでもストーリーモードとエディットは出来ます。

ストーリーモードのボリュームはかなり増えているし、それぞれ凝っていて
良く作り込まれています。
先にエディットを経験しておけば、ステージの仕掛けがどうやって作られているのか
考えたり、仕組みを再現してみる楽しみ方もあり。

リトルビッグプラネットのエディットは良くできていて強力です。
かえってゲーム経験が豊富な人の方が、「エディット=難しい」と先入観があって、
軽視してしまうかもしれません。だとしたらもったいない。

スクリプトでもなく、状態遷移グラフでもない。
物理法則だけでさまざまな仕掛けを作れてしまう、ゲームの新しいプログラミング
スタイル(?)といえるかもしれません。

言ってしまえばゲーム自体が電子ロジックではなく「機械仕掛け」でできています。
その機械仕掛けをわざわざコンピュータでシミュレートしているわけです。

フラグとか演算とか、そんな概念は何も無し。
スイッチと配線が出来るため、がんばれば論理回路が作れます。
でも物理的なスイッチを動かすモーター(ぶらぶらボルト、ピストン)とマグネット
スイッチを経由するのでリレー式です。

このゲーム(アプリケーション)のジャンルはきっと、機械式ゲームのエミュレータ。