Windows Vista での GDI/GDI+ 描画

この文章の初版が「煽りともとれる」という指摘はもっともだと思いますので,修正しお詫び申し上げます.(id:NyaRuRu:20061202#p1)
『【速報】Windows Vista製品版の処理性能をチェック』及び「PC オンライン」でのその詳細記事『Vistaの製品版で性能をチェック』より.

Vista がXPに後れを取ったのは、2Dの描画性能。通常の作業をしている範囲では特に遅さは感じないのだが、Excelのマクロによるテストを実施したところ、画面の描画はXPの半分以下の性能となった。原因として、透明なウインドウ枠などを特徴とする新ユーザーインタフェース「Windows Aero」の処理負荷が影響していることが考えられる。実際、Aeroを無効にすると2〜3割性能が向上した。しかしそれでもXPには及ばないことから、それ以外の要素が関係している可能性もある。なお「3DMark 06」を使った3Dの描画テストの結果は、XPと大きな差はなかった。

ベンチマーク結果のグラフ
(追記)結果自体は Vista の新しいドライバモデルである WDDM や,Aero の根幹である Desktop Window Manager (DWM) の構造を考えれば妥当なものだと思います.ただ,理由づけの方が迷走気味なのでちょっとフォローしておきましょう.
(追記2)Windows Vista WDDM 環境では,GDI 処理が完全ソフトウェア化されるのですが,パフォーマンスの低下についてはまずこの影響を疑うべきかと思います.これを確かめるには,ベンチマークスコアが CPU 速度に強く相関を示すかどうかを調べるのが効果的でしょう.
昨日紹介した WinFS の記事(id:NyaRuRu:20061130#p2)ではなかなか面白いところに注目されていた八木玲子氏ですが,半年以上前に開発者自身がちゃんと説明されている「この記事」はご存じないようですし.
ちょうど先日の VSUG イベントで喋ってきたばかりなのですが(id:NyaRuRu:20061108:p1),復習も兼ねてちょっとばかり書いておきましょう.

Windows Vista での GDI/GDI+ について

従来の Windows では,GDI 命令は「対応するドライバファンクション」というのが存在しました.ドライバファンクションは,3 つに大別できます

オプショナルファンクションは,もしドライバレベルで提供されなければ,ソフトウェアでエミュレートされるというものです.
一方,Windows Vista の WDDM は,もはや一切の GDI ファンクションの実装をドライバに求めません.つまり,全ての GDI 描画はソフトウェアレンダリングされます.VSUG イベントでも強調しましたが,Windows Vista WDDM 環境で,GDI の描画ベンチマークというのは,本質的には CPU ベンチマークと何ら代わりはありません*1
また,この辺りは誤解の元になりそうなので予め書いておきますが,DWM や WPF は,最新の 3D ハードウェアの機能を 100 % 引き出すわけではない,と私は考えています.PIX for Windows で見た WPF の動作は,動的頂点バッファと大量のテクスチャによる力業の描画でした*2.アルゴリズム的には,10 年前のゲームで既に確立していたものをブルートフォース化したものと言えるでしょう*3.しかし,それでも今までに比べれば遙かにレスポンスタイムが向上し,スケーラビリティが改善する,というのが私にとっての Vista の意義です.
DWM のアーキテクチャでは,GDI 描画される従来のアプリケーションは,かならずメインメモリ上にサーフェイスを持ち,一旦そのシステムメモリサーフェイス上で GDI 描画を完成させます.DWM は,一切の GDI 描画をハードウェアアクセラレートさせません.「Vista では最新の GPU を使って描画が高速化される」という表現は,注意深く使わないと大恥をかくことになります.
DWM の役目は,システムメモリサーフェイスの更新を検知し,適当なタイミングで Direct3D サーフェイスと同期を行い,そして Direct3D サーフェイスを元にコンポジションを行うことです.この仕組みは明らかにメモリイーターです.トップレベルウィンドウと同サイズのシステムメモリサーフェイスと Direct3D サーフェイスによるダブルバッファは何故必要なのでしょうか?
この理由は『Redirecting GDI, DirectX, and WPF applications』で語られています.

ウィンドウごとのダブルバッファ - Yes.GDI ウィンドウがシステムメモリとビデオメモリ両方への描画を必要とするというのは正しい.疑いなくこれを行うにはメモリコストがかかる.1 つの明らかな代替案は単純にビデオメモリへの描画のみを持ち,その (バッファのピクセル) フォーマットで描画を行う GDI リダイレクトメカニズムを持つことだ.これには 2 つの主要な問題がある.これらの (ピクセル) フォーマットは同じではない.そして GDI は DirectX (のピクセル) フォーマットでの描画をサポートしない*4.仮にその問題が解決したとしても,より根本的な問題が残る.多くの GDI オペレーション (例として XOR 描画,アルファブレンディング,テキスト描画) は,read-modify-write オペレーション (メモリから読み取って,変更し,書き込む作業) である.ネイティブビデオメモリサーフェイスにこれを行うことは,ビデオメモリから CPU (よってさらにシステムメモリに) に読み出し,処理を行い,そして書き戻すことを必要とする.これは概してひどく遅く,パイプラインをストールさせる処理である.

そう言う意味では,「steps to phantasien」の『いまどきのデスクトップ処理系』も若干誤解を招く表現になっています.

Window Management の上に Drawing のレイヤがある. この層はウィンドウへの描画機能を提供する. 直線, 曲線, 円, ビットマップの貼りつけなど. 性能の都合でドライバを直接利用することもあるため. ちょっと下にはみ出す図にした. Win32 の GDI, Mac OS の Quartz, freedesktop の cairo あたりがこれにあたる.

「いまどきの」Windows Vista WDDM 環境で,ドライバを直接利用すると言えるのは,Direct3D と OpenGL のみです.Direct3D に 曲線, 円,テキストの描画命令などありませんから,これらの処理は全て何らかの翻訳者を必要とします.
その 1 つが,GDI リダイレクションのように,トップレベルウィンドウという比較的大きな処理単位でソフトウェアレンダリングを行い,Direct3D を単なる転送装置に使用するというものです.ソフトウェア処理によって(疑似)半透明描画まで行っていた DirectDraw 後期のゲーム *5と,本質的には同じと言えるかもしれませんね.
一方で,Direct3D API の上にリッチな描画 API を独自実装したのが WPF です.だからこそ,Direct3D9 が動作する Windows XP でも WPF は動作することができます.




とまあ開示情報だけからでもこのあたりまでは十分到達可能です.唯一の難点は,開発者 blog が英語という,その一点でしょうか.

原因として、透明なウインドウ枠などを特徴とする新ユーザーインタフェース「Windows Aero」の処理負荷が影響していることが考えられる。実際、Aeroを無効にすると2〜3割性能が向上した。しかしそれでもXPには及ばないことから、それ以外の要素が関係している可能性もある。

何はともあれ,折角の日本語記事なので,頑張ってくださいね,と.


(追記3) 以前にも紹介しましたが(id:NyaRuRu:20060930#p2),『Windows Vistaに足りないもの』という記事で,「地味な技術」を分かりやすく解説することの大事さを述べられていた八木玲子氏ですので,今後より詳細な解説記事が書かれることを期待したいと思います.

関連記事

id:NyaRuRu:20061004#p1
id:NyaRuRu:20060925#p1

*1:これを確かめる意味でも,先ほどの記事ではビデオカードだけを交換して同じベンチマークをとって欲しかったところですが.

*2:興味がある方は,milcore.dll の export 関数を眺めてみるのも面白いでしょう

*3:ただし,最終的な画面更新にすら更新矩形を用い,全体を再描画しない程度には倹約家の心も持っています

*4:GDI は 0xXXBBGGRR で,Direct3D は 0xAARRGGBB が主流なため

*5:Falcom 系とか『とびでばいん』とか