はじめに
Windows OSにはコントロールパネルから変更できない多くの設定が存在し、それらの設定の多くはレジストリやiniファイルに格納されています。これと同じように、DirectX Runtimeにもいくつかのシステムレベルの設定が存在します。これらの設定は、エンドユーザにとってはあまり役立つものではありませんが、開発者が用いればデバッグや問題解決に利用できる有用なパラメータとなります。この記事ではこれらDirectX Graphicsの隠れた設定について、実装上のテクニックを交えながら紹介してゆきます。なお、以下で特に注釈がない場合、「DirectX」はDirectX 9.0cのDirectX Graphicsを指すと考えてください。
今回紹介するテクニックは、DirectX開発者のみに送るものではありません。デバッグで困ったときや既存ライブラリに機能を追加したいときなど、さまざまな使い道があると信じています。実のところ、私が全く予想もつかなかった分野で、この記事が役立つことが一番楽しみです。
目次
サンプルプログラム
- アプリケーション起動時にRetail/Debug Runtimeを選択する
- DirectXランタイムが出力するデバッグメッセージのログを作成する
- DirectXランタイムのProcessor Specific Graphics Pipeline(PSGP)を無効化する
コラム
- DirectXランタイムライブラリ
- DirectXのコンポーネントとサブシステム
- DirectXのフィーチャとユースケース
- マルチスレッドCRT
- フックの解放
- APIにブレークポイントを設定する
- フックハンドラと再入・再帰
- DirectX DLLを遅延ロードする
- プロセス終了処理とDLL_PROCESS_DETACH
- 浮動小数点演算とFP-strict
対象読者
- DirectXを利用したアプリケーションを開発されている方
- Windows APIを頻繁に利用されている方
- Windows OSの設計やWindows環境でのデバッグ技術に興味がある方
- Windowsでマルチスレッドアプリケーションを開発されている方
- クロスプラットフォームでの数値計算を行われている方
必要な環境
DirectX 9.0cをインストールした以下のOSで動作確認を行いました。
- Windows 98 Second Edition 日本語版
- Windows XP Professional SP2 日本語版
- Windows XP Professional x64 Edition 日本語版
サンプルコードは、以下のコンパイラでコンパイルできることを確認しています。
- Visual C++ .NET 2003 Professional Editon
- Visual C++ 2005 Express Editon
- Visual C++ 2005 Professional Editon
注意
今回紹介する設定は、公式ヘルプに記載されていないものも含まれています。これらの設定が今後リリースされるDirectXによってサポートされる保障はありません。また、サンプルコードは、既存の全ての環境でのテストは行っておりません。互換性の検証は十分に注意してください。
セットアップ
DirectX SDK
サンプルコードをコンパイルするには、DirectX SDKをインストールする必要があります。DirectX 9.0ダウンロードページからSDKをダウンロードしてください。サンプルコードの作成には、DirectX 9.0 SDK (December 2005)を使用しています。これ以降のSDKでコンパイルできるかどうかは不明ですが、大きな変更がない限りは対応できると思います。コンパイルに失敗する場合は、DirectX SDKのインクルードファイルディレクトリとライブラリディレクトリが、正しくVisual C++に設定されているか確かめてみてください。
Microsoft Platform SDK
Visual C++ .NET 2003またはVisual C++ 2005 Express Editionを使用している場合は、最新のPlatform SDKをインストールする必要があります。
Visual C++ 2005 Express Editionユーザの方については高萩 俊行さんの書かれた『Visual Studio 2005/Visual C++ 2005 Express EditionにPlatformSDKを統合する(改訂版) 』が参考になるでしょう。
サンプルコードの作成には、Windows Server 2003 SP1 Platform SDKを使用しています。
その他に準備しておいた方が良いもの
RegMon
「RegMon」(参考資料1)は、Sysinternals社が公開しているリアルタイムのレジストリアクセスモニタリングツールです。
解説で使用するので、Sysinternalsのサイトからダウンロードしておいてください。RegMonの使い方については、@ITの『レジストリへのアクセスをモニタする方法』を参照してください。
FileMon
「FileMon」(参考資料1)は、Sysinternals社が公開しているリアルタイムのファイルアクセスモニタリングツールです。
解説で使用するので、Sysinternalsのサイトからダウンロードしておいてください。
DebugView
「DebugView」は、Sysinternals社が公開しているリアルタイムのデバッグメッセージモニタリングツールです。
Visual C++などのデバッガを持たない環境でも、デバッグメッセージをモニタリングすることができます。
シンボルファイル
記事中に出てくるデバッガ上のコールスタックを再現するには、シンボルファイルが必要です。『シンボル サーバーの使用』に従って、シンボルサーバを導入しておくと良いでしょう。
予備知識
DirectX Graphicsにあまり馴染みがない方のために、本稿に関係するポイントをいくつかピックアップしてみました。本稿では3D技術については取り扱わないので、ライブラリとしての側面から見たDirectXについて見ていくことにします。
普段開発者がDirectX Graphicsと呼んでいるものは、大きく2種類に分けることができます。1つはDirectX Graphicsを使用するために最低限必要な機能セットで、これはドライバとDLLから構成されています。現在Windows Updateでダウンロードできたり、OSに標準で導入されていたりするDirectXランタイムライブラリ(以下では単に「ランタイム」と呼びます)とは、これらのバイナリ群のことを指しています。本稿ではこのランタイムのことを、特に「コアランタイム」と呼ぶことにします。
もうひとつのDirectX Graphicsの意味として、開発者が「DirectX Graphicsを使う」と言った場合、Microsoftが提供する各開発言語用の中間ライブラリのことを指すことがあります。これらの中間ライブラリはDirectX SDKに付属し、ソースコード・静的リンクライブラリ・DLLなどの形態で提供されています。C++言語用のD3DXや、.NET言語用のManaged DirectXなどがこれにあたります。開発者は、これらのライブラリを利用することで、既に提供されている機能を自分で実装することなく、製品を開発することができます。
D3D_DEBUG_INFO
フラグを追加することでCOM ABIが一部拡張され、デバッグ変数がvtblのアドレスの後に配置されるようになります。これにより条件付ブレークポイントやデバッガからの状態評価が容易になります。リリース年月 | バージョン |
2002年3月 | DirectX 9.0 |
2003年3月 | DirectX 9.0a |
2003年7月 | DirectX 9.0b |
2004年7月 | DirectX 9.0c |
なお「d3dx9_28.dll」の28は、DirectX 9.0 SDK(December 2005)のSDKバージョンを示します。SDKがアップデートされるたびに数字が増えてゆき、新しいバージョンのDLLによって上書きされてしまわないようになっています。
図5は、コンポーネントの更新頻度という視点でDirectXを見たものです。コンポーネントごとの大まかな更新頻度を、主観的な印象を基にいくつかポイントしてみました。ただし、作成にあたってきちんと統計をとったわけではなく、あくまで主観的な印象に基づいたものであることをご了承ください。
- 一口にDirectXと言っても、その内部には性質の異なるサブシステムが存在すること。
- 中間ライブラリを構成するコンポーネントの間にも依存関係が存在すること。
- 多くの中間ライブラリはC++言語で実装され、ソースコードレベルの依存関係が存在すること(実際、インターフェイスの絶縁が不完全なため、一部のコンポーネントのみを更新することは困難です。バージョンの変更はしばしば中間ライブラリのサブシステム全体を置き換える必要があります)。
- コアランタイムのコンポーネント更新周期は、おおよそ一年から数年にわたる期間に分布していること。
- 中間ライブラリのコンポーネント更新周期は、2ヶ月程度から数年の間と非常に広い期間に分布していること。
一方、中間ライブラリには、具体的なユースケースを想定したコンポーネントと、コアランタイムがカバーしないフィーチャを提供するコンポーネントが混在しています。残念ながら現状の中間ライブラリは適切な分割が行われないまま肥大化が続いているため、何らかのタイミングで適切な分離が行われるべきと考えます。
D3DXに含まれる、ファイルからテクスチャを作成するという機能は前者のユースケースに該当します。例えば
D3DXCreateTextureFromFile
API(参考資料3)は、よく知られたデータフォーマットの画像ファイルから、3D描画デバイスで使用可能なテクスチャを作成するというユースケースをカバーします。この機能は内部的に「空のテクスチャの作成」と「テクスチャへのデータ転送」というコアランタイムのフィーチャを用いて実装されています。一方、D3DXには興味深いフィーチャを提供するコンポーネントも存在します。
ID3DXEffect
インターフェイスによって提供される『エフェクトシステム』は、近年注目を浴びているDomain Specific Language(DSL)を用いて可変性を実現する野心的なコンポーネントです。このようなDSLが登場した理由のひとつとして、3D描画デバイスが非常に大量の描画設定を必要とするということが挙げられるでしょう。ゲーム開発の大規模化に伴い、多数の描画設定のセットを管理したり、頻繁な要求の変化(描画方式の変化)に対応することが重要となってきました。これに対しMicrosoftは、『エフェクトファイル』(参考資料4)と呼ばれる専用言語を定義しています。エフェクトファイルはコアランタイムの使用する設定の記述に加え、プログラマブルシェーダ記述言語として知られるHLSLやシェーダアセンブリを格納することができます。さらにエフェクトファイルは、構成要素に『アノテーション』と呼ばれるメタデータの付加を行うこともできます。C/C++言語側からは、リフレクションAPIを通してエフェクトファイルの内部要素にアクセスすることができ、実行時複合化を容易にしています。フィーチャとユースケースの視点でDirectXを解説した記事はまだ少ないので、機会があれば、いずれ詳しく取り上げてみたいと思います。
サンプルプログラムの概要
「src.zip」のアーカイブには、次のようなファイルとフォルダが格納されています。
- apihook.h
- apihook.cpp
- Sample1
- Sample2
- Sample3
- Column4
- Column8
「apihook.h」と「apihook.cpp」はAPI Hookの実装部で、プロジェクトにそのまま組み込んで使えるようになっています。その他のフォルダの中には、サンプルプログラムが入っています。各フォルダにはVisual C++ .NET 2003およびVisual C++ 2005用のソリューションファイルを用意しました。
サンプルプログラムが格納されたフォルダの「bin」以下には、こちらでビルド済みの実行ファイルが格納されています。32bit版と64bit版がありますので、ご使用の環境に合わせてお試し下さい。
なお、同梱したビルド済みの実行ファイルの実行には、D3DXランタイムライブラリが必要です。はじめに、コラム8「DirectX DLLを遅延ロードする」で紹介する「CheckD3DX.exe」サンプルを実行して、D3DXランタイムライブラリがインストールされているか確認を行うとよいでしょう。