DirectX Direct3D 10 その2

●caps

caps 情報が必要なく、どのビデオカードでも同じように動作するのが 10 の特徴と
されています。ただ全く判断が必要必要ないかといえばそうではなくて、最低限
D3D10 が動くかどうかの判別は要ります。

DX5 あたりの時代のビデオカードだと、同じチップなのにメーカーによって結構
機能が違っていました。この違いはドライバによるもので、有効になっている機能
であっても実際はドライバ側のエミュレーションだったり他の機能の代用で実現
していたのかもしれません。

D3D10 ではどのメーカーのビデオカードでも同じ用に動作することが求められて
いるのですが、カードによって実装方法が異なっていることは考えられます。
機能が有効になっていてもビデオカードによってはエミュレーション実装で実は
重い、なんて状況にもしなるんだったら、事前に caps で判断して苦手な機能を
弾ける方がいいのかもしれません。
この辺はさまざまなビデオカードが出てくるまではまだなんともいえないところです。

●GeometryShader

GS はプリミティブ単位でシェーダーを実行することができますが、さらに隣接する
プリミティブの情報も参照することが可能です。これは ADJ 系の Topology データ
が必要です。隣接するプリミティブの情報を格納した IndexBuffer や頂点情報を
作成しておくわけです。(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ 等)

なのであらかじめ対応するデータ形式への変換が要ります。頂点情報が重複するので、
本当に隣接情報を受け取りたいだけなら基本的に Indexed だけ使うことになるで
しょう。

例えば Triangle なら隣接込みで 6頂点入力になります。この余分な頂点情報にわざと
関係ないデータの頂点を与えることで、プリミティブ単位の追加情報領域として
活用することができそうです。ここに面法線とか面マテリアルとか入れて GS で
合成してあげるなど、かなり使い道がありそうですね。

なお GS で頂点の追加ができますが、試してみたところ一度の出力は最大 1024 要素
(スカラー)までに制限されるようです。例えば頂点形式が

px py pz nx ny nz tu tx

だと8要素なので、1024/8= 128個。つまり 128頂点まで出力することができます。
Triangle List だと 42個分になるでしょうか。

●resource

リソース周りの構造の理解も重要なポイントです。かなりのリソースが相互に流用
可能になっています。大きく分けると Buffer と ShaderResourceView の2種類です。
シェーダー側でも Buffer として読むか ShaderResourceView として読み込むかで
命令が違います。
ShaderResourceView であっても結局 Load() を使えば offset 指定で直接読めるので、
できることは cbuffer とあまり変わりません。VertexShader のみ cbuffer に
使えるリソースが ConstantBuffer だけに制限されています。

なので VertexShader だけは c0~ 系命令のアクセスが最適化されているけれど、
他の Shader では内部で Load() に置き換わっているのだろうか、とかちょっと
思いましたがそんなことは無いよいうです。

サンプルでもこの辺の比較プログラムが存在するので、どれくらいパフォーマンスに
差が出るかは試すことができます。

ShaderResourceView を使うと FORMAT によるさまざまな形式のデータを読み込め
ますがその代わり配列相当なのでフォーマットの異なる構造を作れません。
(tbuffer としてはアクセスできる)

Buffer を使うと構造を定義できますが、int, float, half 等の組み合わせなので
DXGI_FORMAT のような柔軟なデータ形式では直接宣言できなくなるようです。
(R8G8B8A8とか)
ちなみに subresource は ~DX9 でいう Surface のことのようです。