2009/02/13
Direct2D (7) Tessellate の 2
昨日の Tessellate 結果を図示したものです。
FillGeometry() 相当の場合
ポリゴン化の状態をわかりやすくするために flatteningTolerance = 4 で Tessellate
しています。

DrawGeometry() 相当の場合
strokeWidth = 4.0 で描画した場合のポリゴン分割です。
こちらも見やすいように flatteningTolerance = 4 で分割しています。

デフォルトのままだとこれくらいの分割です。
水平方向の分割かつ Strip になっているのがわかります。

テストに使った DummySink の定義。
そのまま DrawGeometry() で path を描画すると、とがった角にトゲが生えたような
描画になることがあります。折れ線のつなぎ処理が入っているようです。

描画用に ID2D1StrokeStyle を作成しておくとトゲが無くなります。
関連エントリ
・Direct2D (6) Tessellate
・Direct2D (5) ID2D1Geometry を使う
・Direct2D (4) Direct2D の描画
・Direct2D (3) 互換性の検証と Vista で Direct2D
・Direct2D その(2) インターフェース
・Direct2D と Direct3D10.1 の下位互換
FillGeometry() 相当の場合
ポリゴン化の状態をわかりやすくするために flatteningTolerance = 4 で Tessellate
しています。

iFactory->CreateEllipseGeometry( D2D1::Ellipse( D2D1::Point2F( 0,0f, 0.0f ), 80.0f, 80.0f ), &iElli ); DummySink tsink; iElli->Tessellate( NULL, 4.0f, &tsink );
DrawGeometry() 相当の場合
strokeWidth = 4.0 で描画した場合のポリゴン分割です。
こちらも見やすいように flatteningTolerance = 4 で分割しています。

iFactory->CreatePathGeometry( &iPath ); ID2D1GeometrySink* isink; iPath->Open( &isink ); iElli->Widen( 10.0f, NULL, NULL, isink ); isink->Close(); DummySink tsink; iPath->Tessellate( NULL, 4.0f, &tsink );
デフォルトのままだとこれくらいの分割です。
水平方向の分割かつ Strip になっているのがわかります。

テストに使った DummySink の定義。
class DummySink : public ID2D1TessellationSink { private: static ID2D1PathGeometry* iPath; static ID2D1GeometrySink* iSink; public: DummySink() { } public: STDMETHOD_( void, AddTriangles )( const D2D1_TRIANGLE* triangles, UINT trianglecount ) { for( UINT i= 0 ; i< trianglecount ; i++, triangles++ ){ iSink->BeginFigure( triangles->point1, D2D1_FIGURE_BEGIN_FILLED ); iSink->AddLine( triangles->point2 ); iSink->AddLine( triangles->point3 ); iSink->EndFigure( D2D1_FIGURE_END_CLOSED ); } } STDMETHOD_(ULONG, AddRef )( THIS ) { return 0; } STDMETHOD_(ULONG, Release )( THIS ) { return 0; } STDMETHOD( QueryInterface )( THIS_ REFIID riid, void** obj ) { return E_UNEXPECTED; } STDMETHOD( Close )() { return S_OK; } static void Create( ID2D1Factory* factory ) { factory->CreatePathGeometry( &iPath ); iPath->Open( &iSink ); } static void ClosePath() { if( iSink ){ iSink->Close(); iSink= NULL; } } }; ID2D1PathGeometry* DummySink::iPath= NULL; ID2D1GeometrySink* DummySink::iSink= NULL;
そのまま DrawGeometry() で path を描画すると、とがった角にトゲが生えたような
描画になることがあります。折れ線のつなぎ処理が入っているようです。

描画用に ID2D1StrokeStyle を作成しておくとトゲが無くなります。
関連エントリ
・Direct2D (6) Tessellate
・Direct2D (5) ID2D1Geometry を使う
・Direct2D (4) Direct2D の描画
・Direct2D (3) 互換性の検証と Vista で Direct2D
・Direct2D その(2) インターフェース
・Direct2D と Direct3D10.1 の下位互換
2009/02/12
Direct2D (6) Tessellate
FillMesh() はまだ成功していません。
Tessellate() で座標を取ってみました。
まずはただの矩形から。
少々勘違いしていたのは、AddTriangles() はまとめて一度だけ呼ばれるのかと思ったら
1 Triangle 毎に何度も呼び出されること。
結果は次の通り。
頂点の並びが少々おかしい気がします。
それぞれ回転方向が逆になっているので、Strip を展開したような形でしょうか。
ID2D1RectangleGeometry ではなく Path で同様の形を作ってみます。
全く同じです。
パスの方向を逆にしても同じでした。
半径 10 の円の場合。
22個の Triangle に分割されています。ちなみに半径 30だと 30個。
円の中心に頂点がありません。水平方向にスライスされているので、やはり Strip に
展開されているのだと思われます。
分割数は Tessellate() 2番目のパラメータで指定出来ます。
Tessellate( NULL, ここ, &tsink );
省略時は D2D1_DEFAULT_FLATTENING_TOLERANCE が渡されており、これは 0.25f です。
値を大きくすると、5.0 くらいで菱形の 4角形になります。
0.0f を与えると 3862個に分割されました。
RenderTarget 作成時 D2D1_RENDER_TARGET_PROPERTIES dpiX/dpiY に 0 を与えると
デフォルトの 96dpi になります。
96dpi の時、長さは pixel 相当となり、dpi 値を増やすとピクセル密度が高くなります。
相対的に同じサイズの RenderTarget に描かれる図形は大きくなります。
dpi を考慮した実際に描画される大きさと、Tessellate() 2番目の数値によって
生成される Triangle の数が決められています。
関連エントリ
・Direct2D (5) ID2D1Geometry を使う
・Direct2D (4) Direct2D の描画
・Direct2D (3) 互換性の検証と Vista で Direct2D
・Direct2D その(2) インターフェース
・Direct2D と Direct3D10.1 の下位互換
Tessellate() で座標を取ってみました。
iFactory->CreateRectangleGeometry( D2D1::RectF( 0.0f, 0.0f, 10.0f, 10.0f ), &iRect ); DummySink tsink; iRect->Tessellate( NULL, &tsink );
まずはただの矩形から。
少々勘違いしていたのは、AddTriangles() はまとめて一度だけ呼ばれるのかと思ったら
1 Triangle 毎に何度も呼び出されること。
結果は次の通り。
t0= 10.000000 0.000000, 10.000000 10.000000, 0.000000 10.000000 t1= 0.000000 0.000000, 0.000000 10.000000, 10.000000 0.000000
頂点の並びが少々おかしい気がします。
それぞれ回転方向が逆になっているので、Strip を展開したような形でしょうか。
ID2D1RectangleGeometry ではなく Path で同様の形を作ってみます。
ID2D1GeometrySink* isink; iFactory->CreatePathGeometry( &iPath ); iPath->Open( &isink ); isink->BeginFigure( D2D1::Point2F( 0.0f, 0.0f ), D2D1_FIGURE_BEGIN_FILLED ); isink->AddLine( D2D1::Point2F( 20.0f, 0.0f ) ); isink->AddLine( D2D1::Point2F( 20.0f, 20.0f ) ); isink->AddLine( D2D1::Point2F( 0.0f, 20.0f ) ); isink->EndFigure( D2D1_FIGURE_END_CLOSED ); isink->Close(); iPath->Tessellate( NULL, &tsink );
全く同じです。
t0= 20.000000 0.000000, 20.000000 20.000000, 0.000000 20.000000 t1= 0.000000 0.000000, 0.000000 20.000000, 20.000000 0.000000
パスの方向を逆にしても同じでした。
isink->BeginFigure( D2D1::Point2F( 0.0f, 0.0f ), D2D1_FIGURE_BEGIN_FILLED ); isink->AddLine( D2D1::Point2F( 0.0f, 20.0f ) ); isink->AddLine( D2D1::Point2F( 20.0f, 20.0f ) ); isink->AddLine( D2D1::Point2F( 20.0f, 0.0f ) ); isink->EndFigure( D2D1_FIGURE_END_CLOSED ); t0= 20.000000 0.000000, 20.000000 20.000000, 0.000000 20.000000 t1= 0.000000 0.000000, 0.000000 20.000000, 20.000000 0.000000
半径 10 の円の場合。
iFactory->CreateEllipseGeometry( D2D1::Ellipse( D2D1::Point2F( 0,0f, 0.0f ), 10.0f, 10.0f ), &iElli ); iElli->Tessellate( NULL, &tsink );
22個の Triangle に分割されています。ちなみに半径 30だと 30個。
t0= -2.015625 9.796875, 0.000000 10.000000, 2.015625 9.796875 t1= 3.890625 9.218750, 2.015625 9.796875, -2.015625 9.796875 t2= -3.890625 9.218750, -2.015625 9.796875, 3.890625 9.218750 t3= 7.062500 7.062500, 3.890625 9.218750, -3.890625 9.218750 t4= -7.062500 7.062500, -3.890625 9.218750, 7.062500 7.062500 t5= 9.218750 3.890625, 7.062500 7.062500, -7.062500 7.062500 t6= -9.218750 3.890625, -7.062500 7.062500, 9.218750 3.890625 t7= 9.796875 2.015625, 9.218750 3.890625, -9.218750 3.890625 t8= -9.796875 2.015625, -9.218750 3.890625, 9.796875 2.015625 t9= 10.000000 0.000000, 9.796875 2.015625, -9.796875 2.015625 t10= -10.000000 0.000000, -9.796875 2.015625, 10.000000 0.000000 t11= 9.796875 -2.015625, 10.000000 0.000000, -10.000000 0.000000 t12= -9.796875 -2.015625, -10.000000 0.000000, 9.796875 -2.015625 t13= 9.218750 -3.890625, 9.796875 -2.015625, -9.796875 -2.015625 t14= -9.218750 -3.890625, -9.796875 -2.015625, 9.218750 -3.890625 t15= 7.062500 -7.062500, 9.218750 -3.890625, -9.218750 -3.890625 t16= -7.062500 -7.062500, -9.218750 -3.890625, 7.062500 -7.062500 t17= 3.890625 -9.218750, 7.062500 -7.062500, -7.062500 -7.062500 t18= -3.890625 -9.218750, -7.062500 -7.062500, 3.890625 -9.218750 t19= 2.015625 -9.796875, 3.890625 -9.218750, -3.890625 -9.218750 t20= -2.015625 -9.796875, -3.890625 -9.218750, 2.015625 -9.796875 t21= 0.000000 -10.000000, -2.015625 -9.796875, 2.015625 -9.796875
円の中心に頂点がありません。水平方向にスライスされているので、やはり Strip に
展開されているのだと思われます。
分割数は Tessellate() 2番目のパラメータで指定出来ます。
Tessellate( NULL, ここ, &tsink );
省略時は D2D1_DEFAULT_FLATTENING_TOLERANCE が渡されており、これは 0.25f です。
値を大きくすると、5.0 くらいで菱形の 4角形になります。
0.0f を与えると 3862個に分割されました。
# 5.0 t0= -10.000000 0.000000, 0.000000 10.000000, 10.000000 0.000000 t1= 0.000000 -10.000000, -10.000000 0.000000, 10.000000 0.000000
RenderTarget 作成時 D2D1_RENDER_TARGET_PROPERTIES dpiX/dpiY に 0 を与えると
デフォルトの 96dpi になります。
96dpi の時、長さは pixel 相当となり、dpi 値を増やすとピクセル密度が高くなります。
相対的に同じサイズの RenderTarget に描かれる図形は大きくなります。
dpi を考慮した実際に描画される大きさと、Tessellate() 2番目の数値によって
生成される Triangle の数が決められています。
関連エントリ
・Direct2D (5) ID2D1Geometry を使う
・Direct2D (4) Direct2D の描画
・Direct2D (3) 互換性の検証と Vista で Direct2D
・Direct2D その(2) インターフェース
・Direct2D と Direct3D10.1 の下位互換
2009/02/08
Direct2D (5) ID2D1Geometry を使う
GPU の活用によりラスタライズはたいしたウエイトを占めておらず、CPU の仕事は
与えるデータの構築だけとなりました。それゆえ Direct2D はただの描画命令の
集まりにはなっていません。
ベクター描画の途中に介入し、ベクトルの情報のままデータを扱うことが可能です。
Direct2D が単なる GDI の置き換えではなく、可能性を秘めているのはこの Geometry
ではないかと思っています。
実際に ID2D1Geometry がどのようなものか興味あるので、機能を 1つ 1つ追いかけて
みました。
● Path の作成
Path の作成は下記の通り。
ID2D1GeometrySink::Close() (ID2D1SimplifiedGeometrySink::Close()) は
SVG 等の Z コマンド相当かと思っていたら EndFigure( D2D1_FIGURE_END_CLOSED )
の方でした。
ID2D1GeometrySink::SetFillMode() では塗りつぶしのルールを決定します。
SVG 等の vector graphics にある evenodd / nonzero に相当します。
・D2D1_FILL_MODE_ALTERNATE
"evenodd" 相当。外からのレイが交差した回数で決定します。
交差回数が偶数なら外、奇数は中。パスの回転方向は影響しません。
・D2D1_FILL_MODE_WINDING
"nonzero" 相当。外からのレイが交差するとき、交わった線の方向を考慮します。
たとえば閉じているパスが仮に右回りなら +1、左回りなら -1、結果が 0 なら外。
つまりパスの回転方向を見ており、逆回転はくり抜き。
● Sink
Sink は値の追加、データをためることだけが出来るバッファです。
Add 系命令のみで Get はありません。
ID2D1Geometry では各オペレーションに対して受け皿である Sink を渡します。
最初にただの box を作ってみます。
この box を元に、線を太らせる処理を行います。
もともとは描画時に太い幅 (strokeWidth) の線で描画するための変換ですが、
描画前に Path として受け取ることが出来るわけです。
実際に描画したのがこちら。

↑左から順に
・元の Box
・元の Box を幅 10 の線で描画したもの
・幅 10 の描画を Path で受け取ったもの
・幅 10 で Path 化したものをさらに 幅 4 の線で描画したもの
RenderTarget には直接描画可能な DrawRectangle() 命令があります。
Direct2D では内部的には全く同じように
(1) CreateRectangleGeometry() 等でプリミティブを作成
(2) Widen() など与えたオプションによって必要な変換を行う
(3) Tessellate() で ID2D1Mesh 化
(4) 最終的にすべて ID2D1RenderTarget::FillMesh()
という手順で描画しているだけかもしれません。この場合一番低レベルな描画は
FillMesh() になります。
ただし現在 FillMesh() での直接描画が成功しておらず、これらは予想の範囲を
超えておりません。
もし予想が合っているのなら、Geometry を扱うことでより柔軟なデータ管理ができます。
たとえば比較的 Mesh に近い状態のままキャッシュすることで、高速化や再利用が
可能となるでしょう。毎回 stroke を指定して Draw するよりも Geometry か Mesh
化しておいた方が高速だと思います。
●変換形状の読み出し
Geometry の中身は隠蔽されており、パスの座標値などデータを直接さわることが
できなくなっています。
ところが SDK には、テセレートされたアウトラインフォントの形状を取り出して立体化し、
3D ポリゴンとして描画するサンプルプログラム Interactive3dTextSample があります。
その仕組みはこうです。
(1) Sink 互換のインターフェースを自分で定義しておく
(2) Geometry の Tessellate() 等に渡して変換結果を受け取る
たとえば ID2D1Geometry::Tessellate() であれば、変換後の結果を格納するために
内部で ID2D1TessellationSink::AddTriangles() を呼び出しています。
互換インターフェースで AddTriangles() を定義しておけばトラップ可能となるわけです。
このように、Tessellate() など Geometry で変換した座標値をアプリケーションで
使うことができます。
関連エントリ
・Direct2D (4) Direct2D の描画
・Direct2D (3) 互換性の検証と Vista で Direct2D
・Direct2D その(2) インターフェース
・Direct2D と Direct3D10.1 の下位互換
与えるデータの構築だけとなりました。それゆえ Direct2D はただの描画命令の
集まりにはなっていません。
ベクター描画の途中に介入し、ベクトルの情報のままデータを扱うことが可能です。
Direct2D が単なる GDI の置き換えではなく、可能性を秘めているのはこの Geometry
ではないかと思っています。
実際に ID2D1Geometry がどのようなものか興味あるので、機能を 1つ 1つ追いかけて
みました。
● Path の作成
Path の作成は下記の通り。
ID2D1Factory* iFactory; ID2D1PathGeometry* iPath; iFactory->CreatePathGeometry( &iPath ); ID2D1GeometrySink* isink; iPath->Open( &isink ); isink->SetFillMode( D2D1_FILL_MODE_WINDING ); isink->BeginFigure( startpos, D2D1_FIGURE_BEGIN_FILLED ); // = SVG M isink->AddLine( pos1 ); // = SVG L isink->AddBezier( D2D1::BezierSegment( c2, c3, c4 ) ); // = SVG C ... isink->EndFigure( D2D1_FIGURE_END_CLOSED ); // = SVG Z isink->Close();
ID2D1GeometrySink::Close() (ID2D1SimplifiedGeometrySink::Close()) は
SVG 等の Z コマンド相当かと思っていたら EndFigure( D2D1_FIGURE_END_CLOSED )
の方でした。
D2D1_FIGURE_END_OPEN そのまま D2D1_FIGURE_END_CLOSED BeginFigure() の位置に直線で接続(閉じたパスにする)
ID2D1GeometrySink::SetFillMode() では塗りつぶしのルールを決定します。
SVG 等の vector graphics にある evenodd / nonzero に相当します。
・D2D1_FILL_MODE_ALTERNATE
"evenodd" 相当。外からのレイが交差した回数で決定します。
交差回数が偶数なら外、奇数は中。パスの回転方向は影響しません。
・D2D1_FILL_MODE_WINDING
"nonzero" 相当。外からのレイが交差するとき、交わった線の方向を考慮します。
たとえば閉じているパスが仮に右回りなら +1、左回りなら -1、結果が 0 なら外。
つまりパスの回転方向を見ており、逆回転はくり抜き。
● Sink
Sink は値の追加、データをためることだけが出来るバッファです。
Add 系命令のみで Get はありません。
ID2D1Geometry では各オペレーションに対して受け皿である Sink を渡します。
最初にただの box を作ってみます。
ID2D1RectangleGeometry* iRect; iFactory->CreateRectangleGeometry( D2D1::RectF( 0.0f, 0.0f, 60.0f, 50.0f ), &iRect );
この box を元に、線を太らせる処理を行います。
もともとは描画時に太い幅 (strokeWidth) の線で描画するための変換ですが、
描画前に Path として受け取ることが出来るわけです。
// 変換結果を格納する ID2D1PathGeometry を作る ID2D1PathGeometry* iPath2; iFactory->CreatePathGeometry( &iPath2 ); // ID2D1PathGeometry の sink に変換結果を受け取る ID2D1GeometrySink* isink; iPath2->Open( &isink ); // iRect の変換結果を isink へ iRect->Widen( 10.0f, NULL, NULL, isink ); // strokeWidth= 10.0f isink->Close();
実際に描画したのがこちら。

↑左から順に
・元の Box
・元の Box を幅 10 の線で描画したもの
・幅 10 の描画を Path で受け取ったもの
・幅 10 で Path 化したものをさらに 幅 4 の線で描画したもの
// 描画コード iRenderTarget->SetTransform( D2D1::Matrix3x2F::Translation( 20.5f, 20.5f ) ); iRenderTarget->DrawGeometry( iRect, iBrush0 ); iRenderTarget->SetTransform( D2D1::Matrix3x2F::Translation( 120.5f, 20.5f ) ); iRenderTarget->DrawGeometry( iRect, iBrush0, 10.0f ); iRenderTarget->SetTransform( D2D1::Matrix3x2F::Translation( 220.5f, 20.5f ) ); iRenderTarget->DrawGeometry( iPath2, iBrush0 ); iRenderTarget->SetTransform( D2D1::Matrix3x2F::Translation( 320.5f, 20.5f ) ); iRenderTarget->DrawGeometry( iPath2, iBrush0, 4.0f );
RenderTarget には直接描画可能な DrawRectangle() 命令があります。
Direct2D では内部的には全く同じように
(1) CreateRectangleGeometry() 等でプリミティブを作成
(2) Widen() など与えたオプションによって必要な変換を行う
(3) Tessellate() で ID2D1Mesh 化
(4) 最終的にすべて ID2D1RenderTarget::FillMesh()
という手順で描画しているだけかもしれません。この場合一番低レベルな描画は
FillMesh() になります。
ただし現在 FillMesh() での直接描画が成功しておらず、これらは予想の範囲を
超えておりません。
もし予想が合っているのなら、Geometry を扱うことでより柔軟なデータ管理ができます。
たとえば比較的 Mesh に近い状態のままキャッシュすることで、高速化や再利用が
可能となるでしょう。毎回 stroke を指定して Draw するよりも Geometry か Mesh
化しておいた方が高速だと思います。
●変換形状の読み出し
Geometry の中身は隠蔽されており、パスの座標値などデータを直接さわることが
できなくなっています。
ところが SDK には、テセレートされたアウトラインフォントの形状を取り出して立体化し、
3D ポリゴンとして描画するサンプルプログラム Interactive3dTextSample があります。
その仕組みはこうです。
(1) Sink 互換のインターフェースを自分で定義しておく
(2) Geometry の Tessellate() 等に渡して変換結果を受け取る
たとえば ID2D1Geometry::Tessellate() であれば、変換後の結果を格納するために
内部で ID2D1TessellationSink::AddTriangles() を呼び出しています。
互換インターフェースで AddTriangles() を定義しておけばトラップ可能となるわけです。
このように、Tessellate() など Geometry で変換した座標値をアプリケーションで
使うことができます。
関連エントリ
・Direct2D (4) Direct2D の描画
・Direct2D (3) 互換性の検証と Vista で Direct2D
・Direct2D その(2) インターフェース
・Direct2D と Direct3D10.1 の下位互換
2009/02/08
DirectX 一覧 や GPU 年表の更新と ATI Imageon
「 Hyperでんち 」 の古くなっていたいくつかの項目を更新しました。
・DirectX 一覧
・GPU 年表
DirectX 一覧には Direct3D11 を追加 (リリース前なので未完)
GPU 年表は Mobile の項目を分離。
表を見てわかるとおり Mobile はちょうど今が固定機能パイプラインで DirectX7 世代。
その次は Unitifed Shader が当たり前で、一気に Direct3D10/ShaderModel4 世代と
なる可能性があります。
PowerVR SGX はすでに Unified Shader ベースであり、Intel US15W の GMA500 や
OMAP3 をはじめいくつかのデバイスで使われています。
Qualcomm の MSM に搭載されていた ATI Imageon も、新たに Xbox 360 同様の
Unified Shader Architecture を元に開発が行われていたようです。
・AMD Licenses 3D Graphics Core Technology to QUALCOMM, Delivering The Ultimate Visual Experience? to Tomorrow’s Phones
GeometryShader が存在するかどうかわかりませんが Shader ベースであることは確かです。
PowerVR SGX 同様、Vertex/ Pixel の演算ユニットを共有できること、
Graphics 以外への応用が容易なこと、設計時に演算能力をスケーラブルに変更できる
ことがメリットであると考えられます。
・Wikipedia Imageon
上記 wikipedia のページには Z460 という新しい Imageon core の名前が載っています。
直接 AMD の pdf 資料へのリンクもあります。登場は 2009 年以降とのこと。
これらのデータより、HTC Diamond 等に使われている現行 MSM7201A の 3D core は
ATI Imageon 2380 シリーズをベースにしたものだと考えられます。
・2006/1/30 ImageonR 2380 および ImageonR 2388 で驚くべきゲームおよびマルチメディア体験を可能にし、ハンドヘルド 3D グラフィックスの水準を引き上げる ATI
・AMD Imageon 2388/2380
公式ページの資料が参考になります。
Direct3DMobile では使えないものの CubeMap など一通り機能がそろっているようです。
D3D8 相当のスキニング用固定 Matrix Palette もありますが、残念ながら D3DM 側に
対応する機能がありません。
頂点演算は float で行われており、やはり NATIVEFLAOT で正解でした。
違いは VRAM のみで、2388 が内蔵 8MB、2380 が外付けで 16MB 以上に対応とのこと。
関連エントリ
・Intel GMA500 のスペックについて考える。続き (2)
・Intel GMA500 の機能と性能と Aero
・Qualcomm と 3D
・HTC Touch Diamond で Direct3DMobile その(11) 問題まとめその他
・DirectX 一覧
・GPU 年表
DirectX 一覧には Direct3D11 を追加 (リリース前なので未完)
GPU 年表は Mobile の項目を分離。
表を見てわかるとおり Mobile はちょうど今が固定機能パイプラインで DirectX7 世代。
その次は Unitifed Shader が当たり前で、一気に Direct3D10/ShaderModel4 世代と
なる可能性があります。
PowerVR SGX はすでに Unified Shader ベースであり、Intel US15W の GMA500 や
OMAP3 をはじめいくつかのデバイスで使われています。
Qualcomm の MSM に搭載されていた ATI Imageon も、新たに Xbox 360 同様の
Unified Shader Architecture を元に開発が行われていたようです。
・AMD Licenses 3D Graphics Core Technology to QUALCOMM, Delivering The Ultimate Visual Experience? to Tomorrow’s Phones
GeometryShader が存在するかどうかわかりませんが Shader ベースであることは確かです。
PowerVR SGX 同様、Vertex/ Pixel の演算ユニットを共有できること、
Graphics 以外への応用が容易なこと、設計時に演算能力をスケーラブルに変更できる
ことがメリットであると考えられます。
・Wikipedia Imageon
上記 wikipedia のページには Z460 という新しい Imageon core の名前が載っています。
直接 AMD の pdf 資料へのリンクもあります。登場は 2009 年以降とのこと。
これらのデータより、HTC Diamond 等に使われている現行 MSM7201A の 3D core は
ATI Imageon 2380 シリーズをベースにしたものだと考えられます。
・2006/1/30 ImageonR 2380 および ImageonR 2388 で驚くべきゲームおよびマルチメディア体験を可能にし、ハンドヘルド 3D グラフィックスの水準を引き上げる ATI
・AMD Imageon 2388/2380
公式ページの資料が参考になります。
Direct3DMobile では使えないものの CubeMap など一通り機能がそろっているようです。
D3D8 相当のスキニング用固定 Matrix Palette もありますが、残念ながら D3DM 側に
対応する機能がありません。
頂点演算は float で行われており、やはり NATIVEFLAOT で正解でした。
違いは VRAM のみで、2388 が内蔵 8MB、2380 が外付けで 16MB 以上に対応とのこと。
関連エントリ
・Intel GMA500 のスペックについて考える。続き (2)
・Intel GMA500 の機能と性能と Aero
・Qualcomm と 3D
・HTC Touch Diamond で Direct3DMobile その(11) 問題まとめその他
2009/02/05
Direct2D (4) Direct2D の描画
●描画
Direct2D の描画は下記の 4通りあります。
・線描画
・塗りつぶし
・イメージ描画
・文字
ID2D1RenderTarget に対して適用できるものです。
それぞれグループ分けと、グループごとに指定出来る共通プロパティをまとめます。
●形状
形状の操作は Geometry で行います。
その場合も描画同様のプリミティブが使用できます。
多くの操作では同時に 3x2 Matrix (D2D1_MATRIX_3X2_F) を与えることが可能で、
形や座標判定用の命令も用意されています。
・ID2D1EllipseGeometry
・ID2D1PathGeometry
・ID2D1RectangleGeometry
・ID2D1RoundedRectangleGeometry
・ID2D1TransformedGeometry
CombineWithGeometry
複数の Geometry 同士の合成や演算を行います。
Tessellate
テセレートし、トライアングル化した状態にアクセスできるようにします。
Widen
線として描画する場合に、線を太らせた形状を取り出します。
●Mesh
ID2D1Mesh は直接描画データとしてポリゴン (Triangle) を与える場合に使用します。
非常にデバイスに近い低レベルな状態でデータをもてるものと思われます。
おそらく Geometry → Tessellate も Mesh 相当への変換です。
●DirectWrite
DirectWrite はフォント扱うモジュールとして完全に独立しているようです。
描画対象として Direct2D に拘る必要はなく Direct3D など何でも良いとのこと。
Direct3D11 との組み合わせもおそらく出来るでしょう。
当初は Direct2D のデータに変換して出力しているのかと思いましたが、独自の
レンダラを持っているようです。よく考えると ClearType などフォントに依存する
部分が大きいので当然かも。
フォントを扱うためにはデータとして形状を読み込むだけでなく、同時にレイアウト
も必要となります。このあたりのインターフェースは次の通り。
IDWriteFormat → IDWriteLeyout
IDWriteTextFormat → IDWriteTextLayout
Direct2D のテキスト描画も上記 2つの Interface に対応しています。
また文字単位の形状を直接描画することも可能で、それが GlyphRun 系の命令と
なっているようです。
今回はあまりきちんと試しておらず、メモ程度の内容となっています。
間違いなどあったら訂正していきます。
関連エントリ
・Direct2D (3) 互換性の検証と Vista で Direct2D
・Direct2D その(2) インターフェース
・Direct2D と Direct3D10.1 の下位互換
Direct2D の描画は下記の 4通りあります。
・線描画
・塗りつぶし
・イメージ描画
・文字
ID2D1RenderTarget に対して適用できるものです。
それぞれグループ分けと、グループごとに指定出来る共通プロパティをまとめます。
◎線描画 ・DrawEllipse (楕円) ・DrawGeometry (パス) ・DrawLine (直線) ・DrawRectangle (四角) ・DrawRoundedRectangle (角が丸い四角形) ID2D1Brush 色や模様 Stroke 線の太さ (strokeWidth) ID2D1StrokeStyle 線のスタイル (端の形状、丸めたりとんがったり。線の形状、点線やダッシュ点線など) ◎塗りつぶし ・FillEllipse ・FillGeometry ・FillMesh (ID2D1Mesh の描画) ・FillOpacityMask (bitmap でマスク付き塗りつぶし) ・FillRectangle ・FillRoundedRectangle ID2D1Brush 色や模様 ◎イメージ描画 ・DrawBitmap ・(FillOpacityMask) ◎文字 ・DrawGlyphRun (IDWriteFontFace) ・DrawText (IDTextFormatIDWriteTextFormat) 2009/02/06 修正 ・DrawTextLayout (IDWriteLeyoutIDWriteTextLayout) 2009/02/06 修正 ID2D1Brush 色や模様
●形状
形状の操作は Geometry で行います。
その場合も描画同様のプリミティブが使用できます。
多くの操作では同時に 3x2 Matrix (D2D1_MATRIX_3X2_F) を与えることが可能で、
形や座標判定用の命令も用意されています。
・ID2D1EllipseGeometry
・ID2D1PathGeometry
・ID2D1RectangleGeometry
・ID2D1RoundedRectangleGeometry
・ID2D1TransformedGeometry
CombineWithGeometry
複数の Geometry 同士の合成や演算を行います。
Tessellate
テセレートし、トライアングル化した状態にアクセスできるようにします。
Widen
線として描画する場合に、線を太らせた形状を取り出します。
●Mesh
ID2D1Mesh は直接描画データとしてポリゴン (Triangle) を与える場合に使用します。
非常にデバイスに近い低レベルな状態でデータをもてるものと思われます。
おそらく Geometry → Tessellate も Mesh 相当への変換です。
●DirectWrite
DirectWrite はフォント扱うモジュールとして完全に独立しているようです。
描画対象として Direct2D に拘る必要はなく Direct3D など何でも良いとのこと。
Direct3D11 との組み合わせもおそらく出来るでしょう。
当初は Direct2D のデータに変換して出力しているのかと思いましたが、独自の
レンダラを持っているようです。よく考えると ClearType などフォントに依存する
部分が大きいので当然かも。
フォントを扱うためにはデータとして形状を読み込むだけでなく、同時にレイアウト
も必要となります。このあたりのインターフェースは次の通り。
IDWriteTextFormat → IDWriteTextLayout
Direct2D のテキスト描画も上記 2つの Interface に対応しています。
また文字単位の形状を直接描画することも可能で、それが GlyphRun 系の命令と
なっているようです。
今回はあまりきちんと試しておらず、メモ程度の内容となっています。
間違いなどあったら訂正していきます。
関連エントリ
・Direct2D (3) 互換性の検証と Vista で Direct2D
・Direct2D その(2) インターフェース
・Direct2D と Direct3D10.1 の下位互換
2009/02/04
Direct2D (3) 互換性の検証と Vista で Direct2D
こちらで書いたように、Windows7 では Direct3D11 と同じく
Direct3D10.1 でも下位の GPU が新たにサポートされることになりました。
実際にデバイスを作成して試してみました。
今度は Direct2D ではなく、直接 Direct3D10.1 ( D3D10CreateDevice1() ) を
使用しています。
すべて成功しました。
これは、今までの Windows Vista + Direct3D10.0 / Direct3D10.1 では
出来なかったことなのです。
まず Windows SDK for Windows 7 BETA を install しなければ、
D3D10_FEATURE_LEVEL_9_1 ~ D3D10_FEATURE_LEVEL_9_3 のシンボルが
定義されていないということ。
Vista 以前で使える現在の DirectX SDK ではコンパイル出来ませんでした。
DirectX SDK Nov2008 の help では、ヘッダファイルにシンボルが無いのに次の
ように書かれていたりします。
この Windows7 用の FEATURE テストプログラムを WindowsVista 上で走らせて
みたところ、全く同じようにデバイスの生成が成功してしまいました。
考えられるのは Windows Vista でも Direct3D SDK の Direct3D11 beta ランタイム
を導入した時点で使えるようになっていたのではないかということ。
Direct3D11 では実際に D3D9_1~3 の下位の FeatureLevel に対応しています。
Direct3D10.1 で同じように利用できてもおかしくないのかもしれません。
過去の DirectX はすべて互換性を保ちながら移行するのが当たり前でした。
実際に Direct3D 9 は Direct3D 8 のハードウエアでも動作します。
デバイスは作れますし API も呼べますしシェーダーモデル 1 を扱うことが出来ます。
Direct3D9 の特徴であるシェーダーモデル 2~3 は利用できませんが、それは
Direct3D10.1 で Level9 を扱っても全く同じこと。
さらに前、たとえば DirectX7 までは毎年メジャーナンバーがアップデートされる
ことになっていました。わずか 1年で GPU が使えなくなっていたら、とても
ついて行くのが大変ですよね。
・DirectX/GPU 年表
・DirectX list
互換性を完全に切り捨てたのは Direct3D9 → Direct3D10 のタイミングだけなのです。
ドライバモデルが変わったり OS と融合されたりと、内部的に困難な理由が
いろいろあったのではないかと考えられます。
だから今回 Windows7 と同じタイミングで、Windows7 だけでなく Vista でも
同等の機能がサポートされるのは画期的なことかもしれません。
でも古くから DirectX を触ってるものからすれば画期的でも何でもなくて、
互換性の切り捨てを撤回して、やっぱり以前と同じように使えるようにしました、
といってるだけに見えるのです。
● Windows7 SDK の導入
Windows7 SDK があれば、Vista でも Direct3D10.1 で Direct3D9 GPU 向けの
プログラムを作成できることがわかりました。
DirectX SDK の更新と思って Windows SDK for Windows 7 BETA を早めに導入して
おくのもありかもしれません。
あらかじめ DirectX SDK November 2008 をインストールしておく必要があります。
VisualStudio2008 を起動する前に、スタートメニューから
Visual Studio Registration → Windows SDK Configuration Tool
を起動して SDK を切り替えておきます。
include パスの順番には注意が必要です。
Tools → Options → Projects and Solutions → VC++ Directories
Win32 / Include files
$(DXSDK_DIR)\include よりも上に $(WindowsSdkDir)\include が来るようにします。
DirectX SDK の install で直接 C:\Program Files ~とパスが書き込まれている
ことがあるので、その行は削除して $(DXSDK_DIR)include に置き換えておくことを
お勧めします。
lib も同じようにします。
● Vista で Direct2D が動く
Windows7 SDK beta があれば Direct2D のプログラムを作ることが出来ます。
実際に走らせるには Windows7 beta をインストールした PC が必要です。
Direct2D は結局 Direct3D10.1 を呼び出しているだけのはず。
Direct3D10.1 で下位 GPU もなぜか動くことがわかったので、もしやと思って
Windows7 beta から d2d1.dll だけ vista に持ってきたら拍子抜けするほどあっさり
動作しました。
とりあえず build したプログラムと同じ場所に d2d1.dll と DWrite.dll だけ置いておけば
Vsita でも Direct2D のプログラムを作って走らせることが出来るようです。
関連エントリ
・Direct2D その(2) インターフェース
・Direct2D と Direct3D10.1 の下位互換
Direct3D10.1 でも下位の GPU が新たにサポートされることになりました。
実際にデバイスを作成して試してみました。
今度は Direct2D ではなく、直接 Direct3D10.1 ( D3D10CreateDevice1() ) を
使用しています。
Direct3D10.1 D3D10_FEATURE_LEVEL_10_0 D3D10_FEATURE_LEVEL_10_1 D3D10_FEATURE_LEVEL_9_1 D3D10_FEATURE_LEVEL_9_2 D3D10_FEATURE_LEVEL_9_3
すべて成功しました。
これは、今までの Windows Vista + Direct3D10.0 / Direct3D10.1 では
出来なかったことなのです。
まず Windows SDK for Windows 7 BETA を install しなければ、
D3D10_FEATURE_LEVEL_9_1 ~ D3D10_FEATURE_LEVEL_9_3 のシンボルが
定義されていないということ。
Vista 以前で使える現在の DirectX SDK ではコンパイル出来ませんでした。
DirectX SDK Nov2008 の help では、ヘッダファイルにシンボルが無いのに次の
ように書かれていたりします。
D3D10_FEATURE_LEVEL_9_1 This value is in the header, but this feature is not yet implemented. D3D10_FEATURE_LEVEL_9_2 This value is in the header, but this feature is not yet implemented. D3D10_FEATURE_LEVEL_9_3 This value is in the header, but this feature is not yet implemented.
この Windows7 用の FEATURE テストプログラムを WindowsVista 上で走らせて
みたところ、全く同じようにデバイスの生成が成功してしまいました。
考えられるのは Windows Vista でも Direct3D SDK の Direct3D11 beta ランタイム
を導入した時点で使えるようになっていたのではないかということ。
Direct3D11 では実際に D3D9_1~3 の下位の FeatureLevel に対応しています。
Direct3D10.1 で同じように利用できてもおかしくないのかもしれません。
過去の DirectX はすべて互換性を保ちながら移行するのが当たり前でした。
実際に Direct3D 9 は Direct3D 8 のハードウエアでも動作します。
デバイスは作れますし API も呼べますしシェーダーモデル 1 を扱うことが出来ます。
Direct3D9 の特徴であるシェーダーモデル 2~3 は利用できませんが、それは
Direct3D10.1 で Level9 を扱っても全く同じこと。
さらに前、たとえば DirectX7 までは毎年メジャーナンバーがアップデートされる
ことになっていました。わずか 1年で GPU が使えなくなっていたら、とても
ついて行くのが大変ですよね。
・DirectX/GPU 年表
・DirectX list
互換性を完全に切り捨てたのは Direct3D9 → Direct3D10 のタイミングだけなのです。
ドライバモデルが変わったり OS と融合されたりと、内部的に困難な理由が
いろいろあったのではないかと考えられます。
だから今回 Windows7 と同じタイミングで、Windows7 だけでなく Vista でも
同等の機能がサポートされるのは画期的なことかもしれません。
でも古くから DirectX を触ってるものからすれば画期的でも何でもなくて、
互換性の切り捨てを撤回して、やっぱり以前と同じように使えるようにしました、
といってるだけに見えるのです。
● Windows7 SDK の導入
Windows7 SDK があれば、Vista でも Direct3D10.1 で Direct3D9 GPU 向けの
プログラムを作成できることがわかりました。
DirectX SDK の更新と思って Windows SDK for Windows 7 BETA を早めに導入して
おくのもありかもしれません。
あらかじめ DirectX SDK November 2008 をインストールしておく必要があります。
VisualStudio2008 を起動する前に、スタートメニューから
Visual Studio Registration → Windows SDK Configuration Tool
を起動して SDK を切り替えておきます。
include パスの順番には注意が必要です。
Tools → Options → Projects and Solutions → VC++ Directories
Win32 / Include files
$(DXSDK_DIR)\include よりも上に $(WindowsSdkDir)\include が来るようにします。
DirectX SDK の install で直接 C:\Program Files ~とパスが書き込まれている
ことがあるので、その行は削除して $(DXSDK_DIR)include に置き換えておくことを
お勧めします。
lib も同じようにします。
● Vista で Direct2D が動く
Windows7 SDK beta があれば Direct2D のプログラムを作ることが出来ます。
実際に走らせるには Windows7 beta をインストールした PC が必要です。
Direct2D は結局 Direct3D10.1 を呼び出しているだけのはず。
Direct3D10.1 で下位 GPU もなぜか動くことがわかったので、もしやと思って
Windows7 beta から d2d1.dll だけ vista に持ってきたら拍子抜けするほどあっさり
動作しました。
とりあえず build したプログラムと同じ場所に d2d1.dll と DWrite.dll だけ置いておけば
Vsita でも Direct2D のプログラムを作って走らせることが出来るようです。
関連エントリ
・Direct2D その(2) インターフェース
・Direct2D と Direct3D10.1 の下位互換
2009/02/03
Direct2D その(2) インターフェース
ヘッダを読みながら整理してみました。
● RenderTarget
基本となるのが ID2D1RenderTarget です。いわゆるキャンバスのこと。
各種描画命令を使って RenderTarget の上に絵を描いていきます。
次のバリエーションがあります。
それぞれ Bitmap (Texture) に描いたり、そのままウィンドウに描いたりできるということ。
ラインなどプリミティブを描画する命令もありますが、パス(Geometry) を使ったり
DirectWrite を併用してテキストも描くことができます。
描画時に SetTransform() で渡した 3x2 matrix が適用されるようです。
2D の回転、拡大縮小、平行移動などが可能。
● Geometry
Direct2D を特徴付ける存在といえるかもしれません。
ID2D1Geometry はパスや形状などジオメトリを格納します。
無理矢理例えれば Direct3D の VertexBuffer/IndexBuffer のような存在でしょうか。
パスを構成する要素、ラインやベジェ(2次、3次)、Arc を使用することができます。
Geometry の段階で Transform したり合成したり交差を考慮して演算したり、
といった操作が可能。結構自由度が高そうです。
ID2D1Geometry を継承しているインターフェースは次の通り。
● Brush
ID2D1Brush は描画時に使用する状態を保持します。マテリアルやレンダーステートを
保持した StateBlock のようなイメージでしょうか。GDI にもあります。
下記の種類があります。
大きいのがこの 3つのグループです。
その関係は「 Geometry を Brush を使って RenderTarget に描画する 」ということ。
ID2D1RenderTarget, ID2D1Geometry, ID2D1Brush はどれも ID2D1Resource に
属しています。ID2D1Resource を継承しているインターフェースは他にもあります。
ID2D1Resource に属していないのは ~ Sink 系と ID2D1Factory のみ。
~Sink はまだよく理解していませんが、Geometry を操作する場合のイテレータの
ような存在ではないかと思われます。
関連エントリ
・Direct2D と Direct3D10.1 の下位互換
● RenderTarget
基本となるのが ID2D1RenderTarget です。いわゆるキャンバスのこと。
各種描画命令を使って RenderTarget の上に絵を描いていきます。
次のバリエーションがあります。
ID2D1RenderTarget → ID2D1BitmapRenderTarget → ID2D1HwndRenderTarget → ID2D1GdiInteropRenderTarget → ID2D1DCRenderTarget
それぞれ Bitmap (Texture) に描いたり、そのままウィンドウに描いたりできるということ。
ラインなどプリミティブを描画する命令もありますが、パス(Geometry) を使ったり
DirectWrite を併用してテキストも描くことができます。
描画時に SetTransform() で渡した 3x2 matrix が適用されるようです。
2D の回転、拡大縮小、平行移動などが可能。
● Geometry
Direct2D を特徴付ける存在といえるかもしれません。
ID2D1Geometry はパスや形状などジオメトリを格納します。
無理矢理例えれば Direct3D の VertexBuffer/IndexBuffer のような存在でしょうか。
パスを構成する要素、ラインやベジェ(2次、3次)、Arc を使用することができます。
Geometry の段階で Transform したり合成したり交差を考慮して演算したり、
といった操作が可能。結構自由度が高そうです。
ID2D1Geometry を継承しているインターフェースは次の通り。
ID2D1Geometry → ID2D1RectangleGeometry → ID2D1RoundedRectangleGeometry → ID2D1EllipseGeometry → ID2D1GeometryGroup → ID2D1TransformedGeometry → ID2D1PathGeometry
● Brush
ID2D1Brush は描画時に使用する状態を保持します。マテリアルやレンダーステートを
保持した StateBlock のようなイメージでしょうか。GDI にもあります。
下記の種類があります。
ID2D1Brush → ID2D1BitmapBrush → ID2D1SolidColorBrush → ID2D1LinearGradientBrush → ID2D1RadialGradientBrush
大きいのがこの 3つのグループです。
その関係は「 Geometry を Brush を使って RenderTarget に描画する 」ということ。
ID2D1RenderTarget, ID2D1Geometry, ID2D1Brush はどれも ID2D1Resource に
属しています。ID2D1Resource を継承しているインターフェースは他にもあります。
ID2D1Resource → ID2D1Bitmap → ID2D1GradientStopCollection → ID2D1Brush → ID2D1StrokeStyle → ID2D1Geometry → ID2D1Mesh → ID2D1Layer → ID2D1DrawingStateBlock → ID2D1RenderTarget
ID2D1Resource に属していないのは ~ Sink 系と ID2D1Factory のみ。
ID2D1SimplifiedGeometrySink ID2D1GeometrySink ID2D1TessellationSink
~Sink はまだよく理解していませんが、Geometry を操作する場合のイテレータの
ような存在ではないかと思われます。
関連エントリ
・Direct2D と Direct3D10.1 の下位互換
2009/02/02
Direct2D と Direct3D10.1 の下位互換
● Direct2D とは
Direct3D に似ていますが別物です。
DirectDraw とも似ていますが役割が異なります。
現在 DirectX SDK ではなく Windows SDK for Windows 7 の方に含まれます。
下記のページより Windows7 SDK の beta 版を入手することが可能です。
・Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 SP1: BETA
Direct3D11 と違い WindowsVista では動かないので、動作確認には Windows7 beta が
必要となります。ドキュメントはこちらから。
・MSDN Direct2D
Direct2D は Direct3D よりも上位のレイヤに位置します。
レンダーバックエンドとして Direct3D を活用しつつ、ベクターや bitmap 等の 2D
レンダリングを可能とします。Direct3D や DirectDraw のようなハードウエア寄りの
プリミティブではなく、GDI のような高度な描画命令を多数有しています。
SVG/FXG/XAML のようなベクターグラフィックスに対応し、ポリゴンを表示するかわり
に美しい 2D をレンダリングすることに注力した API セットであるといえるでしょう。
現在の Direct2D が利用するのは Direct3D10.1 です。
10.1 といえば WARP によって高速なソフトウエアラスタライズも可能だし、リモート
デスクトップ等で利用可能なCommand Remoting だって使えます。
Direct2D の狙いはまさにここにあります。
ハードウエアアクセラレーション、ソフトウエアラスタライザ、そしてクライアント
サイドのレンダリングなど、2D の描画でもこれらの恩恵を受けられるようになります。
● Direct2D の謎
最初に疑問に思うのは Direct3D10.1 だと使えるハードがかなり限られてくるのでは
ないかということ。
従来 Direct3D10 は専用のビデオカードしか使えず D3D9 世代の GPU とは互換性が
ありませんでした。逆に Direct3D11 の方が下位互換性が強化されており、D3D9 世代の
GPU でも動作します。そのあたりをまとめたのは こちら。
どうやら D3D10 でも下位互換がサポートされることになった模様です。
たとえば一番新しい Direct3D SDK November 2008 のヘッダファイル D3D10_1.h を
見ても、下記の通り FEATURE LEVEL には 10 世代の GPU しか記載されていません。
ところが Windows7 SDK beta 付属の D3D10_1.h を見てみると・・
いつの間にか下位の FEATURE LEVEL が追加されています。
我慢を強いられた Direct3D10/Vista 世代はいったい何だったのでしょうか。
つまり Direct2D は Direct3D9 世代の古い GPU でもハードウエアアクセラレーション
がかかります。(実際に試してみました→後述)
さらに Direct2D は対応ハードウエアがなくてもソフトウエアラスタライザによって
動作可能と書かれています。これが WARP を指しているのか、それとも Direct2D が
さらに独自でラスタライザを有しているのかわかりません。
ハードウエアアクセラレーションといいつつも、おそらくジオメトリ部分は CPU の
割合がそれなりに高いのではないかと思われます。アンチエリアス等のピクセル合成
部分において GPU が活用されているのではないでしょうか。
Direct3D11 世代になればジオメトリ処理でも GPU の割合が高くなるかもしれません。
以前アウトラインフォントの GPU 描画に取り組んだのはジオメトリも GPU で処理させる
ことが目的でした。
もう一つ疑問に思ったのは Direct2D のインターフェースが最初から D2D1 と "1" が
ついていること。DXGI1 など他の API と同調するためなのか、"2" の登場
(Direct3D11 版?) を想定しているのかわかりません。
DirectWrite には "1" がついていませんでした。
●下位互換性の確認
3台とも Windows7 beta
Aero 無効かつ D3D10/11 全滅の GMA500 では HARDWARE_RENDERING だと
動きません。SOFTWARE_RENDERING では動作しました。
このことから HARDWARE/SOFTWARE のフラグ設定は機能しているものと思われます。
GMA950 の EeePC では両方動作しているので、ShaderModel2.0 でも Direct2D で
ハードウエアアクセラレーションが有効になっているのではないかと考えられます。
つまり Windows7 では Direct3D10.1 で ShaderModel2~3 が動いているということ。
直接 Direct3D10.1 を試した方が早かったかもしれません。
関連エントリ
・Intel GMA500 のスペックについて考える。続き (2)
・Windows7 リモートデスクトップと Direct3D
・Direct3D11/DirectX11 (18) GPU を使ったアウトラインフォントの描画の(6)
・Direct3D11/DirectX11 (5) WARP の試し方、Dynamic Shader Linkage
・Direct3D11 Technical Preview D3D11の互換性、WARP Driver
Direct3D に似ていますが別物です。
DirectDraw とも似ていますが役割が異なります。
現在 DirectX SDK ではなく Windows SDK for Windows 7 の方に含まれます。
下記のページより Windows7 SDK の beta 版を入手することが可能です。
・Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 SP1: BETA
Direct3D11 と違い WindowsVista では動かないので、動作確認には Windows7 beta が
必要となります。ドキュメントはこちらから。
・MSDN Direct2D
Direct2D は Direct3D よりも上位のレイヤに位置します。
レンダーバックエンドとして Direct3D を活用しつつ、ベクターや bitmap 等の 2D
レンダリングを可能とします。Direct3D や DirectDraw のようなハードウエア寄りの
プリミティブではなく、GDI のような高度な描画命令を多数有しています。
SVG/FXG/XAML のようなベクターグラフィックスに対応し、ポリゴンを表示するかわり
に美しい 2D をレンダリングすることに注力した API セットであるといえるでしょう。
現在の Direct2D が利用するのは Direct3D10.1 です。
10.1 といえば WARP によって高速なソフトウエアラスタライズも可能だし、リモート
デスクトップ等で利用可能なCommand Remoting だって使えます。
Direct2D の狙いはまさにここにあります。
ハードウエアアクセラレーション、ソフトウエアラスタライザ、そしてクライアント
サイドのレンダリングなど、2D の描画でもこれらの恩恵を受けられるようになります。
● Direct2D の謎
最初に疑問に思うのは Direct3D10.1 だと使えるハードがかなり限られてくるのでは
ないかということ。
従来 Direct3D10 は専用のビデオカードしか使えず D3D9 世代の GPU とは互換性が
ありませんでした。逆に Direct3D11 の方が下位互換性が強化されており、D3D9 世代の
GPU でも動作します。そのあたりをまとめたのは こちら。
どうやら D3D10 でも下位互換がサポートされることになった模様です。
たとえば一番新しい Direct3D SDK November 2008 のヘッダファイル D3D10_1.h を
見ても、下記の通り FEATURE LEVEL には 10 世代の GPU しか記載されていません。
typedef enum D3D10_FEATURE_LEVEL1 { D3D10_FEATURE_LEVEL_10_0 = 0xa000, D3D10_FEATURE_LEVEL_10_1 = 0xa100 } D3D10_FEATURE_LEVEL1;
ところが Windows7 SDK beta 付属の D3D10_1.h を見てみると・・
typedef enum D3D10_FEATURE_LEVEL1 { D3D10_FEATURE_LEVEL_10_0 = 0xa000, D3D10_FEATURE_LEVEL_10_1 = 0xa100, D3D10_FEATURE_LEVEL_9_1 = 0x9100, D3D10_FEATURE_LEVEL_9_2 = 0x9200, D3D10_FEATURE_LEVEL_9_3 = 0x9300 } D3D10_FEATURE_LEVEL1;
いつの間にか下位の FEATURE LEVEL が追加されています。
我慢を強いられた Direct3D10/Vista 世代はいったい何だったのでしょうか。
つまり Direct2D は Direct3D9 世代の古い GPU でもハードウエアアクセラレーション
がかかります。(実際に試してみました→後述)
さらに Direct2D は対応ハードウエアがなくてもソフトウエアラスタライザによって
動作可能と書かれています。これが WARP を指しているのか、それとも Direct2D が
さらに独自でラスタライザを有しているのかわかりません。
ハードウエアアクセラレーションといいつつも、おそらくジオメトリ部分は CPU の
割合がそれなりに高いのではないかと思われます。アンチエリアス等のピクセル合成
部分において GPU が活用されているのではないでしょうか。
Direct3D11 世代になればジオメトリ処理でも GPU の割合が高くなるかもしれません。
以前アウトラインフォントの GPU 描画に取り組んだのはジオメトリも GPU で処理させる
ことが目的でした。
もう一つ疑問に思ったのは Direct2D のインターフェースが最初から D2D1 と "1" が
ついていること。DXGI1 など他の API と同調するためなのか、"2" の登場
(Direct3D11 版?) を想定しているのかわかりません。
DirectWrite には "1" がついていませんでした。
●下位互換性の確認
3台とも Windows7 beta
・DesktopPC RADEON HD4850 (Direct3D10.1 ShaderModel4.1) (Aero 有効) ○ D2D1_RENDER_TARGET_USAGE_FORCE_HARDWARE_RENDERING ○ D2D1_RENDER_TARGET_USAGE_FORCE_SOFTWARE_RENDERING ・EeePC901 945GE GMA950 (Direct3D9 ShaderModel2.0) (Aero 有効) ○ D2D1_RENDER_TARGET_USAGE_FORCE_HARDWARE_RENDERING ○ D2D1_RENDER_TARGET_USAGE_FORCE_SOFTWARE_RENDERING ・VAIO type P US15W GMA500 (Direct3D9 ShaderModel3.0) (Aero 無効) × D2D1_RENDER_TARGET_USAGE_FORCE_HARDWARE_RENDERING ○ D2D1_RENDER_TARGET_USAGE_FORCE_SOFTWARE_RENDERING
Aero 無効かつ D3D10/11 全滅の GMA500 では HARDWARE_RENDERING だと
動きません。SOFTWARE_RENDERING では動作しました。
このことから HARDWARE/SOFTWARE のフラグ設定は機能しているものと思われます。
GMA950 の EeePC では両方動作しているので、ShaderModel2.0 でも Direct2D で
ハードウエアアクセラレーションが有効になっているのではないかと考えられます。
つまり Windows7 では Direct3D10.1 で ShaderModel2~3 が動いているということ。
直接 Direct3D10.1 を試した方が早かったかもしれません。
関連エントリ
・Intel GMA500 のスペックについて考える。続き (2)
・Windows7 リモートデスクトップと Direct3D
・Direct3D11/DirectX11 (18) GPU を使ったアウトラインフォントの描画の(6)
・Direct3D11/DirectX11 (5) WARP の試し方、Dynamic Shader Linkage
・Direct3D11 Technical Preview D3D11の互換性、WARP Driver