日別アーカイブ: 2007年8月1日

Direct3D 10 ConstantBuffer と配列

ConstantBuffer は D3D8~9 同様 32bit×4 が Element の基本サイズに
なります。ただし D3D10 は float, int の混在が可能です。
マニュアルには Packing Rule として、変数がどのように Constant Buffer
へ格納されるか説明が載っています。

配列変数の場合は、インデックス参照を行うとアドレッシングの影響を強く
受けてしまうので大胆なパッキングができません。
例えば次のように宣言して、A を変数インデックスで動的に参照する場合、

cbuffer _Array {
 uint A[256];
};

cb[] の参照は必ず Element 単位となるため 128bit のアライメント整合
が発生します。よって上記の cbuffer は
256 × 4 × 4 = 4096byte になります。(厳密には 4096-12=4084byte)
さらに次のように宣言すると

cbuffer _Array {
 uint A[256];
 float B[256];
};

本当は A を .x に、B を .y にでもパックしてしまえばデータ構造的には
要素をまとめることができるはずですが、
この場合もリニアに 512 × 4 × 4 = 8192byte とられてしまいます。
(厳密には 8192-12 = 8180byte)

struct _pack {
 uint a;
 float b;
};

cbuffer _Array {
 _pack A[256];
};

上のように自分で構造体にまとめると半分の 4096 (4096-8=4088) byte です。
ld 命令が 4要素単位となる tbuffer (Buffer) でも全く同じでした。

この「32bit×4」の制限を回避するには、Sampler を使って 1D Texture
としてアクセスする方法が考えられます。