3流プログラマのメモ書き

元開発職→社内SE→派遣で営業支援の三流プログラマのIT技術メモ書き。 このメモが忘れっぽい自分とググってきた技術者の役に立ってくれれば幸いです。(jehupc.exblog.jpから移転中)

Windows7で気になる件 Part3(グラフィック描画メモ)

前回CrystalMarkでのWindows7ベンチマークでグラフィック関連、特に2Dがらみが異常にスコア低かった件の調査です。

調査してるうちに、2Dでの描画ってのはレスポンスに直結するのでかなり大事な部分ってことを今更ながら思い出しましたよ。

■XP時代のグラフィックアーキテクチャ(XPDM)

さて、Windows7の前にXP以前がどのように2D描画してたかです。

XP以前の時代のグラフィックアーキテクチャは 2DがGDI/GDI+、3DがDirect3Dで構成されてます。

XP時代のグラフィックドライバは XP Display Driver Model(XPDM もしくは XDDM)と呼ばれるもので、こちらもGDI用とDirectX用に分かれてるようですね。

制限多いかつ複雑仕様のGDIですが、APIから直にドライバへ、そしてGPUの2D用アクセラレータへ描画命令が流れるので高速で描画できます。

ちょうどAPIの構成としては下記の図のような感じです。

■Vsita時代のグラフィックアーキテクチャ(WDDM1.0)

Vistaではグラフィックアーキテクチャが一気に変わりました。

API構成は下記の図のように変化します。

この図を見てわかるように2Dも3Dもすべて DirectX を介して描画される仕組みになってます。

そのため、グラフィックドライバも新たに Windows Vista Display Model(WDDM) に対応したものとなります。

(この Vista リリース時の WDDM は初期バージョンなので、WDDM1.0 とも呼ばれるようです)

この描画機能の DirectX(Direct3D) への統合が弊害を生むことになります。

それは2D描画が異常に遅くなったということです。

なぜかというと、描画を Direct3D に統合したため GDI/GDI+ による描画がソフトウェアレンダリングされてから Desktop Window Manager(DWM) に送られるからです。(ソフトウェウェアレンダリングはCPUで描画します)

さらに、DWM への描画データの送り方にもひと癖あります。

いったんシステムメモリにCPUで描画したイメージを保存してから、DWM へ転送しているのです。

つまり、この方法だと、ソフトウェアレンダリングとシステムメモリからビデメモリ(VRAM)へのイメージ転送にコストがかかるのと、ソフトレンダリングの結果をシステムメモリ、VRAMの両方に同一の画像のコピーを持つので、共に膨大なメモリが必要になります。

また、XPDMではグラフィックドライバがカーネルモードだけでしたが、WDDMでは安定性を確保するためにドライバ内でユーザーモードカーネルモードに分かれています。分かれたぶん、オーバーヘッドが発生しますよね。

なお、この描画シーケンスを図にしたものが下記です。

ちなみに、システムメモリにバッファするので、ウィンドウを開くごとに DWM (と各exe)のメモリが増えていきます。

この辺はDWM による描画の現場を押さえる - NyaRuRuの日記で検証されてます。

確かに、この方法使うと従来のGDIに比べ、ウィンドウ再表示の WM_PAINT メッセージを処理してウィンドウ再表示する回数が減るのでCPU負荷の軽減やちらつき防止には役立つかもしれません。

しかし、GDIがソフトウェアレンダリングになるということは、GPUではなくCPUの性能が求められますよね。だからCPUが遅い低スペックマシンだと逆効果になって描画にもっさり感が出たんだと思います。

(ただし、VistaにおいてWDDM1.0に対応したドライバだけ上記のような描画シーケンスになるようです。WDDMに対応してないドライバでは従来通りのXPDMドライバとなるので、ハードウェアによるGDIアクセラレータが働きます。)

ここまでが XP , Vista でのグラフィック描画アーキテクチャです。

簡単にまとめると、XPDM(XP時代)のGDIがハードウェアで直に描画できてたのが、WDDM1.0(Vista時代)から(Direct3Dで出力するようになったため)GDIがCPUによるソフトウェアレンダリングになったため2D描画が遅くなった + 同一の描画イメージを2重に持つためメモリ食いになった というわけですね。

ここまでの話は下記サイトで詳しく説明されています。

Windows Vista での GDI/GDI+ 描画 - NyaRuRuの日記

今回の記事はほぼこちらのブログを参考にさせてもらってます。かなり詳しい考察です。

@IT:改良されたVistaの描画アーキテクチャ

Vistaアーキテクチャの基本動作と利点。

WDDM, DWM: pros and cons - NyaRuRuの日記

WDDM1.0とDWMのメリット、デメリット。

Vistaを買ってはいなけい理由: あるプログラマの手記

MS批判が過激ですが、中ほどくらいからVistaでのGDIについて書いてます。

[特集]Vista買うのはまだ早い!(1)グラフィックス編

Windows7時代のグラフィックアーキテクチャ(WDDM1.1)

さて、Windows7ではグラフィックのアーキテクチャはどうなったんでしょうか?

グラフィックドライバモデルが、Vista時代にWDDM1.0だったのが WDDM1.1 になってます。

特に、Vistaで不評だったGDIの描画が改善されているようです。

まず、Vistaの時(WDDM1.0)のGDI描画は同一の画面のコピーをメインメモリとビデメモリ(VRAM)の両方に持っていました。

これが膨大なメモリを食いつぶしてましたが、Windows7(WDDM1.1)ではGDIアプリケーションはドライバ(GDIハードウェアアクセラレーションを使って)を経由して直にVRAMに描画できるようになりました。

これにより、GDIアプリケーションのウィンドウイメージをメインメモリに持たなくてすむので、メモリ使用量の軽減となります。

そして、ドライバ(とGPU)がGDIアクセラレーションを新たな形で実装したので、ソフトウェアレンダリングしてたWDDM1.0に比べ高速で描画できるようです。(といっても、XPDM時代に比べると、ドライバ内のGDIドライバファンクションの数は少ないためXP時代ほどまでに速くなるかどうか微妙らしいです。ここの詳細はGDI アクセラレーションについて整理する - NyaRuRuの日記に詳しく説明。)

いずれにせよ、WDDM1.1のドライバであれば、Vista時代のWDDM1.0に比べメモリ使用量の軽減と、GDI描画速度の回復というメリットがあるわけですね。

WDDM1.1ドラバでの描画シーケンスは下記のように感じだそうです。

Window7ではDirectX10.1を採用してます。つまり、DWMで描画する際にもDirect3D 10.1のAPIを使ってるわけですね。

で、Direct3D 9時代のGPUを積んでる場合は、GPUに足りない機能をソフトウェアエミュレーションで実現してるようです。

さらに、WDDMに対応してないGPUでも Direct3D Warp10 という機能により Direct3D 10.1 の機能をすべてソフトウェアエミュレーションで処理することができるようです。

つまり、古いグラフィックカードだと余計にCPU負荷を食ってしまうようですね。

また、2D描画においてGDIに置き換わるものとして Direct2D と DirectWrite という新APIがサポートされたようです。

ただ、既存のアプリケーションがこれを利用するになるまでは結構時間がかかるかもしれません。(現状.Netで簡単にDirect2D,DirectWriteを呼び出す方法もなさそうですしね。)

Windows7でグラフィック周りがどう変わったかは下記のサイトを参考にさせてもらいました。

Windows 7 のグラフィックスの変更点を整理する - NyaRuRuの日記

XP,Vista時代のアーキテクチャ復習と、Windows7でどう変わったかを詳しく解説。特にアーキテクチャ図は参考になります。

Direct2D 入門 ≫ Blog Archive ≫ デバイスロスト&ドライバ

前半部分で解説。

Windows 7グラフィック性能改善、少ないメモリでも動作 | エンタープライズ | マイコミジャーナル

どうやらGDIグラフィック描画時のロックも変更した模様。これによりマルチコアCPU環境でGDIのパフォーマンスが上がるようです。

InfoQ: Windows 7のグラフィックスエンジンはVistaよりも優れたものになろうとしている

改善点が簡潔にまとめられてます。

ASCII.jp:DirectX 10.1をベースにするWindows 7 |あなたの知らないWindows

DirectX10.1がなぜDirectX9のグラボで動くのか説明。

ASCII.jp:Windows7で大幅に変わったグラフィックドライバー|あなたの知らないWindows

WDDM1.1の説明やGDIのロックに関する改善、WDDM1.0ではVistaと同じってことがまとめられてます。

@IT WDDM 1.1(Windows Display Driver Model 1.1)

WDDM1.1の説明で、2Dの描画処理もドライバ+GPUで高速化してることが書かれています。

Aero Glassを有効にすると2D描画性能がアップ -- 「WDDM 1.1」を整理する(2) - ZDNet Japan

WDDM1.0とWDDM1.1でのベンチマーク結果が載せられてます。やっぱWDDM1.1速いです。

【特集】すべてが分かるWindows 7大百科 (38) 第3章 Windows 7のユーザーインターフェース - パフォーマンスが改善されたDesktop Window Manager マイコミジャーナル

WDDM1.1でGDIアクセラレーションのサポートが書いてます。

3流PGPCの2Dが遅かった原因は?

さて、ここまでXP以前からVista,Windows7までのグラフィック描画に関することを書いてきました。

この知識を踏まえて、なぜ前回CrystalMarkでのベンチマークで描画機能が低かったか、そしてXPより重く感じるのかの検証をしたいと思います。

Vista時代のWDDM1.0を使ったアーキテクチャでGDI描画は遅くなりました。

しかし、Windows7WDDMが1.1になりだいぶ改善されました。ところが、これにはグラフィックドライバがWDDM1.1でないといけません。

では、ドライバWDDM1.1ではない場合、例えばWDDM1.0だとどうなるんでしょうか?

その場合は、WDDM1.0、つまりVista時と同じ描画アーキテクチャになるようです。さらに WDDM1.0でない場合は、XPDMドライバでも動くようWindows7はサポートされているようです。

3流PGの使ってるグラフィックボードは NVIDIA GeForce 7600GS です。

ドライバは最新のものを先日入れました。(バージョン191.07)

このドライバがXPDM,WDDM1.0,WDDM1.1なのかは「DirectX 診断ツール」を使えばわかります。(XPはシステム情報から見れたんだけどWindows7はファイル名を指定して実行で「dxdiag.exe」と入れないとだめなよう)

上のSS見てわかるようにこのドライバはWDDM1.0を使ってるようです。

これゆえに3流PGのPCはGDI描画のレスポンスが遅いようです。

また、DDIが9Exとなっているように、Direct3D 9のGPUなので、DWMがDirect3D 10.1の足りない機能をソフトウェアエミュレートしてこともさらに遅くしてる要因になっているのかもしれません。

いずれにせよ、WDDM1.0を使ってることが原因だということがわかったので、NVIDIAがGeForce7x00用のWDDM1.1ドライバを出してくれるのを待つか、DirectX10.1対応ビデオカードを買うかしか解決策はなさそうです。(ドライバ出してくれるのかどうか分かりませんが。。4Gamer.netによると、GeForce 8以降じゃないとWDDM1.1じゃないみたいなこと書かれてますし。。)

と思っていると、Direct2DとGDIとDX10。 | ひねもす庵で面白い記述を見つけました。

GeForce 7までは2Dアクセラレーション回路がGPUにあったようで、ドライバ(XP)も2桁の頃は2Dアクセラレータに対応してたようです。

つまり、今のWindows7にXP用2桁のドライバを入れてみればいいわけです。XP用なので、おそらくXPDMドライバモデルでしょう。その場合、GDIがGPUの2Dアクセラレータを使うことができるので、GDI描画がXP相当になるじゃないかという考えです。(当然Aeroは使えなくなりますが。。)

上記の実験結果をWindows7で気になる件 Part4(グラフィック描画メモ補足)で書いてみました。

Windows 7 UltimateWindows 7 ProfessionalWindows 7 Home Premium