Archives

August 2008 の記事

2008/08/24
AMD Stream SDK (2)

Global Buffer は Shader には無い機能で自由に書き込めますが、同時アクセスで
衝突します。2つの入力値を比較し、相違があった場合だけ値を書き込むような
使い方だと、1回の実行で結果を一カ所に集約できます。
コリジョン判定などに使えるかもしれません。

il_ps_2_0
dcl_input_position v0.xy
dcl_resource_id(0)_type(2d,unnorm)_fmtx(float)_fmty(float)_fmtz(float)_fmtw(float)
dcl_resource_id(1)_type(2d,unnorm)_fmtx(float)_fmty(float)_fmtz(float)_fmtw(float)
dcl_output_generic o0
sample_resource(0)_sampler(0) r0, v0.xy
sample_resource(1)_sampler(0) r1, v0.xy
eq r2.x, r0, r1
cmov g[0], r2.x, v0
mov o0, r2.x000
ret_dyn
end

コンパイル時のエラーは calclGetErrorString() で返ってきますが、
エラー行もわからずあまり意味のある情報が含まれていないので慣れるまで
デバッグは少々大変。

HLSL を使うには utilities\amdhlslCompiler を使います。
HLSL コンパイラ自体はただの lib で、amdhlslCompiler 以下でそのまま
実装されているようです。

関連エントリ
AMD Stream SDK



2008/08/23
AMD Stream SDK

コメント欄で、Vista で走らせる方法を教えて頂きました。
WindowsVista x64 SP1 + RADEON HD 4850 を使用しています。

AMD Stream SDK

(1) AMD Stream SDK 1.01.0_beta を install
(2) Folding@home GPU2 6.20 を install
(3) C:\Program Files (x86)\AMD\AMD CAL 1.01.1_beta\lib\xp32
  内の amdcalcl.dll, amdcalrt.dll の代わりに、
  C:\Users\<USER>\AppData\Roaming\Folding@home-gpu
  に入っている dll を使う。

(2) の注意点
すでに NVIDIA GPU 上で Folding@home を走らせたことがある場合は下記の手順で
 1. Folding@home を uninstall
 2. C:\Users\<USER>\AppData\Roaming\Folding@home-gpu を削除
 3. \C:\Program Files (x86)\Folding@home\Folding@home-gpu を削除
 4. Folding@home を再び install

例えば C:\Program Files (x86)\AMD\AMD CAL 1.01.1_beta\bin\xp32 に
入っているサンプルは、上記 dll と同じ場所にあれば実行できます。
サンプルのコンパイルは VisualStudio2008 でも大丈夫でした。

CAL の使い方は
C:\Program Files (x86)\AMD\AMD CAL 1.01.1_beta\doc
の ProgrammingGuide.pdf に従います。

GPU 上で走らせるプログラム kernel はほぼシェーダー相当の機能を持っています。
入出力用のリソースを確保し、context に割り当てて、シェーダー内のレジスタに渡します。

最初少々はまったのは PixelShader 相当だということ。
入力リソースは dcl_input に渡すわけではなく、あくまで texture のように
リソース扱いで sampler 経由で読み込みます。
4096 vector 以下なら constant buffer を使うことも可能です。

dcl_input で受け取るのはラスタライザの補間パラメータ相当です。
CAL の場合はこれを自分自身の ID と見なすことが出来ます。
いわゆるシステム値の SV_Position で、出力位置を指しています。

dcl_input の詳しい説明が載ってませんが、ほぼ次のような宣言の仕方で
使われています。

dcl_input_position v0.xy
dcl_input_interp(linear) v0.xy

例えば実行時の CALdomain が 0,0 から 128,128 までなら
0.5~127.5 のように 0.5 offset された値が入ります。
上の 2つの宣言の違いは特にありませんでした。

CALdomain は出力範囲の指定に相当します。RenderTarget の書き込み範囲です。
実行するプログラムの数や dcl_input のパラメータにも影響します。

シェーダーと違うのは、自由に読み書きできる共有メモリ Global Buffer を持っていることです。
Global Buffer (g[]) は Constant Buffer (cb[]) と同じように、命令内で直接
アドレッシング出来ます。書き込みも出来ます。

mad g[0], r0, g[1], r1

o0~ を使ったストリーム出力と違い書き込み制限がありません。

マニュアルに詳細が書かれていませんが、実際に試したところ 4850/4870 では
最大 2048 vector 使用することが出来ました。

常に 128bit = 4要素単位となるため、8192 float 相当 = 32KByte 分と考えられます。
特に同期などの仕組みがないので、同じ Global Buffer への書き込みが発生した場合、
値は不定となるようです。

実際に Global Buffer から値を読んで Global Buffer に書き込むプログラムを
走らせてみるとわかります。
同じタイミングで実行されているスレッドでは同じ初期値が読み込まれます。
実行スレッド数を増やしていくと、そのうち書き込んだ値を読み出している
スレッドも含まれるようになります。

実行はほぼ ID 順ですが、リソース読みだしを行うと順番が崩れてきます。
リソースアクセス待ち間のスケジューリングのためと考えられます。

DirectX11 の Compute Shader では同期アクセスがサポートされるらしいので、
同じメモリに書き込みを行って合計値を求めるような使い方ができるみたいですが
CAL ではおそらく出来ません。

RADEON HD 4850
##calDeviceGetInfo()
target=5  RV770
maxResource1DWidth=8192
maxResource2DWidth=8192
maxResource2DHeight=8192

##calDeviceGetAttribs()
target=5
localRAM=512
uncachedRemoteRAM=2047
cachedRemoteRAM=2047
engineClock=625
memoryClock=337
wavefrontSize=64
numberOfSIMD=10
doublePrecision=1
memExport=1

関連エントリ
AMD Stream Computing



●まとめ

・Animation 無しの場合

 ■ Transform Shader
  + in VertexStream 0 ( _LL_geometry00 ) M3+P
  + in ShaderResourceView ( _LL_geometry00 ) M3+P
  + in ConstantBuffer ( "GRoot" = _LL_rootWorld ) M4
  + out StreamOutput ( _LL_geometryWorld ) M3

・Animation ありの場合

 ■Animation Shader ( Animation Data がある場合のみ )
  + in VertexStream 0 ( _LL_geometry00 ) M3+P
  + in ShaderResourceView ( "GAnimation" = _LL_Anim00 ) M3
  + in ConstantBuffer ( "GTime" )
  + in ConstantBuffer ( "GBind" )
  + out StreamOutput ( _LL_geometryAnimation ) M3+P

 ■Transform Shader
  + in VertexStream 0 ( _LL_geometryAnimation ) M3+P
  + in ShaderResourceView ( _LL_geometryAnimation ) M3+P
  + in ConstantBuffer ( "GRoot" = _LL_rootWorld ) M4
  + out StreamOutput ( _LL_geometryWorld ) M3

 ■Bone Shader ( Bone Matrix を持っている場合のみ)
  + in VertexStream 0 ( _LL_geometry00 ) M3+P // 後半の BoneMatrix のみ
  + in ShaderResourceView ( _LL_geometryWorld ) M3
  + out StreamOutput ( _LL_geometryWorldB ) M3

M3 = Matrix:float4x3
M4 = Matrix:float4x4
P = Index:int4


・描画

 ■Draw IndexedInstanced (single)
  + in VertexStream 0 ( VertexBuffer )
  + in VertexStream 1 ( _LL_geometryWorld )
  + in ConstantBuffer ( "GCamera" )
  + in ConstantBuffer ( "GLight" )

 ■Draw Bone Indexed
  + in VertexStream 0 ( VertexBuffer )
  + in ShaderResourceView ( _LL_geometryWorldB )
  + in ConstantBuffer ( "GCamera" )
  + in ConstantBuffer ( "GLight" )



●Animation なしのまとめ

 ■ Transform Shader
 + in VertexStream 0 ( _LL_geometry00 )
 + in ShaderResourceView ( _LL_geometry00 )
 + in ConstantBuffer ( _LL_rootWorld ) 描画時に CPU が与える
 + out StreamOutput ( _LL_geometryWorld )


●Animation ありの場合

準備
 1. 頂点に Geometry の node 番号と weight 値を埋め込んであります。
 2. Animation データは plot した値をバッファにつめて格納します。
 3. 描画単位のノード毎に、参照する bone の逆行列をあらかじめ求めておいて
   GeometryMatrix の後ろに格納しています。
 4. データを読み込み、モデルに Animation データを Bind します。
   ノードとの対応表を作っておきます。

(1) Aniamtion の取り出し

単純化するため plot した値をそのままバッファに格納しています。
外部から描画すべき frame を与えて、そのフレームの Animation ノードを取り出します。
フレーム補間は容易に実現できますがここでは行っていません。

単に frame 値による値の選択なので、独立した描画パスに分ける必然性はありません。
ただし、モデルのノードとアニメーションのノードをマッピングする必要があります。

・アニメーションデータの n 番が、実モデルの何番の node に対応するのか
・対応するノードがモデルに存在しているかどうか

これらのノード対応表をデータを読み込んだあと、Animation を bind するときに
作成しておきます。

アニメーションデータのバッファ定義は下記の通り。

// 実際のアニメーションデータ
Buffer	_LL_Anim00
Usage	IMMUTABLE
Cpu	0
Bind	SHADER_RESOURCE
Format
	MATRIX:32x4F
	MATRIX:32x4F
	MATRIX:32x4F
 ~

ノード毎の frame 単位の値を、単一バッファにパックしています。
ノード対応表にはただの番号ではなく、バッファ内のオフセット値を入れておきます。

例えば index0~31 が node 3 のデータ、index 32~63 が node 1 に bind され
たとします。ノード→Animation の対応表は次のようになります。

 0: 無し
 1: 32
 2: 無し
 3: 0

ここでのセットアップ情報

// Shader Setup
Vertex			_LL_geometry00
CBuffer 		"GBind"= マップデータ
ShaderResourceView 	"GAnimation"= _LL_srv_Anim00
StreamOut		_LL_geometryAnimation
Draw	POINTLIST

その他のバッファは下記の通りです。

// アニメーション参照用
ResourceView	_LL_srv_Anim00
Link	_LL_Anim00
Format	32x4F BUFFER
Element	151110

// 出力バッファ
Buffer _LL_geometryAnimation
Usage	DEFAULT
Cpu	0
Bind	STREAM_OUTPUT SHADER_RESOURCE VERTEX_BUFFER
Format
	MATRIX:32x4F
	MATRIX:32x4F
	MATRIX:32x4F
	INDEX:32x4UI

出力は、アニメーションを適用した _LL_geometry00 の置き換えとなります。

// Animation Shader
struct TBindMap {
	uint	Remap;
	uint	reserved0;
	uint	reserved1;
	uint	reserved2;
};

cbuffer cb_GBind
{
	TBindMap	GBind[MAX_TRANSFORM_BUFSIZE_];
};

struct VS_INPUT_ANIMATION { // _LL_geometry00
	float4	Mat0		: MATRIX0;
	float4	Mat1		: MATRIX1;
	float4	Mat2		: MATRIX2;
	uint4	Parent		: INDEX;
	uint	VertexID	: SV_VertexID;
};

struct VS_OUTPUT_ANIMATION { // _LL_geometryAnimation
	float4	Mat0	: MATRIX0;
	float4	Mat1	: MATRIX1;
	float4	Mat2	: MATRIX2;
	uint4	Parent	: INDEX;
};

VS_OUTPUT_ANIMATION VS_Animation( VS_INPUT_ANIMATION In )
{
	VS_OUTPUT_ANIMATION	Out;

	float4	cmat0= In.Mat0;
	float4	cmat1= In.Mat1;
	float4	cmat2= In.Mat2;

	uint	id= GBind[ In.VertexID ].Remap;
	if( id != 0xffffffff ){
		// animation
		uint	offset= id * 3 + cFrame.x*3;
		Out.Mat0= GAnimation[ offset + 0 ] * cBlend.x;
		Out.Mat1= GAnimation[ offset + 1 ] * cBlend.x;
		Out.Mat2= GAnimation[ offset + 2 ] * cBlend.x;
	}else{
		// through
		Out.Mat0= In.Mat0;
		Out.Mat1= In.Mat1;
		Out.Mat2= In.Mat2;
	}
	Out.Parent= In.Parent;

	return	Out;
}


(2) 階層構造の解決

(1) の出力は _LL_geometry00 と同じものなので、これを入力として
Animation なしの場合と同じ Transform Shader に与えます。

Vertex			_LL_geometryAnimation
CBuffer			"GRoot"= _LL_rootWorld
ShaderResourceView	"GTree"= _LL_srv_geometryAnimation
StreamOut		_LL_geometryWorld
Draw	POINTLIST


(3) スキニングのためのマトリクス計算

それぞれの頂点が参照するノード個数分、静止状態で前計算した Bone の逆行列を
あらかじめ格納しておきます。これは BasePose に相当します。

この Matrix には Bone Matrix の参照用 id と、描画するオブジェクト自体が
存在する node の id を持たせておきます。

バッファ数を減らすためと管理しやすくするために、非 Animation データでも
使っていた GeometryMatrix ( _LL_geometry00 ) を流用します。
この node 用 Geometry Matrix の後ろに、追加で Bone 用 Matrix 領域を
確保しておきます。

_LL_geometry00 は index 部の .x に parent の node Geometry 番号を
格納していました。

Bone 用マトリクスは、.x に Bone Matrix の番号、.y に描画するオブジェクトの
node 番号を格納しています。

Buffer	_LL_geometry00
Usage	IMMUTABLE
Cpu 	0
Bind	VERTEX_BUFFER SHADER_RESOURCE
Format
	MATRIX:32x4F
	MATRIX:32x4F
	MATRIX:32x4F
	INDEX:32x4UI	// .x= parent/bone id,  .y= world id
# node 0
 ~
# Primitive0 - Bone0
f -0.187506 -0.875848 0.444671 -7.197771
f -0.011216 0.454579 0.890635 1.248997
f -0.982199 0.162011 -0.095059 1.356605
i  6  26  0  1
 ~

ここで必要なのは Bone Matrix の部分だけです。
この値を Vertex (Stream) として入力し、アニメーション変換済みの
Bone Matrix に乗算します。

StreamOut	_LL_geometryWorldB
Vertex		_LL_geometry00	// offset 付き (Bone Matrix のみ入力)
ShaderResourceView "GOutT"= _LL_srv_geometryWorld
Draw	POINTLIST


struct VS_INPUT_BONE {
	float4	Mat0	: MATRIX0;
	float4	Mat1	: MATRIX1;
	float4	Mat2	: MATRIX2;
	uint4	Parent	: INDEX;
};

struct VS_OUTPUT_BONE {
	float4	Mat0	: MATRIX0;
	float4	Mat1	: MATRIX1;
	float4	Mat2	: MATRIX2;
};


VS_OUTPUT_BONE VS_Bone( VS_INPUT_BONE In )
{
	VS_OUTPUT_BONE	Out;

	uint	boneid= In.Parent.x;
	uint	worldid= In.Parent.y;

	float4	rmat0= In.Mat0;
	float4	rmat1= In.Mat1;
	float4	rmat2= In.Mat2;

	M34_MATRIX	mp;
	mp= mul34(
			GOutT[ boneid*3 + 0 ],
			GOutT[ boneid*3 + 1 ],
			GOutT[ boneid*3 + 2 ],
			rmat0,
			rmat1,
			rmat2
			);

	// worldid の乗算を行うと動的な変化に対応できるけどしていない
	Out.Mat0= mp.mat[0];
	Out.Mat1= mp.mat[1];
	Out.Mat2= mp.mat[2];

	return	Out;
}


今見ると、無理に Transform Shader を共有しようと思わなければ
もっと簡略化できそうですね。

関連エントリ
Direct3D10 GPU だけでジオメトリ計算 (1)



アニメーションから描画までの一連の演算を GPU のみで行ってみます。
少々古いネタで恐縮ですが、実際に 1年くらい前に作成した描画パスです。

特徴はまじめに描画エンジンに組み込んだこと。
Maya 等のツールから出力したデータを、画面に描画するまでの一連の作業に対応できます。
やってる内容はたいしたものではないものの、実作業ではどんなデータが来るかわかりません。
さまざまな状況への対応を考えると、やることは意外に複雑です。

例えば Animation は任意の Model と bind 可能で、各 node と対応する順番も任意、
存在しない node は無視し、Animation しないノードと共存できる必要もあります。
Bone 構造を持ったデータでも Animation を Bind せずに描画する状況も考えられます。

欠点はレンダリング回数が増えたために遅くて実用にならなかったことです。
他にもいろいろ理由があるのですが、、今までお蔵入りでした。


●考え方

・Animation なし

(1) Buffer 上の Geometry を元に各ノードの world matrix を算出します。
(2) (1) の結果をもとに実際の Primitive 描画を行います。


・Animation あり

(1) 任意 frame の Animation 値を、node 対応付けしながら取り出します。
(2) (1) の出力を入力と見なして world matrix の算出します。
(3) node 毎に bone が参照している matrix と、前計算した逆行列を乗算します。
(4) 頂点毎に必要なノードを参照し、blend しながら描画します。


●Animation なしの場合

(1) TransformShader

あらかじめ各 node 毎の変換 Matrix を Buffer に格納しておき、
描画時に world matrix に変換します。

Matrix は stream 入力し、変換した結果もそのまま Stream Output します。
ただし各ノードは親の影響を受けるため、他の Matrix を参照する必要があります。
そのため全く同じ Geometry Matrix のバッファを

・Vertex (StreamInput)
・ShaderResourceView

の両方に入力します。
現在の node は Stream (Vertex) で参照し、階層をたどる場合に
ShaderResourceView を使います。

Matrix は 4x3 で、空いた 4要素に親の index 番号を格納しています。

// 各 node の matrix。あらかじめ用意しておく。書き換えない
Buffer	_LL_geometry00
Usage	IMMUTABLE
Cpu 	0
Bind	VERTEX_BUFFER SHADER_RESOURCE
Format
	MATRIX:32x4F
	MATRIX:32x4F
	MATRIX:32x4F
	INDEX:32x4UI	// .x= 親の index 番号、 .yzw= 未使用
# node 0
f  1.0  0.0  0.0  0.0
f  0.0  1.0  0.0  0.0
f  0.0  0.0  1.0  0.0
i  99999  0  0  1	// 99999 = 親無し
# node 1
f  1.0  0.0  0.0  0.0
f  0.0  1.0  0.0  0.0
f  0.0  0.0  1.0  0.0
i  0  0  0  1
 ~

必要な node の数だけ matrix が並びます。

セットアップは下記の通り。
"GRoot" や "GTree" は Shader 内のシンボル名で、それぞれ _LL_rootWorld と
_LL_srv_geometry00 を割り当てています。

// 描画時の Shader Setup
Vertex			_LL_geometry00
CBuffer			"GRoot"= _LL_rootWorld
ShaderResourceView	"GTree"= _LL_srv_geometry00
StreamOut		_LL_geometryWorld
Draw	POINTLIST

その他のバッファ定義

// Root の Transform 値。アプリケーションから渡す描画位置
Buffer	_LL_rootWorld
Usage	DEFAULT
Cpu	0
Bind	CONSTANT_BUFFER
Format
	MATRIX:32x4F
	MATRIX:32x4F
	MATRIX:32x4F
	MATRIX:32x4F

// ResourceView
ResourceView	_LL_srv_geometry00
Link	_LL_geometry00
Format	32x4F BUFFER
Elemet	4

// 出力用
Buffer	_LL_geometryWorld
Usage	DEFAULT
Cpu	0
Bind	VERTEX_BUFFER STREAM_OUTPUT SHADER_RESOURCE
Format
	MATRIX:32x4F
	MATRIX:32x4F
	MATRIX:32x4F

問題は、各ノードが親の影響を再帰的に受けること。
相互参照が発生するため 1pass では完了しません。
ここでは index を元に毎回 root までループして計算し尽くしています。
無駄が発生しますがとりあえず一回で終わります。

// Transform Shader

struct VS_INPUT_TRANSFORM {	// _LL_geometry00
	float4	Mat0	: MATRIX0;
	float4	Mat1	: MATRIX1;
	float4	Mat2	: MATRIX2;
	uint4	Parent	: INDEX;
};

struct VS_OUTPUT_TRANSFORM {	// _LL_geometryWorld
	float4	Mat0	: MATRIX0;
	float4	Mat1	: MATRIX1;
	float4	Mat2	: MATRIX2;
};

VS_OUTPUT_TRANSFORM VS_Transform( VS_INPUT_TRANSFORM In )
{
	VS_OUTPUT_TRANSFORM	Out;

	uint	parent= In.Parent.x;
	float4	cmat0= In.Mat0;
	float4	cmat1= In.Mat1;
	float4	cmat2= In.Mat2;

	// 親まで計算する
	for(; parent < 0xffff ;){
		M34_MATRIX	mp;
		mp= mul34(
				GTree[ parent ].M[ 0 ],
				GTree[ parent ].M[ 1 ],
				GTree[ parent ].M[ 2 ],
				cmat0,
				cmat1,
				cmat2
				);
		cmat0= mp.mat[0];
		cmat1= mp.mat[1];
		cmat2= mp.mat[2];
		parent= GTree[ parent ].Parent.x;
	}

	// 最後に root を乗算
	M34_MATRIX	mp2;
	mp2= mul34(
			GRoot[ 0 ],
			GRoot[ 1 ],
			GRoot[ 2 ],
			cmat0,
			cmat1,
			cmat2
			);

	Out.Mat0= mp2.mat[0];
	Out.Mat1= mp2.mat[1];
	Out.Mat2= mp2.mat[2];

	return	Out;
}


(2) 描画

上で求めた _LL_geometryWorld を元にモデルデータの描画を行います。
頂点毎の index で _LL_geometryWorld を参照してもいいし、
オフセットを付けて空いている Stream に入れ、
1回だけのインスタンシングでパラメータを受け取ることも出来ます。

インスタンシング描画命令を使うとオフセットを渡せるので、
ジオメトリ番号を渡すためだけにバッファを書き換える必要がなくなります。



NVIDIA の CUDA と同じように AMD (ATI) では AMD Stream SDK が用意されています。

AMD Pioneers Stream Computing on Graphics Processor Units
AMD Stream SDK

XP のみ対応となっているようで Vista では動作しませんでした。
RADEON + Vista で Folding@Home が動作しない理由もこの辺でしょうか。 (2008-08-19 追記を参照してください)
インストール自体は可能でドキュメントは読むことが出来ました。

CUDA は C言語 の拡張で、Cg と同じように専用コンパイラを用いた高級言語が
使われています。内部の詳細は出来る限り見えないように隠されています。
対する AMD Stream SDK は R600 (RADEON HD2000/3000) の詳細な資料が付属しており
ハードウエアから GPU の ISA までより詳しく内部構造を理解できるようになっています。

資料を見ると、GPGPU よりと思われる G80 系の GeForce と違い、
従来のグラフィック向け GPU 色をそのまま強く残しているように見えます。
プログラムの実行もシェーダーパイプラインをほぼなぞる形で実行されており、
メモリアクセスも頂点やテクスチャのフェッチと変わらないようです。

ネイティブコードは VLIW なので、これをそのまま人間が手で書いてパイプライン
最適化を行うのは困難です。
そのため、よりわかりやすくハードウエアを抽象化した
CAL (Compute Abstraction Layer) が用意されています。

CAL で用いられる言語もアセンブラですが、ハード依存を無くした比較的シンプルな
命令セットになっているようです。
この命令は IL (Intermediate Language) と呼ばれています。

IL でプログラムを用意しておけば、ドライバが実行時に GPU にあわせて
ネイティブな GPU 命令にコンパイルしてくれます。

この仕組みは GPU としてはごく当たり前の動作です。
例えば Direct3D の Shader は下記の手順で実行されています。

 HLSL → Direct3D IL → Driver 内蔵 Compiler → ネイティブコード

もともと Shader も D3D で定義された汎用の中間コードを、さらにコンパイルして
実行しているわけです。
IL 自体 ShaderModel 4.0 の HLSL がはき出すコードによく似ています。
実際 Shader とほとんど同じもので、HLSL で記述することもできるようです。

グラフィック向け Shader と異なる点としては
・OpenGL/DirectX といったグラフィック用 API を使わなくて良いこと。
 描画とか画面とか複雑な初期化がいらない。
・double 演算など専用の拡張命令が使えること
・オフセットを利用してメモリ書き込み位置をある程度指定出来ること
等でしょうか。

CAL SDK の他に Brook plus SDK が付属しており、Stream プロセッサ向けの
上位言語を使うこともできるようです。

素の GPU にかなり近いこともありますが、比較的低いレベルで抽象化し
さまざまな上位言語に対応する方針であること、など
CUDA との方針の違いがよくわかります。

2008-08-19 追記:
コメントで指摘がありましたが、Folding@home は RADEON + Vista で動きます。
log file をよく見たら Nvidia と誤認識されており、ビデオカードを頻繁に
入れ替えていたのが原因だったようです。
すみません、OS は全く関係なくただの勘違いでした。

UAC 設定や管理者権限で実行したかどうかによりますが、
C:\Program Files (x86)\Folding@home\Folding@home-gpu
だけではだめで
C:\Users\<USER>\AppData\Roaming\Folding@home-gpu
のファイルもすべて消してから Folding@home の GPU2 client (6.20) を
入れ直したら動作するようになりました。

また Vista 対応 CAL runtime も入るとのことで、SDK も試せるかもしれません。
こちらはまだ未確認です。それらしき dll は Roaming 側に入っていました。


MYCOM SIGGRAPH 2008 - NVIDIAが公開、DirectX 11世代の次世代GPUについて

DirectX11 への流れは思ったよりもずっと速いのかもしれません。
直前の Direct3D9 が長かったのでなおさらです。

API セットを一新した Direct3D8 はシェーダーへの流れを加速化し、
GPU の新たな可能性が明らかになりました。
D3D8 の欠点など小規模な改良修正を施し、将来を見据えて先の先の仕様まで
盛り込んだ D3D9 が出たのはわずか 2年後。
この後 D3D10 が出るまで 4年以上、長期にわたり D3D9 が使われ続けています。

汎用化の流れから再び仕様を完全に覆した D3D10 が登場しました。
それも今年の末でおよそ 2年。
足りない部分が明らかとなり、再びフィードバックの時期が来たのかもしれません。
この流れだと 11 はそれほど大幅な仕様変更ではなく、概念的には D3D10 を継承し、
比較的長期間使われるものになるのではないでしょうか。


上記 MYCOM JOURNAL の記事を見ると、パイプラインには新たに HullShader、
Tessellator、DomainShader が追加されています。

従来マルチパスレンダリングは、貧弱なピクセルパイプラインを補うのが目的でした。
その後 PixelShader に傾倒した高機能化が行われ、D3D9 ShaderModel3.0 で
この流れはほぼ一段落しています。

Direct3D10 ではむしろ StreamOutput を使ったジオメトリのためのマルチパスが
必要となりつつあります。
ジオメトリの場合は頂点数の増減など CPU へのフィードバックは難しく、
Index が展開されてしまう欠点もあります。

 (いっそ GPU 側だけで Draw 発行までできたらいいのですが、、
  Larrabee なら出来るのかもしれません。)

Direct3D 11 におけるパイプライン構成要素(HS、TS、DS)の追加は、
このようなジオメトリに対するマルチパス化要求とその問題点を
スマートに解決してくれるものと期待しています。


D3D10 のテクスチャは汎用的なバッファの一種でピクセルフォーマットが
拡張されています。

特に整数型の直行性が高くなり、固定少数として扱うかどうか、符号付きと
みなすかどうかといったバリエーションが増えています。
また Texture Array が追加されたため、従来のテクスチャフォーマットよりも
次元が増えました。

DirectX SDK のマニュアルでは、Direct3D 10 用の DDS フォーマット拡張を
定義しています。
残念ながらこの解説は不完全で、このドキュメントを見ても厳密な DDS のヘッダ
構造がわかりませんでした。

DirectX SDK の texconv10 コマンドを使うと D3D10 用のテクスチャを生成する
ことができます。このコマンドでヘッダの違いを調べてみました。
以下 DirectX SDK Aug2008 x64 を使用しています。


● ヘッダサイズの疑問

DDS テクスチャのヘッダは先頭の dwMagic と構造体を合わせてちょうど 128byte です。
Programming Guide for DDS によるとヘッダブロックは次のように定義されています。

In Direct3D 10:
  DWORD             dwMagic;  // 4byte
  DDS_HEADER        header;   // 124byte  = 0x7c
  DDS_HEADER_DXT10  header10; // 20byte

In Direct3D 9:
  DWORD             dwMagic;  // 4byte
  DDSURFACEDESC2    header;   // 124byte  = 0x7c

sozeof(DDS_HEADER) == sizeof(DDSURFACEDESC2) == 124byte で内容は互換性が
あります。

Direct3D10 で追加された DDS_HEADER_DXT10 は 5要素の 32bit UINT でできており
20byte と少々中途半端な大きさです。ヘッダサイズのアライメント崩れてしまう
のでこのような構造にするとは考えられにくいのが正直なところです。
例えば R32G32B32A32_FLOAT 型のテクスチャを読み書きする場合でも、ヘッダを
含めると SSE の直接アクセスに制限が生じることになります。

DDS_HEADER(DDSURFACEDESC2) の最後、DDS_PIXELFORMAT の後ろがちょうど
20byte あるので、もしここに格納されるのならつじつまが合います。

ところが実際に texconv10 で D3D10 専用形式に変換してみると、
ぴったりファイルサイズが 20byte 増えています。
128byte 目以降に追加の DDS_HEADER_DXT10 が入っていました。

よって DDS_HEADER_DXT10 の追加ブロックはマニュアルのヘッダ構造が正解です。
Direct3D 10 用 DDS はヘッダが 20byte 増えて 148byte になります。


● ヘッダ区別の方法

DDS ファイルを開いたときに、Direct3D 10 の拡張情報が含まれているかどうか
判断する必要があります。先頭 128byte 部分はほぼ完全な互換性があり、
追加情報を読むべきかどうかの手段が明確にされていないようです。

基本的に D3D9 形式で表現できるテクスチャは D3D9 ヘッダのみ格納するようです。
例えば次のように dds 変換した場合

(1) texconv   -ft dds white.bmp -m 1 -sx _dx9   -f a8r8g8b8
(2) texconv10 -ft dds white.bmp -m 1 -sx _unorm -f r8g8b8a8_unorm
(3) texconv10 -ft dds white.bmp -m 1 -sx _sint  -f r8g8b8a8_sint

出力
(1) white_dx9.dds   262272byte
(2) white_unorm.DDS 262272byte
(3) white_sint.DDS  262292byte

同じ texconv10 を使っても、D3D9 形式と互換性のある (2) と D3D10 専用の (3)
ではファイルサイズに 20byte の差が生じます。

このとき (2) の DDS_PIXELFORMAT は DDPF_RGB|DDPF_ALPHAPIXELS となり
Mask にも一通り正しい値が入りました。

(3) の DDS_PIXELFORMAT は DDPF_FOURCC で、dwFourCC に 0x30315844 = 'DX10'
が入りそれ以外はゼロです。

よって、D3D10 拡張 DDS の場合は dwFourCC を見て、'DX10' の場合のみ追加
の D3D10 ヘッダを参照すればいいようです。

ここで悩んだのは、(2) のテクスチャにも 128byte 目以降に追加のヘッダ情報が
格納されているように見えること。
当初 dwFourCC != 'DX10' の場合でも DDS_HEADER_DXT10 が挿入される場合が
あるのではないかと疑ったのですが、ファイルサイズを見るとデータ領域と
判断して良さそうです。データが壊れているのかもしれません。

その後いろいろ試したけど、やはり texconv10 ではデータが壊れてしまう問題が
生じるようです。x86 bin でもだめ。
March 2008 の texconv10 だと正しい値が取れています。要調査。



新 masafumi's Dialy さんによると DirectX SDK August 2008 が出ている
そうなので入れました。

とりあえずマニュアルとか。リリースノートに無いところ

マニュアルでの DXGI の扱いが変わっているようです。
以前は Direct3D 10 のカテゴリの一部だったのが、Direct3D 10/9 と並列な
位置に移動しています。

その他 Primitive Topology、Stream Output あたりにも手が入っている感じ。

Linking Static and Dynamic Libraries に d3d10sdklayers.dll の項目が増えてます。

個人的に気になった変更は stop 命令。
今までマニュアルに載っているのになぜか使えなかった、HLSL の stop 命令が
削除されていました。
やはり clip 命令 ( clip( -1 ) 等) が正式な手法なのでしょうか。