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

Direct2D (3) 互換性の検証と Vista で Direct2D

こちらで書いたように、Windows7 では Direct3D11 と同じく
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 の下位互換

Direct2D その(2) インターフェース

ヘッダを読みながら整理してみました。

● RenderTarget

基本となるのが ID2D1RenderTarget です。いわゆるキャンバスのこと。
各種描画命令を使って RenderTarget の上に絵を描いていきます。
次のバリエーションがあります。

ID2D1RenderTarget
 → ID2D1BitmapRenderTarget
 → ID2D1HwndRenderTarget
 → ID2D1GdiInteropRenderTarget
 → ID2D1DCRenderTarget

それぞれ Bitmap (Texture) に描いたり、そのままウィンドウに描いたりできるということ。
ラインなどプリミティブを描画する命令もありますが、パス(Geometry) を使ったり
DirectWrite を併用してテキストも描くことができます。
描画時に SetTransform() で渡した 3×2 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 の下位互換

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 しか記載されていません。

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

WindowsMobile touchkeysip v1.10 加速センサーで文字入力

WindowsMobile 用のソフトウエアキーボード touchkeysip に、
前から考えていた機能をいくつか追加しました。

ダウンロード
touchkeysip v1.10

●加速センサー対応

加速センサーに対応した専用バージョン touchkeysip GS をリリースしました。
アーカイブやインストーラを標準版と分けてあります。

Script 内でセンサー値を直接受け取ることが出来ます。
サンプル gsensorsip では本体を傾けることで画像をスクロールしているだけですが、
本体を傾ける向きで 日本語、英数、記号などの入力パネルを切り替えたり、
カーソルを移動させるといった応用も考えられます。
本体のアクションをきちんと処理するのは難しいですが、Script 処理次第では
何らかの動作で文字入力することも出来るかもしれません。

●ステータス領域のアイコン画像の切り替え

標準の SIP だと「あ」「A」など入力文字の状態が表示されているエリアです。
あらかじめ作成したアイコン画像を用意しておけば、状態に合わせて表示を切り替える
ことが出来るようになりました。

またキーボードをデザインした人が touchkeysip ではなく自前のアイコンを表示
したい、といった用途にも使えます。

●管理可能な画像を増量

アイコン表示追加に伴い、複数枚の画像の読み込みにきちんと対応しました。
従来は 2枚まで読み込めましたが、DisplayList に使えないなど中途半端な実装でした。
8 枚まで読み込めてかつ表示やステータスアイコンとして利用できます。
でも表示するデータはできるだけ 1枚にまとめた方が処理は高速だと思われます。

●タイマーの追加

加速センサー対応によって、従来のキーリピートとは別にポーリング用のタイマーが
必要となりました。よって複数のタイマー機能を使えるようにしています。
上限は容易に撤廃できますが API としてはとりあえず 4個まで。

●読み込める画像形式の追加

bmp 以外も読み込めるようになりました。jpeg など。
Script の命令自体は LoadBitmap のままです。
16bit RGB bitmap は直接読み込めないことがあるようです。

●サンプル

gsensorsip v1.00 はこれらの追加機能を実際に使用しています。
実用性は全く無く、あくまで機能のテスト用です。

●注意点

機能の追加や変更が多いため、互換性など何らかの問題がある場合は旧バージョン
v1.09 等を使用してください。
制作時に動作テスト可能な機種や環境も限られるため、必ずしも完全にテストが
行われているわけではない点にご注意ください。

関連エントリ
HTC Touch Diamond タッチセンサー API
WindowsMobile touchkeysip v1.07
WindowsMobile touchkeysip / ctrlswapmini