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

HTC Touch Diamond で Direct3DMobile その(5)

時間が無くてほとんど触っていませんが、、結果速くなりませんでした。
CPU 処理の方が有利と結論づけるにはまだ検証が足りないようです。

光源ありの場合は不要なものを大幅に省けるので相対的に速度が出ます。
逆に軽いデータでもピーク性能が全く伸びません。
少々触っただけでは何ともいえないので、時間があるときに詳しく測定して
原因を特定する必要がありそうです。

rhw の問題も回避手段が見つからないので、その(3) の結果を受け入れた方が
良いのかもしれません。

・ FIXED のテクスチャ頂点の問題

頂点形式を固定少数 D3DMFVF_TEXCOORDFIXED(0) にした場合に uv 値がおかしい、
テクスチャが出なくなるという問題がありました。

調べたところ FIXED 指定は無視され内部では常に float でアクセスしているようです。
FVF に何を指定しようが float 値を書き込むとうまくいきます。
やはりセットアップエンジンへは float で値が渡っているのでしょうか。
頂点も演算だけ FIXED で行い、バッファへは float で書き込んでみるのもありかも
しれません。

・ rhw の問題

D3DMFVF_XYZRHW_FLOAT や D3DMFVF_XYZRHW_FIXED の rhw に 1.0 以外の値を
書き込むと、ポリゴン自体の描画位置がずれてしまう問題があります。
こちらは特に触っていないので進展は無いです。

関連エントリ
HTC Touch Diamond で Direct3DMobile その(4) 高速化
HTC Touch Diamond で Direct3DMobile その(3) 実際の頂点性能
HTC Touch Diamond で Direct3DMobile を使う。その (2)
HTC Touch Diamond で Direct3DMobile を使う。ハードウエアアクセラレータ

HTC Touch Diamond で Direct3DMobile その(4) 高速化

速くなりました。光源入りで 4つ表示して 23.2fps。
その(2) の時は 1つで 18.5fps しか出ていなかったデータです。

Qualcomm MSM7201A Direct3DMobile
TouchDiamond (Qualcomm MSM7201A) Direct3DMobile

前回 調べた結果から

数値を見る限り 30fps でフレーム 10000頂点くらいがいいところでしょうか。
しかもデータ側の頂点数ではなく実演算の頂点数です。
ポリゴン数だとがんばって 3000~4000ポリゴン相当くらい。

さらに裏面や画面外など、描画してないけど計算してしまったポリゴンも含むので
実際に使うと予想以上に少なく感じるはずです。
頂点がかなり足を引っ張る形になります。
(API 呼び出しのオーバーヘッドとかフィル周りはまだ未調査です)
Dreamcast とか PSP クラス とかとても無理で、おそらく DS 未満。

光源を入れるとさらに 2.5 倍ほど重くなるようです。

いろいろ考えた結果、caps が HWTRANSFORMANDLIGHT を返してくるのはたぶん嘘では
ないかと。頂点はおそらく CPU 計算です。

試しに CPU だけで頂点の変換を行ってみたところ、同等以上の速度で描画することができました。
しかも FPU (VFP) が乗ってない CPU で float 演算しているのにこの速度。
caps が NATIVEFLOAT を返してくるので D3DM も CPU で float 演算している可能性が
あります。

固定少数でためしたら、float よりちょっとだけ速くなりました。
これが 最初にのせた 23.2fps の結果となります。

最適化とかほとんど考慮していないのに、それなりに速いのには理由があります。

 ・クリッピングしていない
 ・頂点バッファ単位で変換しているので共有頂点は一度しか計算していない
 ・光源計算は必要最小限で不要なものを省いている

よって実際に使える状態まで機能を入れるともっと負担が多くなるはずです。

●ここまでの結論

 Touch Diamond で D3DM を使う場合
 ・CPU で自前で頂点演算をやる
 ・CPU 内で完結するものは固定小数演算

自前で書けば、プログラマブルシェーダーのように必要最小限な処理に最適化できます。
ライティングなども実用的な速度で動作すると思います。

●問題点

実際に CPU で頂点演算をしてみると、いくつか問題が出てきました。

・rhw の挙動がおかしい

 自分でスクリーンスペースまで変換した場合、変換後の頂点の rhw の挙動が
 どうもおかしい。狙った通りの結果になりません。
 これがだめだとパースペクティブコレクションが効かないので少々致命的です。

・Fixed 形式の頂点だと Texture の uv が出ない

 負の uv 値でおかしなテクスチャの値になる。原因調査中

関連エントリ
HTC Touch Diamond で Direct3DMobile その(3) 実際の頂点性能
HTC Touch Diamond で Direct3DMobile を使う。その (2)
HTC Touch Diamond で Direct3DMobile を使う。ハードウエアアクセラレータ

HTC Touch Diamond で Direct3DMobile その(3) 実際の頂点性能

HTC Touch Diamond の 3D アクセラレータの速度テストです。
Qualcomm MSM7201A 内蔵 ATI core

時間がないので軽く調査、厳密なテストではないです。
頂点性能だけ見たかったので TriangleStrip で見えるか見えないかぎりぎりの
極小ポリゴン描画を並べたもの。ほとんど 1pixel 以下です。
単一バッファで一度だけ DrawPrimitive() しています。

●低負荷と思われるフォーマットでどれだけ頂点処理できるか

テクスチャ無し、ライティング無し、頂点カラーのみ

FVF = D3DMFVF_XYZ_FLOAT|D3DMFVF_DIFFUSE
struct { // 16byte
	float	x, y, z;
	DWORD	color;
};

頂点数  解像度  頂点形式     速度
 16384   VGA    xyz col     17.0fps   58msec
 32768   VGA    xyz col      9.6fps  103msec
 49152   VGA    xyz col      7.8fps  128msec
 65536   VGA    xyz col      5.7fps  176msec

おおざっぱに 16K 頂点が 40msec とすると、どんなにがんばっても最高 40万頂点/sec
程度しか出ない計算に。
ボトルネックが、頂点補充が追いつかないのか演算なのかは不明。

●ピーク速度に近づきたいために頂点カラーも無くしてみる

FVF = D3DMFVF_XYZ_FLOAT
struct { // 12byte
	float	x, y, z;
};

頂点数  解像度  頂点形式     速度
 16384   VGA    xyz         17.4fps   57msec
 32768   VGA    xyz          9.9fps  100msec
 49152   VGA    xyz          8.0fps  125msec
 65536   VGA    xyz          5.8fps  172msec

頂点カラーの影響は 16K 頂点あたり 1msec くらい。
65536頂点時に 38万頂点/sec

●解像度変更

頂点数  解像度  頂点形式     速度
 16384   VGA    xyz         17.4fps   57msec
 16384   HVGA   xyz         15.7fps   63msec
 16384   QVGA   xyz         22.5fps   44msec
 65536   VGA    xyz          5.8fps  172msec
 65536   HVGA   xyz          9.2fps  108msec
 65536   QVGA   xyz         11.2fps   88msec

フィルの影響も調べるために解像度も変えてテスト。
ポリゴン描画以外はクリアと Flip (COPY) だけなのに解像度の影響がかなりあります。
頂点数の増加によって解像度の影響をより強く受けているので、極小ポリゴンとは
いえそれなりにフィルを消費していることがわかります。

VGA = 639×480 (なぜ 639 なのかはこちら)
HVGA = 480×320 (iPhone/iPod touch や Android G1 がこれ)
QVGA = 320×240

●Memory Pool の違い

頂点数  解像度  頂点形式  Pool          速度
 65536   VGA    xyz       videomem      5.8fps 172msec
 65536   VGA    xyz       systemmem     5.8fps 172msec

caps ではどちらにも配置可能。特に差は無し。
速度が同じなのか、最初から同じメモリなのか、内部で Pool を無視して同一処理して
いるのかは不明。

●Index かどうか

もともと TriangleStrip だし頂点キャッシュが(もしあったとしても)有効なケース
ではないので、アクセスすべきメモリが増えた分だけ遅くなるはず。

頂点数  解像度  頂点形式  Index                   速度
 65536   VGA    xyz       DrawPrimitive           5.8fps 172msec
 65536   VGA    xyz       DrawIndexedPrimitive    5.8fps 173msec

結果、誤差の範囲でほとんど差は出ていません。

●浮動小数と固定少数の違い

頂点形式を FIXED にしても全く差がなかったです。
もともと caps が NATIVEFLOAT を返してくるし HW T&L 入ってるので Float だと
思いますが、どちらにせよ頂点バッファを作った時点で効率よい形式に
変換されていると考えられます。

● Texture つき

一番実用に近いと思われる頂点形式でテストです。
これが使い物になれば何とでもなる。

FVF=	D3DMFVF_XYZ_FLOAT|D3DMFVF_TEX1
	|D3DMFVF_TEXCOORDSIZE2(0)|D3DMFVF_TEXCOORDFLOAT(0)
struct _VTYPE {
	float	x, y, z;
	float	tu, tv;
};

頂点数  解像度  頂点形式       速度
 16384   VGA    xyz tex       16.8fps   59msec
 32768   VGA    xyz tex        9.6fps  104msec
 49152   VGA    xyz tex        7.6fps  131msec
 65536   VGA    xyz tex        5.3fps  190msec
  1000   QVGA   xyz tex       28.5fps   35msec
  1000   VGA    xyz tex       28.0fps   35msec
  5000   VGA    xyz tex       27.4fps   36msec
 10000   VGA    xyz tex       25.8fps   38msec
 20000   VGA    xyz tex       15.9fps   62msec

頂点の負担を見ることが目的なので、結果に大きな影響が出ないように Texture は
1pixel しか読み込んでいません。

ずっと気になっていたのが、必ず 29fps くらいで頭打ちになること。
設定はどれも D3DMPRESENT_INTERVAL_IMMEDIATE です。
これを D3DMPRESENT_INTERVAL_ONE にしてもなぜか同じ。

● Texture + Color つき

かなり使われることが多いフォーマットです。
これが使えればテクスチャを減らせます。

FVF=	D3DMFVF_XYZ_FLOAT|D3DMFVF_DIFFUSE|D3DMFVF_TEX1
	|D3DMFVF_TEXCOORDSIZE2(0)|D3DMFVF_TEXCOORDFLOAT(0)
struct _VTYPE {
	float	x, y, z;
	DWORD	color;
	float	tu, tv;
};

頂点数  解像度  頂点形式       速度
 16384   VGA    xyz col tex   16.6fps   60msec
 32768   VGA    xyz col tex    9.2fps  108msec
 49152   VGA    xyz col tex    6.9fps  145msec
 65536   VGA    xyz col tex    5.2fps  193msec
 10000   VGA    xyz col tex   25.8fps   38msec
 20000   VGA    xyz col tex   15.9fps   63msec

実用的な頂点処理能力としては、フレームあたり 1万ポリゴンくらいが限界といったところです。
ただし単一バッファで一回の描画でこの数値です。
実際は多数の DrawPrimitive() を呼び出すことになるので速度は落ちるはずです。

また前回やった通りライティングはかなり遅いのでテストしてません。
●光源処理あり 2008/01/07 3:02 追記

せっかくなので本当にどれだけ遅いのか光源もテストしてみました。
ハードウエア光源を使うだけで頂点が 2.5倍以上重くなっています。
これは純粋に演算量の増加によるものでしょう。

FVF = D3DMFVF_XYZ_FLOAT|D3DMFVF_NORMAL
struct { // 16byte
	float	x, y, z;
	float	nx, ny, nz;
};

◎平行光源 x1、スペキュラ無し
頂点数  解像度  頂点形式    光源                      速度
 16384   VGA    xyz normal  Dir x1  Diffuse           7.0fps  143msec
 32768   VGA    xyz normal  Dir x1  Diffuse           3.7fps  264msec
 49152   VGA    xyz normal  Dir x1  Diffuse           2.7fps  371msec
 65536   VGA    xyz normal  Dir x1  Diffuse           2.0fps  497msec

◎平行光源 x2、スペキュラ無し
頂点数  解像度  頂点形式    光源                      速度
 16384   VGA    xyz normal  Dir x2  Diffuse           6.9fps  144msec
 32768   VGA    xyz normal  Dir x2  Diffuse           3.7fps  275msec
 49152   VGA    xyz normal  Dir x2  Diffuse           2.6fps  380msec
 65536   VGA    xyz normal  Dir x2  Diffuse           1.9fps  512msec

◎平行光源 x1、スペキュラあり Power=10
頂点数  解像度  頂点形式    光源                      速度
 16384   VGA    xyz normal  Dir x1  Diffuse+Specular  6.1fps  165msec
 32768   VGA    xyz normal  Dir x1  Diffuse+Specular  3.2fps  310msec
 49152   VGA    xyz normal  Dir x1  Diffuse+Specular  2.3fps  440msec

◎平行光源 x2、スペキュラあり Power=10
頂点数  解像度  頂点形式    光源                      速度
 16384   VGA    xyz normal  Dir x2  Diffuse+Specular  6.0fps  165msec
 32768   VGA    xyz normal  Dir x2  Diffuse+Specular  3.2fps  311msec

●TriangleList の負荷 2008/01/07 9:30 追記

TriangleStrip で描画していた全く同じ頂点配列+ポリゴンを、Index で
TriangleList に展開したものです。
Index の数が (vertices-2)*3 に増えた分だけメモリアクセスが増えますが、
キャッシュがある一般的な GPU だと速度が落ちません。

頂点数  解像度  頂点形式 描画API      PrimitiveType   速度
 32768   VGA    xyz    DrawPrimitive  TriangleStrip  10.1fps   99msec
 32768   VGA    xyz    DrawIndexedPri TriangleStrip  10.0fps  100msec
 32768   VGA    xyz    DrawIndexedPri TriangleList    4.0fps  248msec

プログラムが間違っていなければ頂点キャッシュ無し確定。
おそらく演算が 3倍になってると思われます。

問題はむしろフィルの方なので、あとはピクセルがどれくらい出るかどうか。

IT Media QUALCOMM、MSM7201A上で動作するAndroidのデモを公開
上のページには PSP に近いくらいと書かれていますが、現状とてもそこまで
出せそうにないです。

関連エントリ
HTC Touch Diamond で Direct3DMobile を使う。その (2)
HTC Touch Diamond で Direct3DMobile を使う。ハードウエアアクセラレータ

HTC Touch Diamond で Direct3DMobile を使う。その (2)

前回は板を描画するだけで力尽きたので、もうちょっとだけテスト。
16bit 565 なのでマッハバンドが目立ちます。

Direct3D Mobile MiteKoKo
Direct3D Mobile MiteKoKo

401頂点、760ポリゴン、平行光源×1(Diffuseのみ)、
Texture 1枚、256x256xR5G6B5 (mip無し、バイリニアフィルタ)
1頂点 32byte (xyz normal texuv float)

TouchDiamond S21HT   VGA  639x480  ATI  d3dm_ati.dll      18.5  fps
EMONSTER lite S12HT  QVGA 320x240  REF  d3dmref.dll        0.25 fps
EM・ONE S01SH        WVGA 800x480  XSC  D3DMXSc50PB.dll    4.3  fps

Touch Diamond は光源なしだとテクスチャ付きでも 30fps 出てました。
LightEnable を TRUE にしただけで 18.5fps へ。
SpecularEnable ではあまり変わらないけどローポリの頂点単位だと見た目がきつい。

他の端末でも走らせてみましたが、解像度が違うのであんまり参考にならないかも。
Reference Driver は遅いです。

Touch Diamond の光源処理には少々問題があります。
World だけの回転でなぜか光源も一緒に動いてしまうこと。
法線用の Matrix の設定が間違っているのか少々バグっぽい挙動です。

Qualcomm MSM7201

上記ページによると 頂点性能 4M triangle/sec、フィルレート 133M pixel/sec。
1/30sec で frame 13万頂点。おそらくライティング無し、最小頂点形式のピーク値。

フィルは VGA (640×480) の場合全部転送と見なして 14画面分に相当します。
ただし GPU の処理能力なのかバス能力の上限なのかはわかりません。
おおざっぱに 読み出し 16bit texture + 16bit depth 、書き込み 16bit color
+ 16bit depth で 133MHz といったところでしょうか。

4M Triangle/sec というと、スペック上の数値だけなら Dreamcast クラスに見えます。
VGA 解像度や 16bit 565 フレームバッファも同じ。
でも数値だけなのでもちろん無理。

しかもバス帯域を効率よく使う PowerVR に比べるとフィルで不利だし、caps 一覧を
見る限り DXT 圧縮テクスチャがないのも PVR よりバスを圧迫しそう。

実際 D3DM 経由でどの程度パフォーマンス出せるかまだわからないですが、現状
オーバーヘッドもかなり多そうです。
CPU も FPU 無しだし、解像度も高いし、iPhone/iPod touch 比ではかなり不利だと
思われます。

関連エントリ
HTC Touch Diamond で Direct3DMobile を使う。ハードウエアアクセラレータ

HTC Touch Diamond で Direct3DMobile を使う。ハードウエアアクセラレータ

やっと HTC Touch Diamond で Direct3DMobile が動くようになりました。
ハードウエアアクセラレータがきいていて、一応 VGA のフルスクリーンで
28~29fps くらい出ています。
かなり苦労しました。

Direct3D Mobile

caps を見ると Touch Pro なども同じかもしれません。

●苦労話

とにかく Touch Diamond では Direct3DM が全く動かなくて驚きました。
昔作ったプログラムも全滅で、WindowsMobile6 SDK のサンプルもだめ。
プログラムは動作するものの全く描画されないという症状。

caps はそれらしい値が取れていて、しかもハードウエアアクセラレータが有効との
魅力的な値を返してきます。
実際に d3dm_ati.dll が読み込まれているところまでは確認できます。

それでも画面は変わらず Clear() で埋めたカラーすら画面には現れてこないという。
D3DMPRESENT_PARAMETERS の組み合わせをいくら変えてもだめ。
画面の回転方向を変えてもだめ。

API 呼び出しは矛盾する設定をするとエラーになるので、一応動作しているようにも
見えます。

ちなみに d3dmref.dll も無いのでリファレンスラスタライザも使えません。
何とか d3dm_ati.dll が動く条件を見つけるしかなさそうです。

とりあえず Present() が悪いのかレンダリングそのものが走っていないのかだけ確認
してみます。

BeginScene();
Clear();
EndScene();
Present();

GetBackBuffer();
CopyRect(); // BackBuffer → ImageSurface
ImageSurface->LockRect()
// 読み出し
ImageSurface->UnlockRect()

こんな感じで BackBuffer の値を読み出してみると、一応カラーが書き込まれている
ことがわかりました。
Present() が失敗してるだけでレンダリングそのものは動いています。
でも Present() はエラーを返さず、Device も Lost していません。

BackBuffer には書き込まれていることがわかったので、Lock して読み出して
自分で Window に描画すれば (力業だけど) 描画できるのではないかと思いつきました。

フレームバッファの値を直接読み出して CPU で DIB に変換。CompatibleBitmap に
描画してからウィンドウにコピー。
最終的には R5G6B5 サーフェースの値がそのまま DIB として利用できることが
わかったので、転送や変換を減らして下記の通りです。

  ~
iDevice->Present( NULL, NULL, NULL, NULL );

IDirect3DMobileSurface*	iBack= NULL;
iDevice->GetBackBuffer( 0, &iBack );
iDevice->CopyRects( iBack, NULL, 0, iSurface, NULL );
iBack->Release();

D3DMLOCKED_RECT	lock;
iSurface->LockRect( &lock, NULL, D3DMLOCK_READONLY );
SetDIBitsToDevice( hDC, 0, 0, Width, Height, 0, 0, 0, Height,
		lock.pBits, &BitmapHead, DIB_RGB_COLORS );
iSurface->UnlockRect();

一応これで VGA (640×480) フルスクリーンでの Direct3DM の描画に成功しました。
でもかなり遅いです。上の最適化した状態で目測 5fps 程度。

この方法は FullScreen でも Windowed どちらでも動作しますが、最終的には
Bitmap 化するためウィンドウの中に描画しています。
転送を減らすため、試しに QVGA 240×320 くらいにフレームバッファを縮小してみます。

FullScreen の場合デバイスの解像度と一致していないとハングアップするので
Windowed = TRUE に。QVGA だとこの方法でも 15fps くらいになりました。

ふとこの状態で Lock & Copy をやめてみると、DIB を通さなくてもちゃんと
描画されていて、しかも 30fps 近く出ていることを発見!
ハードウエアアクセラレータ効いています。

その後いろいろためした結果、なんと「640×480 のレンダリングだけ」失敗することが
わかりました。
例えば 1pixel 減らして 480 x 639 や 478×640 にすると描画できます。

FullScreen (Windowed = FALSE) の場合デバイスの解像度と一致していないと
エラーで落ちるので、WindowMode (Windowed = TRUE) が必須となります。

●結論

・解像度を 480×640 より小さくする (480×639 or 479×640 など)
・小さくするために必ず WindowMode にする

の条件さえ満たせば Touch Diamond でも Direct3D でポリゴン描画できます。

SDK のサンプルなど、多くのプログラムは GetSystemMetrics( SM_CXSCREEN )、
GetSystemMetrics( SM_CYSCREEN ) を使ってデバイスの解像度でレンダリング
しようとしています。これが原因でした。

わかってしまえば簡単なんだけど、、、途中何度挫折しかけたことか。
リファレンスラスタライザが使えていたらすぐあきらめていたかも。