月別アーカイブ: 2009年1月

携帯電話 Android

Android Dev Phone 1 (G1) の実機端末を見せてもらいました。
想像よりずっと良かった、というのが第一印象です。
端末は思ったよりもコンパクトでしっかりした作り。
スライド式キーボードも弧を描くような動きでユニーク。
ボタンの中央にあるのはカーソルキーでもスティックポインタでもなくてトラックボール。

HTC T-Mobile G1

タッチパネルは指で軽く触れただけでスムーズに動きます。
これ iPhone/iPod touch と同じです。
ノート PC などのタッチパッドと同じで、指で操作するならこちらの方がやりやすいと感じます。

WindowsMobile 系端末に使われてる感圧式タッチパネルはスタイラスが使えるものの、
触れただけでは反応せず少々押す力がいります。
指操作だと反応してるかどうか若干わかりにくく、ものによっては爪を立てた方が
操作しやすくなります。
HTC の G1 も同様の感圧式かと思っていたので、この点でまず気に入りました。

使われているチップ自体は Touch Diamond と同じ Qualcomm MSM7201A だそうです。
画面解像度は iPhone 等と同じ 480×320 でした。
GPS 等は Diamond にもありますが、電子コンパスが目新しい機能です。

Android の OS 自体はさまざまな端末にも多くの方の努力によって移植されています。
HTC の WindowsMobile 端末で動作するものがあるようです。

HTC Android

実際に手持ちの EMONSTER lite (S12HT, Touch Dual) と Touch Diamond (S21HT) で
試してみました。上記サイトを参考に、落としたファイルの exe を実行。

S12HT は一発目は起動成功しましたが、2度目以降は起動したり出来なかったりで
何度もリセットしながらです。
Android の操作をよく知らないせいか、試す前にホーム画面に戻れなくなったりと
はまってしまってまだきちんと使えていません。

S21HT は比較的すぐに起動できました。
コマンドラインに仮想キーボードからコマンドをタイプしなければならないですが、
しばらく待つと Dev Phone で見たような画面になります。
カーソルキー上下でメニュー階層の行き来が出来るようですが、Diamond のカーソルは
押しづらくて、さらに間違って OK (←) が押されてしまうと固まるみたいなので
こちらもまだうまく使いこなせていないところです。

EMONSTER lite S12HT android
Touch Diamond S21HT Android
Touch Diamond S21HT Android

2009/01/17 23:58 写真追加

Intel GMA500 の機能と性能と Aero

Atom Z500 系の CPU を使ったノートが増えてきました。
小型軽量なものも多く魅力的です。
レビュー記事を見ていると Vista や Windows7 の Aero は off になっているとのこと。
気になったので調べてみました。

使われている GPU はチップセット (System Controller Hub) US15W 内蔵の GMA500。
最近携帯デバイスで多く使われている PowerVR core の一種ですが、アーキテクチャが
さらに進化した SGX に属するもののようです。

その特徴は Unified Shader であること。
DirectX10.1 (Direct3D10.1) 世代に対応できるだけの高度な機能を持っており、
VertexShader, PIxelShader や GeomteryShader を実行可能。
32bit float 演算可能でプログラム長の制限もなく分岐等の制御命令も備えています。
GPGPU として汎用処理に用いられることも想定しているようです。

機能だけ見ると GMA950~ 等よりも上に見えます。
実際に D3D10 対応ドライバが出ているのかどうか、Windows で D3D10.1 や
ShaderModel4.1 が使えるのかどうかわかりませんが、かなり興味が出てきました。

ドキュメントはこのあたりから落とすことが出来ます。
IntelR System Controller Hub US15W Technical Documents

詳しい仕様は Datasheet の方で、Specification update でいくつか更新が入っています。
(update の方で 2GB RAM 対応が書かれています)

datasheet 「9 Graphics, Video, and Display」の一番最初、頂点性能なのに
15 clock/triangle と書かれている点がまず気になりました。
これは 3頂点分なのか、直後に書いてあるように
「 Vertex/Triangle Ratio average = 1 vtx/tri 」で 1頂点分なのか、
それとも 「 peak 0.5 vtx/tri 」の方を指している (つまり1頂点の半分の数値)
なのか曖昧です。

ただ 1頂点で 15cycle は少々多すぎような気がします。実際に計算すると
200MHz 動作なので 13.3M triangle/sec 。
wikipedia PowerVR に書かれている SGX535 の 28Mpoly/sec と比べて半分ほどです。

またピークの fill rate は 2pixel/clock と書かれています。
200MHz なので 400Mpixel/sec。
この数値は GPU としてはかなり低く GMA950 の数分の一。ここで重要なのが
PowerVR であるという事実。PVR はバスの効率を 2~3 倍とみなすため、
800M~1Gpix/sec 相当と書かれていることがあるようです。
Z/Stencil を内部メモリだけで処理可能で、3D のシーンなどポリゴンの重なりが
多くても、描画順に依存せずに常に一番上のポリゴンのみ描画可能だからです。

200MHz という記述は datasheet p.46 (CFG による選択で GFX 200MHz) や
Specification update の p.12 に Graphics Frequency 200MHz と書かれています。
112/160MHz はモニタ出力時のドットクロックのことで、core の動作クロックでは
ないようです。

NVIDIA や AMD で sp, spu 等と呼ばれているシェーダーユニットは、PowerVR SGX
だと USSE (Universal Scalable Shader Engine) という名称になっています。
例えば下記 wikipedia の記述を見ると SGX520~540 の性能はちょうど整数倍です。

wikipedia PowerVR

GeForce や RADEON のように、シェーダーユニットの個数でグレードを分けている
のかもしれません。となると問題は GMA500 にはいったい何個載っているのか。

datasheet の説明を読むと、どうやら USSE は 2個ではないか、と思えます。
wikipedia の記述には GMA500 のシェーダーユニットは 4個と書かれています。
(SGX535相当とのこと) でも 4個だといまいち計算が合いません。

wikipedia Intel GMA

datasheet には同時に 4つのシェーダーが実行可能状態になると書かれていますが、
もしかしたら同時実行ではなくインターリーブしている可能性もあります。
(ちなみに待機状態を含めて 16スレッドの状態を同時に保持できるようです。
レジスタは 1スレッドあたりスカラー 128個)
また下記の記事を見ても 535 までは USSE は 2個であるとのこと。

Centrino Atomにも搭載されるIMGのPowerVRビジュアルIPコア

さらに PowerVR の本家サイト下記ページから、Intel CE3100 の pdf を
読むことが出来ます。

Imagination Intel

Intel CE3100 は同じく GMA500 を搭載したメディアプロセッサで、pdf によると
dual USSE、13M triangle/sec、 2pixel/clock と書かれていました。
こちらの数値 13M triangle/sec は 200MHz 動作の 15clock/triangle とも
一致しますし、US15W の GMA500 と同じと思って良さそうです。
結局 SGX530 に近い数値ですが、同じものなのかそれとも計算方法が違うのかは
わかりません。

USSE の演算ユニットの構成は詳しくはわかりませんが ALU は 32bit 幅とのこと。
他の GPU でも D3D10 世代の Unified Shader はスカラー単位で動作しているので
USSE も同じような構造になっているのかもしれません。

もし 1 USSE が 1 ALU だとしたら、unified shader をフルに割り振っても
float4 の計算に 2cycle かかります。2pix/clock に間に合いません。
datasheet によると ALU は float x1 または fixed16 x2 または int8 x4 を
SIMD として一度に演算できるそうです。
レガシーな GDI のように 8bit ×4 の 24/32bit color ならば 1 ALU だけで済みます。
この場合のみ 2pix/clock が実現できるという意味かもしれません。

逆に言えば pixel にも float 演算が必要な ShaderModel2.0 以降は、ピクセル処理
速度が 1/4 になるということ。RGB だけでも 1/3。
ShaderModel1.0 でも符号付き 8bit なので 9bit 必要です。
おそらく fixed16 の演算が必要になると思われます。この場合 1/2。
Unified Shader なので頂点や GeomteryShader など他の処理も割り込みます。

もしこれらの仮定が正しいとするなら、GMA500 は pixel 性能が足りていないのだと
予想できます。3D のように深い重なりが無ければ PowerVR の特性も活かせず、
タイトなバスがそのまま見えてしまうでしょう。

特に Aero が半透明やレンダリング途中のフレームバッファを使った特殊効果を
利用しているなら、PVR の良いところがさっぱり発揮できていないのかもしれません。
よくよく考えると相性悪そうです。タイルをまたぐ大きなポリゴンも多いし。
さらに ShaderModel2.0 以上を必要とする Aero だと、シェーダーためにカラー
演算能力が 1/4 になっている可能性もあります。

Aero が使えなくても D3D10.1 相当のシェーダーが使えればおもしろそうなので、
実物を触る機会があったら試してみたいと思っています。
そういえばテクスチャユニットとかは全く情報がありませんでした。

これらの内容はすべてドキュメントを元にした想像で書いていますので、
実際に検証しながら調べたわけではないです。
いろいろ勘違いしている可能性が高いですのであらかじめご了承ください。
間違いがありましたらごめんなさい。

続き>Intel GMA500 のスペックについて考える。続き (2)

HTC Touch Diamond で Direct3DMobile その(10) d3dmclock v1.10 3Dクロック 更新

メニューから任意の画像を読み込めるように変更しました。(前回)
対応フォーマットも大幅に増えて、任意サイズの画像を直接背景として登録できます。

d3dmclock HTC Touch Diamond
↑ Windows7 ぽい感じに・・

ダウンロードはこちら
d3dmclock v1.10 ダウンロードページ

WindowsMobile 用アプリです。

速度はだいたい 16~21fps 程度です。
速度は主に時間帯と背景テクスチャの解像度で変わります。
時間帯で速度が変化するのは、各数字モデルのポリゴン数が違うから。

1024×1024 に変換されてしまう大きな画像だともっと速度が落ちるかもしれません。
HTC Touch Diamond は VGA (640×480) なので、512×512 がちょうど良いくらいでしょう。
QVGA の端末ならもっと小さくて構いません。

Touch Diamond は 2.8インチで VGA (640×480) の解像度があるため、かなり密度が
高くきれいに見えます。輪郭のジャギも気にならないし、この密度でリアルタイムに
レンダリング出来てリアルタイムに動いているのだから十分かもしれません。
blog のキャプチャは 1/4 に縮小しています。

WindowsMobile だと、せっかく載っている 3Dアクセラレータがあんまり活用されていないのは
もったいないですね。

テクスチャの読み込みは、当初 Direct3DMobile D3DMX のテクスチャローダーを
そのまま使用していました。これ対応フォーマットは dds と bmp だけ。
しかも bmp は 16bpp を読み込めないことがわかりました。
さらに 2の n乗以外のサイズも読み込めるけど固まったかと思うくらい低速です。

テクスチャローダーを作り直しました。
参考にしたのは WindowsMobile6.0 SDK サンプル
Windows Mobile 6 SDK\Samples\Common\CPP\Win32\Imaging

これで bmp だけでなく jpeg や png 、gif などメジャーなものはたいてい
読み込めるようになりました。しかも速いです。

流れは次の通り

(1) IImage として画像を読み込む
(2) IBitmapImage に変換する
(3) LockBits() してピクセル情報にアクセス
(4) SystemMemory の Surface (CreateImageSurface()) に格納する
(5) CreateTexture()
(6) Texture から Surface を取り出す。
(7) (6) の Surface に (4) の Surface をコピーして vram に転送
(8) テンポラリリソースとインターフェースを Release

#include  

// interface 取得
IImagingFactory*	iImageFactory= NULL;
CoCreateInstance( CLSID_ImagingFactory, NULL, CLSCTX_INPROC_SERVER,
			IID_IImagingFactory, &iImageFactory );
// ファイル読み込み
IImage*	iImage= NULL;
iImageFactory->CreateImageFromFile( file, &iImage );

ImageInfo	info;
iImage->GetImageInfo( &info );
int	w= info.Width;
int	h= info.Height;

// bitmap に変換
IBitmapImage*	iBitmap= NULL;
iImageFactory->CreateBitmapFromImage( iImage, w, h,
	PixelFormat24bppRGB, InterpolationHintDefault, &iBitmap );

iImage->Release();
iImageFactory->Release();

// lock
static BitmapData	lockdata;
iBitmap->LockBits( NULL, ImageLockModeRead, PixelFormat24bppRGB, &lockdata );

lockdata.Width;
lockdata.Height;
lockdata.Stride;
lockdata.Scan0;

// texture を作成
IDirect3DMobileTexture*	iTexture= NULL;
CreateTexture( w, h, 1, 0, D3DMFMT_R5G6B5, GetTexturePool(), &iTexture );

// SystemMemory の surface を作成
IDirect3DMobileSurface*	iSurface= NULL;
CreateImageSurface( w, h, D3DMFMT_R5G6B5, &iSurface );

// 書き込み
D3DMLOCKED_RECT	dlock;
iSurface->LockRect( &dlock, NULL, 0 );
uintptr_t	di= reinterpret_cast( dlock.pBits );
for( int y= 0 ; y< h ; y++ ){
    unsigned short*	dp= reinterpret_cast( di );
    for( int x= 0 ; x< w ; x++ ){
        const unsigned char*	sp= image.GetXY( x, y );
        unsigned int	b= sp[0];
        unsigned int	g= sp[1];
        unsigned int	r= sp[2];
        *dp++= ((r<<8)&0xf800)|((g<<3)&0x07e0)|((b>>3)&0x001f);
    }
    di+= dlock.Pitch;
}
iSurface->UnlockRect();

// texture の surface を取り出す
IDirect3DMobileSurface*	iTexSurface= NULL;
iTexture->GetSurfaceLevel( 0, &iTexSurface );

// コピー
CopyRects( iSurface, iTexSurface );

iSurface->Release();
iTexSurface->Release();

// unlock
iBitmap->UnlockBits( &lockdata );
iBitmap->Release();

関連エントリ
HTC Touch Diamond で Direct3DMobile その(9) d3dmclock v1.00 3D クロック
HTC Touch Diamond で Direct3DMobile その(8) ノーマルマップの解説
HTC Touch Diamond で Direct3DMobile その(7) ノーマルマップを表示する
HTC Touch Diamond で Direct3DMobile その(6) 頂点性能続き
HTC Touch Diamond で Direct3DMobile その(5)
HTC Touch Diamond で Direct3DMobile その(4) 高速化
HTC Touch Diamond で Direct3DMobile その(3) 実際の頂点性能
HTC Touch Diamond で Direct3DMobile を使う。その (2)
HTC Touch Diamond で Direct3DMobile を使う。ハードウエアアクセラレータ

HTC Touch Diamond で Direct3DMobile その(9) d3dmclock v1.00 3D クロック

せっかくなのでもうちょっと実用的なやつを。
デジタル時計にしてみました。

d3dmclock

HTC Touch Diamond の加速センサーに対応したので、本体の傾きに合わせて画面が
スムーズに回転します。
意味もなく数字 1つ 1つがポリゴンです。

d3dmclock
↑数字が不揃いなのはバグではありません。

ダウンロードはこちら
d3dmclock v1.00

WindowsMobile6.0/6.1 で動作します。加速センサーが無くても起動します。
ただし 3Dアクセラレータがないと非常に低速です。
おそらく HTC Touch Diamond 系、Touch Pro 等で動作すると思われます。

加速センサー以外にも、画面タッチの左右で回転、上下でズームします。

d3dmclock

↑どんな角度にもなります。

背景画像は適当なので入れ替えて使ってください。
プログラムと同じフォルダに入っている bgimage0.bmp ~ bgimage2.bmp です。
サイズが 256×256 や 512×512 ならおそらく何でも大丈夫です。

textimage0.dds~textimage7.dds ファイルを置き換えれば、数字用のテクスチャも
入れ替えできます。こちらもサイズは 2の n乗で mipmap が必要です。
フォーマットは R5G6B5 にしてください。

Menu の Light にチェックを入れると、光源を操作できます。
この状態で画面をタッチすると、タッチした位置から画面中央に向かうベクトルを
光源の向きと見なします。

iPhone/iPod touch みたいにスムーズに動くものを、と思ったけどなかなか難しいですね。
Touch Diamond 系をお持ちの方はよろしければ一度お試しください。

関連エントリ
HTC Touch Diamond で Direct3DMobile その(8) ノーマルマップの解説
HTC Touch Diamond で Direct3DMobile その(7) ノーマルマップを表示する
HTC Touch Diamond で Direct3DMobile その(6) 頂点性能続き
HTC Touch Diamond で Direct3DMobile その(5)
HTC Touch Diamond で Direct3DMobile その(4) 高速化
HTC Touch Diamond で Direct3DMobile その(3) 実際の頂点性能
HTC Touch Diamond で Direct3DMobile を使う。その (2)
HTC Touch Diamond で Direct3DMobile を使う。ハードウエアアクセラレータ

HTC Touch Diamond で Direct3DMobile その(8) ノーマルマップの解説

設定等をもう少し説明してみます。(→前回)

Direct3DMobile Touch Diamond

ダウンロードはこちら
bumptest v1.00

スマートフォン HTC Touch Diamond は Qualcomm MSM7201A 内蔵の
3D アクセラレータを搭載しており ATI の GPU core となっています。

Direct3DMobile は PC でいう DirectX8 のサブセットですが、機能自体は
DirectX7 世代相当で固定パイプラインのみ。シェーダーは使えません。

caps を調べるとハードウエアアクセラレータとして認識していることがわかります。

D3DMDEVCAPS_HWTRANSFORMANDLIGHT
D3DMDEVCAPS_HWRASTERIZATION
D3DMDEVCAPS_NATIVEFLOAT

また使用できるマルチテクスチャは 2枚で TextureStage 数も 2段です。
無理矢理シェーダーにたとえれば ShaderModel 1.0 でピクセル単位に

・テクスチャ命令 x2
・演算命令 x2

を実行できるということ。DirectX7 世代のレジスタコンバイナそのままです。
TextureStage で使用できる演算として D3DMTEXOPCAPS_DOTPRODUCT3 が有効に
なっていたのでこれを使用します。

TextureStage には外部から与えられる定数がありません。
試しに D3DMRS_DIFFUSEMATERIALSOURCE を使って頂点カラーの代わりに Material
からパラメータを取れないか試しましたがだめでした。
これはライティングユニットへの入力時にのみ機能するようです。

外部から定数を渡すことが出来ればすぐにでもオブジェクトスペースの
ノーマルマップでテストできるのですがあきらめます。
パラメータは頂点カラーとして渡すことにします。
どうせ頂点を経由するなら最初からタンジェントスペースにします。

頂点の光源計算はもともと CPU で行っていました。
このときオブジェクトスペースに変換した光源ベクトルを使いますが、ここで
DotProduct せずにベクトルをそのままカラー値として出力します。

まずは D3DMTEXOPCAPS_DOTPRODUCT3 のベクトルフォーマットを確認します。
いくつかのカラー値を通してみてどのような復号が行われているか推測。
マニュアルには符号付きとだけ書かれており明確ではありませんでしたが、
やはりシェーダー同様 _bx2 相当 ( (x-0.5)*2 ) でした。

モデルデータの頂点にはオブジェクトスペースからタンジェントスペースへの変換
マトリクスを埋め込んでおきます。
1軸は法線と共有するため +2 vect。CrossProduct するなら +1 のみ。
データの生成と export は昔 3ds Max 用に作った自作プラグインを使用しています。

WorldSpace (GlobalSpace)
   → ObjectSpace (LocalSpace)
       → TangentSpace (TextureSpace)

元の光源ベクトルは WorldSpace に配置されているため、頂点法線も WorldMatrix
(3×3) で変換してから演算する必要があります。
一般的に光源の数より頂点の方が多いので、CPU 演算の手抜きライトの場合は光源の方を
WorldMatrix(3×3) の逆行列で ObjectSpace に変換した方が演算量が減ります。
同じようにノーマルマップからサンプリングした法線を適用するため、
光源ベクトルを TangentSpace まで逆変換します。

頂点単位のライティングの代わりに、オブジェクトスペースへ変換した光源ベクトルを
タンジェントスペースへ変換する演算を追加します。変換 matrix (3×3)をかけるだけ。
結果を 0~1.0 に収まるよう _bx2 の逆変換で格納します。
固定小数演算なのでビットシフト等で最適化します。

vect3 tslightdir;
TangentMatrix.Transformation( tslightdir, oslightdir );
colorr= ((tslightdir.x+ FIXED16(1.0f))* 255)>>17;
colorg= ((tslightdir.y+ FIXED16(1.0f))* 255)>>17;
colorb= ((tslightdir.z+ FIXED16(1.0f))* 255)>>17;

シェーダーがあれば VertexShader でやっているところです。
またノーマルマップ生成ツールによって座標系が異なってることがあるので
軸の符号などは合わせます。

テクスチャステージでは読み込んだノーマルマップの値と頂点から出力した上記の
光源ベクトルを DotProduct します。

一段目はノーマルマップで光源演算。

SetTexture( 0, iTexture0 );
SetTextureStageState( 0, D3DMTSS_COLORARG1, D3DMTA_TEXTURE );
SetTextureStageState( 0, D3DMTSS_COLORARG2, D3DMTA_DIFFUSE );
SetTextureStageState( 0, D3DMTSS_RESULTARG, D3DMTA_CURRENT );
SetTextureStageState( 0, D3DMTSS_COLOROP, D3DMTOP_DOTPRODUCT3 );
SetTextureStageState( 0, D3DMTSS_ALPHAOP, D3DMTOP_DISABLE );
SetTextureStageState( 0, D3DMTSS_TEXCOORDINDEX, 0|D3DMTSS_TCI_PASSTHRU );

二段目はカラーマップの合成。

SetTexture( 1, iTexture1 );
SetTextureStageState( 1, D3DMTSS_COLORARG1, D3DMTA_TEXTURE );
SetTextureStageState( 1, D3DMTSS_COLORARG2, D3DMTA_CURRENT );
SetTextureStageState( 1, D3DMTSS_RESULTARG, D3DMTA_CURRENT );
SetTextureStageState( 1, D3DMTSS_COLOROP, D3DMTOP_MODULATE );
SetTextureStageState( 1, D3DMTSS_ALPHAOP, D3DMTOP_DISABLE );
SetTextureStageState( 1, D3DMTSS_TEXCOORDINDEX, 0|D3DMTSS_TCI_PASSTHRU );

まだ ALPHA があいています。
PowerVR だと適用可能なオペレーションの種類がもっと多いのでいろいろ出来るでしょう。

関連エントリ
HTC Touch Diamond で Direct3DMobile その(7) ノーマルマップを表示する
HTC Touch Diamond で Direct3DMobile その(6) 頂点性能続き
HTC Touch Diamond で Direct3DMobile その(5)
HTC Touch Diamond で Direct3DMobile その(4) 高速化
HTC Touch Diamond で Direct3DMobile その(3) 実際の頂点性能
HTC Touch Diamond で Direct3DMobile を使う。その (2)
HTC Touch Diamond で Direct3DMobile を使う。ハードウエアアクセラレータ