VistaでWindowsMobile5 の開発環境設定メモ

Vista で WindowsMobile 5.0 の SDK 環境を作るメモです。
ノートにとりあえず作った最小の環境手順です。

WindowsCE の開発場合、何らかの WindowsPC 側に開発環境を構築する
必要があります。クロス開発です。

● WindowsVista

 WindowsVista を使いました。まだ特に何も設定していない状態です。

● VisualStudio2005

 まずは VisualStudio2005 を install します。
 残念ながら Express Edition は Mobile 開発に対応していないようです。
 下記の表を見ると Standard Edition からになってますね。

 ・Visual Studio 2005 機能比較

 今回は Professional Edition を使ってます。Standard では未確認なので
 ご了承ください。

 Win32API しか使わないので、インストール時に Custom を選んで
 C++ 関連残してあとはチェックをはずしました。
 .NET Framework を使うならばたぶん C# も必要でしょう。

 途中で互換性がないとか言われますが、気にせず実行を選んでとりあえず
 進めます。

 VisualStudio が終わって更新チェックもドキュメントのインストールも
 しないで完了。
 ドキュメントはオンラインだけで何とかして HDD をできるだけ
 食わないようにします。

● VisualStudio2005 SP1

 VisualStudio SP1 の install は Vista の Microsoft Update からできます。
 まず Windows Update を Microsoft Update に変更。
 更新をかけるとインストールされます。

 下記のファイルをインストールします。
 Visual Studio 2005 Service Pack 1 Update for Windows Vista

● WindowsMobile5.0 SDK

 ダウンロードは下記のページが参考になります。
 ・Windows Mobile Device – Download

 WindowsMobile5.0 の
 ・WindowsMobile5.0 SDK for PocketPC
 をダウンロードしてインストールします。

 このとき ActiveSync が必要だけど入っていない、とかいわれますが
 無視してインストールします。

 Vista の場合標準で WindowsMobile デバイスを繋いでアクセスできるように
 なっているので、SDK を使ってデバッグするだけなら
 Windows Mobile デバイスセンターを入れなくても大丈夫です。

 なので、普段同期を取ってる PC と開発に使う PC が別な場合でも、
 いちいちゲスト設定を選ばなくて良いので簡単になりました。

 また動作確認やデバッグに、実機 (Device) だけ使うなら Emulator も不要です。

● 接続&実行

 デバイスを USB で接続します。
 EM・ONE の場合は Bluetooth を内蔵していますので、Bluetooth で
 つないでも OK です。

 後は通常の VisualStudio による開発そのままなので、
 WindowsMobile5.0 向けのプロジェクトを開いて、ビルドして、
 接続先を Device に設定して実行です。

やはり VisualStudio2005 の購入が最初の難関でしょうか。

たしか一番最初は、VisualStudio だけでなくて WindowsCE 用の
開発キットも有料でした。
「WindowsCE Toolkit for Visual C++ 6.0」という箱と CD が
今でも手元に残ってます。

その後開発キットが無料でダウンロードできるようになり、
さらには

 ・eMbedded Visual Tools 3.0
 ・eMbedded Visual C++ 4.0

が無料で手に入るようになって、Mobile 向け環境は一時期全部ダウンロード
できるようになりました。
eMbedded Visual Tools/C++ は使い方もメニューも 2003 以前の
VisualStudio そのままです。

PocketPC2003SE 以前の SDK を使う場合は今でも上記ツールが使えますので、
WindowsMobile5.0 SDK にこだわらなければアプリケーションを作ることが
可能です。

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
としてアクセスする方法が考えられます。

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 が無いので起動できませんでした。