月別アーカイブ: 2007年7月

Direct3D 10.1 での共存とSDKバージョン

WindowsVista SP1 で対応するらしい Direct3D 10.1 ですが、
今の 10.0 対応ビデオカードでそのまま 10.1 の新機能が
使えるとは限りません。(たぶん使えなさそう)
といっても 10.0 ハードに対応しないわけにもいかないでしょう。

D3D10CreateDevice1() で Device のインターフェースを作成するときに、
・D3D10_FEATURE_LEVEL_10_1
・D3D10_FEATURE_LEVEL_10_0
と2種類のパラメータ指定ができるようです。

ということは、10.1 がリリースされた場合は今後 SDK 上は 10.1 を
使っておき、初期化で 10.0 or 10.1 を切り替えることになるのでしょうか。

ShaderModel4.1 についてはまだ何もわかりません。
実行環境が無いとコンパイルもできないので、調べようにも手が出せない
状態です。

ちなみに DirectX SDK August2007 のバージョンは 9.20 1057 でした。

久しぶりに、以前調べた SDK 一覧に追加してみると
DirectX SDK April2007 とバージョン番号

9.19 / 1005.0000 Jun2007
9.19 / 1007.0000 Jun2007 07/10版
9.20 / 1057.0000 Aug2007 (10.1 TechPreview)

こうなります。Jun2007 も 2種類あって、今ダウンロードできるものは
7月版に入れ替わっています。

Direct3D10 StreamOutput

D3D10 で StreamOutput を使う場合、ID3D10GeometryShader の作成に
ID3D10Device::CreateGeometryShader() ではなく
ID3D10Device::CreateGeometryShaderWithStreamOutput() を使います。

Effect(fx) を使用している場合も、Effect(fx) ファイルの中で
 CompileShader() → ConstructGSWithSO()
の流れで、StreamOutput 対応 GeometryShader を作成します。
この辺はほとんどサンプルの記述どおりです。

出力フォーマットの記述など、扱いは Effect ファイルの方が楽なので、

・Effect(fx) ファイルに ConstructGSWithSO() で記述
・ID3D10Effect 作成
・GeometryShader のインターフェース取り出し

の手順で、WithStreamOutput の GeometryShader を簡単に取り出す
ことができます。

普段 GeometryShader を使わない場合は NULL 省略できますが、
StreamOutput では上記方法で GeometryShader を作らなければなりません。

少々不思議なのは D3D10 のサンプルでは、GeometryShader が不要な場合に
ConstructGSWithSO() にコンパイルした VertexShader を渡していること。

例えばこんな感じで使われており、実際にコンパイルしてみても
GeometryShader に VertexShader が入っていました。

VertexShader vs_transform= CompileShader( vs_4_0, VS_Transform() );
GeometryShader gs_transform= ConstructGSWithSO( vs_transform,
  ”POSITION.xyzw;NORMAL.xyz;TEXCOORD.xy” );

StreamOutput 先のバッファを指定するには ID3D10Device::SOSetTargets()
を使います。また同時に現在 SO Stage が有効かどうかの切り替えもこの
SOSetTargets() で行われています。

D3D10_BIND_STREAM_OUTPUT で作った ID3D10Buffer を渡すか NULL を渡すか、
これだけです。

StreamOutput を使う場合は PixelShader を通らないので、PixelShader には
NULL を設定しなければなりません。
さらに Depth/Stencil Buffer が有効になっていると、Pixel Pipeline が
有効とみなされるようです。

StreamOutput 時は Depth/Stencil test を Disable しなければなりません。
この切り替えはもちろん ID3D10DepthStencilState です。

・Shaderやバッファ作成
 CreateGeometryShaderWithStreamOutput()
 CreateDepthStencilState()
 CreateBuffer( D3D10_BIND_STREAM_OUTPUT )

・描画時
 OMSetDepthStencilState( ZENABLE= D3DZB_FALSE , ZWRITEENABLE= FALSE )
 PSSetShader( NULL )
 SOSetTargets( iBuffer )
 Draw( … )
 SOSetTargets( NULL )

バッファ内の StreamOutput 位置は SOSetTargets() の Offset で
指定することができます。

位置が重ならないようにリソースを作ったり Stream に入れたりしても
やはり入出力に同じ Buffer を与えることはできませんでした。

ちなみに GeometryShader で複数頂点を入力して Triangle 出力すると
Index が展開されるので、DrawIndexed() 用の mesh データでも
Draw() での描画になります。
Triangle の増減も可能なのだから仕方ないですが、頂点 Cache の効率を
考えると少々もったいないですね。

GeometryShader が不要で頂点単位の事前変換だけ行う場合は、
StreamOutput 時に POINTLIST を使います。
この場合 Triangle の増減はできないものの、出力頂点数は変化ないので
事前変換しつつ DrawIndexed() を使うことができます。

Direct3D 10.1 Tech Preview

DirectX SDK August 2007 がもう公開されているとのことです。早い!
新 masafumi’s Diary, 8月号
しかも Direct3D 10.1 Tech Preview が入ってるとのこと。
ざっと見てみました。

変更点など詳細はこちら
DirectX Software Development Kit

ShaderModel 4.1 の追加と、レンダリング関連の強化が行われるようです。
まだ詳細も不明で、使えるようになるのもまだまだ先でしょうが
これは楽しみです。以下ドキュメントに書いてなさそうな点です。

追加されたインターフェース名は最後に”1″がついています。

ID3D10BlendState1
ID3D10ShaderResourceView1
ID3D10Device1

10.1 のシンボル定数は D3D10_1_~ といった感じ。

作成は D3D10CreateDevice1() / D3D10CreateDeviceAndSwapChain1()

●BlendState1

10.0 では最大8枚の出力先に対して、
・BlendEnable
・RenderTargetWriteMask
を個別に指定することができました。Blend を使うかどうか、
書き込むチャンネルのみ独立して指定でき、合成方法は全プレーン共通です。

どうやら 10.1 では、Src/Desc 等のブレンドモードも RenderTarget
毎に別パラメータを設定できるようになりそうです。

●ShaderResourceView1

ShaderResourceView1 ではドキュメントにも書かれているように
TextureCubeArray が追加されています。
10.0 では Texture1D/2D/2DMS だけが Array 対象でした。
Cube の Array というと ShadowMap などに便利かもしれません。
Texture の Load コマンドのアドレッシングが 5次元になってしまうので
引数が追加されるのでしょうか。

インターフェースを ~1 に、
やヘッダ d3d10.h → d3d10_1.h の置き換え、
D3D10CreateDeviceAndSwapChain1() で D3D10_FEATURE_LEVEL_10_1 指定、
ライブラリ d3d10_1d.lib 追加等で一応 10.1 の Build はできます。
が、d3d10_1core.dll が無いので起動できませんでした。

Direct3D 10 Streamと同時Resource

Vertex として Stream で読み込んでいる Buffer を、
ShaderResourceView で同時にランダムアクセスすることができました。
これはいいね、使えそう。

可能
・Stream + ShaderResourceView

不可能
・StreamOutput + ShaderResourceView
・StreamOutput + StreamInput

これらのパラメータ組み合わせは D3D10_CREATE_DEVICE_DEBUG 時は
かなり細かくチェックしてくれて詳細な説明とともにエラーが出ます。

若干気をつけないといけないのはパラメータ設定の順番です。

IASetVertex BufA
SOSetTarget BufB
Draw

IASetVertex BufB
SOSetTarget BufC
Draw

SOSetTarget NULL

一見問題ないように見えますが、2つ目の IASetVertex BufB では、
BufB がまだ StreamOutput 対象だからだめだと怒られます。

先に SOSetTarget BufC を設定しなおして BufB を切り離すか、
間に SOSetTarget NULL が必要となります。

IASetVertex BufA
SOSetTarget BufB
Draw

SOSetTarget BufC
IASetVertex BufB
Draw

SOSetTarget NULL

同様のことは ShaderResource や StreamInput 側にも言えます。
特に Stream の 2~3 番目に設定された Buffer は NULL による解放を
を忘れがちなので、あとから StreamOutput の Target にしようとすると
エラーです。

ミスを無くすためには Set 系には毎回こまめに NULL を入れた方が
いいようです。

それにしても Direct3D10 + ShaderModel4.0 は、
こうしなければいけないっていう変な制限が少なく、
Buffer やら InstanceID とか組み合わせたり、
結構自由に考えたとおりに動いてくれるのが気持ちいいですね。
(速度や効率はおいといて)

Direct3D 10 8bit IndexBuffer

d3d10.h (June2007) を見ると、
D3D10_16BIT_INDEX_STRIP_CUT_VALUE や
D3D10_32BIT_INDEX_STRIP_CUT_VALUE と一緒に、
D3D10_8BIT_INDEX_STRIP_CUT_VALUE なるシンボルが定義してあります。
これだけみるとなんだか 8bit IndexBuffer が使えそうです。

ID3D10Device::IASetIndexBuffer
マニュアルにはだめ (16bit or 32bit) と明記されてますが、さすが
Unified Shader だなと思って R8_UINT を試してみました。

結果はだめでディスプレイドライバがハングアップし、ドライバリセットが
かかります。
画面にプリミティブ形状は出るので、一応中で変換するのか
またはハード上バッファは読めるが API で禁止しているのかわかりません。
追求はしておりません。

Shader が自分で Buffer を読み進めれば似たようなことはできるのですが。

STRIP_CUT_VALUE は Strip 中にプリミティブの区切りを指定する特殊な
Index 値です。D3D9 までは頂点を同じ座標に何度も重ね書きすることで
Jump してましたが D3D10 では扱いが簡単になりました。