Archives

January 2007 の記事

やっと出ました!
ベータでない Vista 用ドライバです。
nVIDIA のサイトから落とせます。
http://www.nvidia.com/content/drivers/drivers.asp

GeForce8800 GTX/GTS が発売されて、
DirectX SDK の D3D10 も RTM して、
Windows Vista も発売されて、
Vista 用ドライバも出て、
ようやく Shader4.0 が普通に使えます。
長かった・・

追記: よく見たらベータでした。
失礼しました。


従来相違があって不思議と互換性が無かった
頂点フォーマットとテクスチャフォーマットが D3D10 で統一されています。
これもシェーダーが統合されたおかげでしょうか。

Direct3D9 では例えば頂点だと

 FLOAT4   float×4
 FLOAT16_4  float(16bit)×4
 SHORT4N   short×4
 UBYTE4   byte×4 (a b g r)
 D3DCOLOR  byte×4 (a r g b)
 DEC3N    (10,10,10)
 
等の専用形式があり、テクスチャにも

 A32B32G32R32F
 A16B16G16R16F
 A16B16G16R16
 A8B8G8R8
 A8R8G8B8
 A2R10G10B10

があります。上にあげたものはほぼ似たようなフォーマットですが、
それ以外のものは互換性が無くアクセスのために専用のコードが必要でした。

Direct3D10 では VertexShader も PixelShader も同じ性能を持っているので、
アクセス可能な Buffer および ShadeResource のフォーマットが同じものになって
いるようです。
(2次元圧縮の BC(DXT) 形式は除く)

その代わり頂点フォーマットでも R G B A 表記になります。
よく見ると D3D9 の A B G R 表記と逆順です。
もちろん x y z w にあわせたためだと思われます。

xyzw と rgba の統合までの道のり

・D3D8 まで ARGB → D3D9 で ABGR 追加 → D3D10 で RGBA に変更


●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 のことのようです。


2007/01/21
DirectX Direct3D10

GeForce8800 のドライバが出た(?)ので早速 D3D10 を試しています。
ずっと DirectX SDK には Direct3D10 の Preview が付属していましたが、
RTM した December でもマニュアルが融合しただけで D3D9 も D3D10 もどっちも
入った状態なのは一緒です。

これまでも、DirectX9 に入ってた DirectInput はずっと DirectInput8 の
ままだったし、DirectSound も DirectSound8 でした。
なので Direct3D も、DirectX 全体のバージョンとは独立したナンバリングが
行われたようです。

といっても、もともと DirectX の初期の頃は各コンポーネントごとにばらばらに
インターフェース番号がついてました。

で、確か DirectX7 のときに SDK 全体の番号と各インターフェースの番号の統合
が行われました。ほぼ全部のインターフェースの番号を SDK の番号にあわせたわけ
です。

だから元に戻ったようなものでしょうか。

D3D10 はインターフェース周りからフォーマット名のシンボルから使い方まで
Direct3D9 と全く違ったものになってます。
結構大変に見えるかもしれませんが、DirectX7 まではだいたい 1年に一回
こんな感じで大幅な刷新があったんですよね。

とりあえず D3D10_DRIVER_TYPE_HARDWARE でちゃんと高速に動作しました。


API セットは Fixedパイプが無くなってかなりすっきりしたはずなのですが、
その代わり汎用性が増して自由度があがったためか、インターフェースの種類も
かなり増えています。おかげで一見しただけだと全体の構造がわからなくなって
しまいました。
例えばテクスチャの読み込み1つ見てもやるべき手順が増えてます。

また従来は目的毎に API があったため何をやるのかは割と明確でした。今では
ライティングもマテリアルもフォグも何から何まで Shader の実装依存になった
ために専用の API や構造体は無く全部汎用です。

逆に Depth, Stencil あたりの判定の流れは変わっていないので、レガシーに
感じてしまいます。

設定やパラメータの渡し方も大幅に変更になっています。効率優先でできる限り
バッファに置く構造となっていて、非常に徹底したものです。
いまのビデオカードは RAM 容量もかなり多いので、これを活用する構造にシフト
したのでしょう。コマンドストリームに乗せるものは最小限です。


・マニュアルのミス?
 December でマニュアルの D3DX10CreateShaderResourceViewFromFile() の引数が
 足りないようです。
 実際の定義では D3DX10_IMAGE_LOAD_INFO と ID3DX10ThreadPump* の2つが追加
 されています。

 チュートリアルやプログラミングガイドでも、たまに関数名が間違ってることが
 あるようです。例えば

 DirectX Graphic
  Direct3D 10
   Programming Guide
    API Features
     Reference Counting
 の最後の pDevice->GetRasterrizerState() 等。

 もしかしたら設計の最後に、全部の API 名が RSGetState() のように RS~、PS~、
 OM~、と整理されたのかもしれません。こういうミスはその名残かも。



・その他気がついたこととか随時

HLSL は technique ではなく、technique10。間違えると signature 取れずにはまる。

D3D10 では Set 系で Reference Count が増えない。

Texture の管理に ResourceView を使った場合、開放の手順が多少複雑。
データの実体は ID3D10Texture2D なので、Resource の開放も必要。


ついに来た!(のかな?)
 Direct3D 10 に必要な Windows Vista が RTM し
 Direct3D 10 対応ハード GeForce8800 が発売され
 Direct3D 10 SDK も RTM したのに、
Vista 用の GeForce8000 のドライバが無くてずっと待たされ続けてました。
D3D10 どころかドライバが無いためで Vista そのものがまともに使えません。
せっかく買ったカードもずっと箱の中でした。
これでやっと D3D10 のプログラムが書けるようになります。

Forceware 100.30 (Beta)

入れてみました。
一応 Vista に install して、DirectX SDK の D3D10 用サンプルが動くことは
確認できました。ドライバが Beta だからと思いますが、D3D10 専用サンプルは
少々予想外に重い印象。まだ動作が不安定なものもありました。

GeForce8800 のデモも Vista 上で動きました。こちらはきちんと動きますね。

・Adrianne
 http://www.nzone.com/object/nzone_adrianne_home.html

・Froggy
 http://www.nzone.com/object/nzone_froggy_home.html

・Box of Smoke
 http://www.nzone.com/object/nzone_boxofsmoke_home.html