次の方法で共有


Visual Studio でのシェーダー デバッガーの使用

シェーダーをデバッグするための最新のツールは、いくつかのチュートリアルで使用されている PIX (「頂点シェーダーのデバッグ」または「ピクセル シェーダーのデバッグ」を参照) です。

Microsoft Visual Studio .NET は、DirectX Extensions for Visual Studio .NET (シェーダー デバッガー) を使用して、アセンブリレベル言語と上位レベル言語の頂点シェーダーおよびピクセル シェーダーとエフェクトのデバッグをサポートします。多数のデバッガー機能を以下に示します。コンピューターをシェーダー デバッグ用として準備する手順については、「Visual Studio でのシェーダーのデバッグ (Direct3D 9)」を参照してください。

デバッガーは、デバッグ バージョンのランタイムと特定の種類のデバイスで動作します。リファレンス デバイスを使用している場合は、頂点シェーダーとピクセル シェーダーをデバッグできます。頂点シェーダーは、それらが、ソフトウェア頂点処理用に作成されたハードウェア アブストラクション レイヤー (HAL) デバイス上で稼働している場合にデバッグできます。ハードウェア頂点処理または "ピュア" HAL デバイスでは、デバッグはサポートされていません。デバイスの種類の詳細については、「D3DDEVTYPE」を参照してください。

  • デバッグ情報でのビルド
  • デバッガーの起動
  • ブレークポイント
  • デバイス ステートの表示
  • C++ コートと Direct3D コードの同時デバッグ
  • 関連項目

デバッグ情報でのビルド

シェーダーのソースレベルのデバッグを実行するには、シェーダーをデバッグ情報でビルドする必要があり、さらにそれに関連付けられたディスク上のソース ファイルが必要です。このようなシェーダーは、次の 2 とおりの方法で作成できます。

  • ビルド時に、Vsa.exe (頂点シェーダー アセンブラー)、Psa.exe (ピクセル シェーダー アセンブラー)、または Fxc.exe (上位レベル言語コンパイラ) を使用し、/Zi コマンドライン フラグを指定して、シェーダーをコンパイルします。
  • 実行時に、D3DXAssembleShaderFromFile または D3DXCompileShaderFromFile を使用し、D3DXSHADER_DEBUG フラグを指定して、シェーダーをコンパイルします。コンパイラ フラグの詳細については、「D3DXSHADER フラグ」を参照してください。

デバッグを目的とする場合は、/Od コマンドライン フラグまたは D3DXSHADER_SKIPOPTIMIZATION フラグを指定して、最適化を無効にします。

D3DXAssembleShaderD3DXCompileShaderD3DXCreateEffect などのメソッドを使用してメモリーからシェーダーをコンパイルする場合は、デバッガーを適切に動作させるために、シェーダー コードに #line ディレクティブを追加します。次に、1 つの例を示します。


#line 2 "currentfile.fx"

シェーダー デバッガーを使用するために、Visual Studio .NET でアプリケーションをビルドする必要はありません。任意のコンパイラでアプリケーションをビルドし、その後、Visual Studio .NET を使用して、アプリケーションを起動し、[プロセスにアタッチ](Attach To Process) ダイアログ ボックス (次のトピックで説明) を使用して、それをデバッグします。

デバッガーの起動

アプリケーションをデバッグするには、アプリケーションがデバッグ バージョンの Microsoft Direct3D ランタイムを使用しており、シェーダー デバッグが有効になっている必要があります。これらのオプションは、Microsoft DirectX コントロール パネル アプレットの [Direct3D] タブで設定できます。また、ターゲット コンピューターで、DirectX デバッグ サービスが実行されている必要があります。このサービスは、Microsoft DirectX Extensions for Visual Studio .NET をインストールするときに、自動的にインストールされます。

  • HAL デバイスを使用している場合は、ソフトウェア頂点処理用に作成された頂点シェーダーのみをデバッグできます。ピクセル シェーダーは、一切デバッグできません。"ピュア" HAL デバイスでは、デバッグはまったくサポートされていません。
  • リファレンス デバイスを使用している場合は、すべての頂点シェーダーまたはピクセル シェーダーをデバッグできます。"ピュア" リファレンス デバイスのデバッグは、"非ピュア" リファレンス デバイスの場合と同様に動作します。

デバッグを起動する方法は 2 とおりあります。どちらの方法も C++ アプリケーション上で動作しますが、マネージ コード アプリケーションをデバッグできるのは 2 番目の方法を使用した場合だけです。

技法 1:[デバッグ](Debug)、[Direct3D]、[Start With Direct3D Debugging] の順にクリックし (または、CTRL+ALT+F5)、デバッガーを起動します。

技法 2:既に実行中の Direct3D プロセスに "アタッチ" できます。Visual Studio .NET からこれを実行する最も簡単な方法は、次のとおりです。

  1. [デバッグ](Debug) メニューで、[デバッグなしで開始](Start Without Debugging) コマンドを使用してアプリケーションを起動します。

  2. [デバッグ](Debug) メニューで、[プロセス](Processes) をクリックして、[プロセス](Processes) ウィンドウを開きます。

  3. プロセス リストからアプリケーションを選択し、[アタッチ](Attach) をクリックします。

  4. [プロセスにアタッチ](Attach to Process) ダイアログ ボックスで、[ネイティブ](Native) を選択して C++ コードをデバッグし、さらに、[Direct3D] を選択して Direct3D コードをデバッグします。C++ と Direct3D の両方のコードを同時にデバッグできます (このトピックの下部にある「C++ コートと Direct3D コードの同時デバッグ」を参照)。

    また、Visual Studio .NET は Direct3D アプリケーションのリモート デバッグもサポートしています。リモート コンピューターの Direct3D プロセスにアタッチするには、[プロセス](Processes) ダイアログ ボックスで、[名前](Name) ボックスにリモート コンピューターの名前を入力し、その後、ローカル プロセスの場合と同様に、そのプロセスにアタッチします。

ブレークポイント

頂点シェーダーまたはピクセル シェーダーのソース ファイル内にブレークポイントを設定するには、シェーダーがデバッグ情報を保持している必要があります (「デバッグ情報でのビルド」を参照)。モジュール ウィンドウ ([デバッグ](Debug)、[Windows]、[モジュール](Modules) の順にクリック) を使用して、現在ロードされているすべてのシェーダーを表示できます。ネイティブ コードをデバッグしている場合は、ウィンドウを右クリックして [Show Modules for All Programs] を選択すると、ロードされているシェーダーが表示されます。

行ブレークポイント

C++ ソース コード内でブレークポイントを設定するのと同じ方法で、シェーダー内の特定の行にブレークポイントを設定できます。

  1. Visual Studio .NET テキスト エディターでソース ファイルを開きます。ブレークポイントを設定する行にカーソルを移動し、[ブレークポイントの設定/解除](Toggle Breakpoint) コマンドを選択します (既定では F9)。
  2. ブレークポイントを設定するソース コード内の行を右クリックし、ショートカット メニューから [ブレークポイントの挿入](Insert Breakpoint) を選択します。
  3. [ブレークポイントの作成](New Breakpoint) コマンドを選択します (既定では CTRL+B)。[ブレークポイントの作成](New Breakpoint) ダイアログ ボックスの [ファイル](File) タブを使用して、ファイル名と、オプションでブレークポイントの行数を入力します。

ソース コード内の行の横にあるマージンを左クリックすると、ブレークポイントのオン/オフが切り替わります。

関数のブレークポイント

[Breakpoint Properties] ダイアログ ボックスの [関数](Function) タブを使用して、名前としてシェーダー関数の大文字/小文字を区別する名前を入力し、言語を Direct3D Shader に設定します。関数名は、デバッグ情報に格納されているシェーダー関数の名前、またはシェーダーを含むファイルの名前になります。モジュール ウィンドウ ([ウィンドウ] をクリックし、[ウィンドウ...] メニュー項目を選択して開く) に、現在ロードされているシェーダーとそれらの名前が一覧されます。IDirect3DDevice9::BeginScene および IDirect3DDevice9::EndScene のブレークポイントは、以前と同様に動作します。

条件付きブレークポイント

次の種類のブレークポイントは、条件が true のときに (条件が変更されたときとは逆に) ブレークポイントが実効されるように設定されている限り、条件を持つことができます。

  • 関数
  • ファイル/行
  • アドレス

式は、単一要素のブール演算の結果を評価する必要があります。

ピクセル領域ブレークポイント

ピクセル領域ブレークポイントは、特定の矩形内のピクセルを変更する直前にあるピクセル シェーダーの最初の命令でトリガー-されます。ピクセル領域ブレークポイントを設定するには、まず、[ブレークポイント](Breakpoint) ダイアログ ボックスの [データ](Data) タブに移動します。

  • 言語として Direct3D Shader を選択します。
  • [変数](Variable) テキスト ボックスに、次のいずれかの形式でブレークポイントを入力します。
    • (x,y) :(x, y) のピクセルの計算時に中断します。
    • (left,top)-(right,bottom) :矩形内の任意のピクセルの計算時に中断します。標準の RECT セマンティクスが適用されます。左端と上端は矩形内にあり、右端と下端は矩形外です。

別の方法として、マウスで矩形をレンダー ターゲット ツール ウィンドウにドラッグして、ピクセル領域ブレークポイントを作成することもできます。

アセンブリ コード (アドレス) ブレークポイント

シェーダーの特定の命令にブレークポイントを設定するために、デバッグ情報は必要ありません。アドレス ブレークポイントは、次の方法で設定できます。

  • [逆アセンブル](Disassembly) ウィンドウで、ブレークポイントを設定する命令を含む行にカーソルを移動し、[ブレークポイントの設定/解除](Toggle Breakpoint) コマンドを選択します (既定では F9)。

  • [逆アセンブル](Disassembly) ウィンドウで、ブレークポイントを設定する命令を含む行を右クリックし、ショートカット メニューから [ブレークポイントの挿入](Insert Breakpoint) を選択します。

  • [ブレークポイントの作成](New Breakpoint) コマンドを選択し (既定では CTRL+B)、[アドレス](Address) タブを選択し、[言語](Language) コンボ ボックスで Direct3D Shader を選択して、ブレークポイントが必要な命令のアドレスを入力します。

    アドレスの形式は、xxx:yyy です。ここで、

    • xxx はシェーダー モジュール番号です。
    • yyy は命令のアドレスです。

    xxx:yyy の値を検索するには、[逆アセンブル](Disassembly) ウィンドウを開き、ブレークポイントを設定する命令を検索して、直前の行からモジュール番号:アドレス番号をコピーします。xxx の番号は、頂点シェーダーの場合は "v" で、ピクセル シェーダーの場合は "p" で始まります。次に、番号の例を示します。P00000009:00000780 (P9:780 として入力可能)。これは、アドレス 780 のモジュール 9 にあるピクセル シェーダーにブレークポイントを設定します。

BeginScene または EndScene のブレークポイント

デバッグ中のアプリケーションが IDirect3DDevice9::BeginScene または IDirect3DDevice9::EndScene に達した時点にブレークポイントを設定するには、[ブレークポイントの作成](New Breakpoint) コマンドを選択し (既定では CTRL+B)、[関数](Function) タブの [言語](Language) コンボ ボックスで Direct3D Shader を選択して、関数名として BeginScene または EndScene のいずれかを入力します。

ステッピング

[デバッグ](Debug) メニューの [ステップ オーバー](Step Overv コマンド (既定では F10) を使用して、シェーダー コードをステップ スルーできます。Direct3D コードをステッピングすると、デバッグ中のアプリケーションは、実行する次の頂点またはピクセル シェーダー命令で中断します。

式の評価

デバッグ中のアプリケーションが頂点またはピクセル シェーダー内、または BeginScene もしくは EndScene ブレークポイントで中断された場合は、[ウォッチ](Watch) ウィンドウを使用して、デバッグ中のアプリケーションの状態を調べることができます。また、[逆アセンブル](Disassembly) ウィンドウまたはシェーダー ソース コード内で、マウスポイントをレジスタの上で一時的に静止させると、レジスタの内容をすばやく表示できます。

式構文では、レジスタ名、スィズル、コンポーネントごとに動作する次の演算子がサポートされています。

+ - * / == < != <= > >= [] ! || &, &

さらに、次の 2 つの組み込み関数もサポートされています。

  • any( e ) - e のいずれかのブール要素が true の場合に、TRUE を返します。
  • all( e ) - e のすべてのブール要素が true の場合に、TRUE を返します。

すべての型が正確に一致している必要があります。浮動小数点型リテラルは、小数点を持つ必要があります。小数点がない場合は、整数として処理されます。

次の式は、r0 の最初の 3 つの要素がすべて、c4 の対応する要素より小さい場合に TRUE を返します。

all( r0.xyz<c4.xyz )

定数レジスタには、a0 の x 要素に 1 を加算した値がインデックスとして付加されます。

c[a0.x+1]

レジスタの内容の表示

ウォッチ ウィンドウでレジスタの内容を表示するには、次の式構文を使用します。

registerName[.swizzle][,format][,w]

この場合

  • registerName は、調べるレジスタの名前です (たとえば、r0、oPos、t7)。
  • swizzle は、オプションのスィズル指定子です。これは、シェーダー アセンブリ言語のソース レジスタで使用されるものと同じです (たとえば、v0.xxyy、r2.rgb)。
  • format は、オプションの浮動小数点フォーマット指定子で、C++ デバッグの場合と同じものです。有効なフォーマット指定子は、次のとおりです。
    • e - 指数表記 (たとえば、1.23e+1)
    • f - 標準表記 (たとえば、12.3)
    • g - 'e' または 'f'。よりコンパクトな表記になります。
  • w は、表示する前に、最初の 3 つの要素を 4 番目の要素で除算するように命令するオプションの指定子です。

デバイス ステートの表示

デバイスのレンダリング ステートおよびテキスチャ ステージ ステートの現在の値を表示するには、[ウォッチ](Watch) ウィンドウで $DeviceState と入力します。

現在のピクセル位置の表示

ピクセル シェーダーが現在レンダリングしているピクセルの座標は、レジスタ vPos に含まれています (「位置座標レジスタ」を参照)。ウォッチ ウィンドウに vPos と入力すると、その値が表示されます。

サーフェスの内容の表示

レンダー ターゲットの表示 - 現在のレンダー ターゲット サーフェスの内容を表示するには、[デバッグ](Debug) メニューで [Direct3D]、[Render Target] の順にメニュー オプションを選択し、[Render Target] ウィンドウを開きます。このウィンドウは、デバッグ中のアプリケーションが中断モードに切り替わるたびに更新され、レンダー ターゲットの現在の内容が表示されます。

テキスチャの表示 - 現在テキスチャ ステージに選択されているテキスチャの内容を表示するには、[デバッグ](Debug) メニューで [Direct3D]、[テクスチャー](Textures) の順にメニュー選択し、さらに該当するテクスチャー ステージを選択して、[テクスチャー](Textures) ウィンドウを開きます。テクスチャー ウィンドウは、デバッグ中のアプリケーションが "中断" モードに切り替わるたびに更新され、対応するテクスチャー ステージの現在の内容が表示されます。

サーフェスの内容 (レンダー ターゲットまたはテクスチャーのいずれか) が使用できない場合は、サーフェスのウィンドウに "使用できません" というテキストが表示されます。サーフェスが使用できない理由としては、次のことが考えられます。

  • サーフェスをロックできない。サーフェスは、読み取り専用アクセスのためにロックできるように作成されている必要があります。ロック可能なバック バッファーを作成するには、IDirect3D9::CreateDevice の呼び出し時に、D3DPRESENT_PARAMETERS に D3DPRESENTFLAG_LOCKABLE_BACKBUFFER フラグを指定します。
  • サーフェスがボリューム テクスチャーである。現リリースでは、テクスチャー ウィンドウは、ボリューム テクスチャーの表示をサポートしていません。
  • サーフェスがサポートされていないピクセル フォーマットである。デバッガーは、現在、もっとも標準的な RGB および RGBA ピクセル フォーマットと、DXTn 圧縮テクスチャー フォーマットの表示をサポートしています。
  • デバッグ中のアプリケーションがリモート コンピューター上で実行されている。現リリースでは、リモートでのデバッグ時のサーフェスの表示はサポートされていません。

C++ コートと Direct3D コードの同時デバッグ

Visual Studio .NET のデバッガーは、複数のプログラム タイプの同時デバッグをサポートしています。典型的な C++ デバッグでは、"ネイティブ" プログラム タイプを使用します。Direct3D デバッグでは、"Direct3D" プログラム タイプを使用します。デバッグ中のアプリケーションが C++ コード内で中断した場合、現在のプログラムはネイティブに設定され、呼び出し履歴、ウォッチ ウィンドウ、および他のデバッグ ウィンドウに、そのネイティブ プログラムの状態が反映されます。同様に、デバッグ中のアプリケーションがシェーダー コード内で中断した場合は、現在のプログラムは Direct3D に設定され、デバッグ ウィンドウにその Direct3D プログラムの状態が反映されます。プログラム タイプを切り替えるには、[デバッグの場所](Debug Location) ツールバーの [プログラム](Program) コンボ ボックスを使用します。デバッグ中のアプリケーションがネイティブ コード内で中断された場合は、Direct3D プログラムの大半の状態は取得できない点に注意してください。ただし、逆は当てはまりません。たとえば、シェーダー内のブレークポイントで中断した場合は、ネイティブ プログラムに切り替えて、シェーダーを呼び出した原因となる C++ 呼び出し履歴を表示できます。

複数のプログラム タイプの同時デバッグの詳細については、「複数プログラムのデバッグ」を参照してください。

デバッグ情報なしのデバッグ

可能な場合は、デバッグ情報が有効なシェーダーをビルドします (「デバッグ情報でのビルド」を参照)。"即時" にビルドされるシェーダーなど、デバッグ情報を使用したビルドが不可能な場合は、デバッグは可能ですが、かなり厄介になります。ソース コードが使用できないため、ソース コードのブレークポイントは動作しません。デバッグ情報なしでのデバッグするためのアプローチの 1 つは、BeginScene ブレークポイントを設定し、ブレークポイントに達したときに、F10 キーを押して、最初のシェーダーのシェーダー コードにステップ インすることです。逆アセンブリ コードをステップ スルーする場合は、[逆アセンブリ](Disassembly) ウィンドウでブレークポイントを設定できます。また、[モジュール](Modules) ウィンドウを使用して、現在ロードされているすべてのシェーダーの名前を表示し、必要に応じて選択的にそれらにブレークポイントを設定できます。

関連項目

Direct3D 9 のツール