読者です 読者をやめる 読者になる 読者になる

7080 + 1

ゲームプログラミングの記事を書いてます。

IDXGIDebug::ReportLiveObjects()を使うまでの道のり その1

記念すべき初投稿は、DirectX11のデバッグレイヤーの話です。

DirectXでは、COMオブジェクトを使った設計がされています。 COMオブジェクトについては詳しく知らないので、ここでは割愛します。

ようは、Release()忘れを絶対にするなよということです。 とはいっても結構やってしまったりします。

そこで、Release忘れが発生しているかを調べる方法があります。それがデバッグレイヤーです。 デバッグレイヤーというのはD3Dデバイスの話です。 CreateDeviceをする時に、D3D11_CREATE_DEVICE_DEBUGを第4引数に渡すことで作成できます。

デバッグレイヤーはRelease忘れのチェックなどの処理をするため、普通よりも重たいです。 デバッグビルド時のみ有効にするとかしておくと便利ですね。

さて、Release忘れはこんなふうに、VisualStudioの出力ウィンドウに表示されます。
出力されるのは、アプリケーションが終了した時です。

f:id:atori708:20150220013441p:plain

ズラリと並んでいます。文字に色が付いているのは、拡張機能を入れているからです。 便利です。
VSColorOutput extension (VS2013です)

これすべてがRelease忘れなんですが、各文の後ろにUNKNOWNと出ています。 これでは何がRelease忘れかわかりません。レンダーターゲットビューやらテクスチャやら色々とあるのに、 これでは困ります。

しかし画像の中の一番上で、

Process is terminating. Using simple reporting. Please call ReportLiveObjects() at runtime for standard reporting.

と書いてあります。ReportLiveObjects()を呼べば詳細を見れそうな気がします。

ここから私の長い旅が始まります。
ググってみると、IDXGIDebug::ReportLiveObjects()ID3D11Debug::ReportLiveDeviceObjects()が引っかかりました。

前者を解説する前に後者の説明をしたいと思います。 前者はWindows8以降でしか使えないです。
2015年2月現在、実装に至っていません。

ID3DDebug::ReportLiveDeviceObjects()は、D3Dデバイスがデバッグレイヤーであることが前提です。
以下ソースコードです。

// dxgidebug.hをインクルードしてください。

HRESULT hr;

ID3D11Device* pD3dDevice;
ID3D11Debug* pD3dDebug;

// デバイス作成は割愛

// 作成
hr = pD3dDevice->QueryInterface(__uuidof(ID3D11Debug), reinterpret_cast<void**>(&m_pD3dDebug));
if( FAILED(hr))
{
    return E_FAIL;
}

// 詳細表示
hr = m_pD3dDebug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL);

これだけです。超簡単です。注意すべきなのは、詳細が出力ウィンドウに表示されるのは、 メソッドが呼ばれた時です。そのときのCOMオブジェクトの状況を見ることが出来ます。

f:id:atori708:20150220021041p:plain

先ほどと違い、オブジェクトのインターフェースが見えるようになり、InitRefというものも追加されています。 RefCount、InitRefの両方が0になって初めてCOMオブジェクトは解放されます。
(2つの違いは残念ながら私にはわかりません...)

しかし先程の一文、

Process is terminating. Using simple reporting. Please call ReportLiveObjects() at runtime for standard reporting.

と書いてあります。あくまでReportLiveObjects()の方です。ReportLiveDeviceObjects()ではありません。

次回は、それを実装しようと悪戦苦闘し、あと一歩まで行った記録を記事にします。出来ました。
それではまた次回。