GPUViewで確認できるEventを簡単に追加する方法

GPUViewは、GPUとCPUのスレッド実行のタイミングを確認する際に特に有用なのですが、処理が複雑になると、一体どのDMAパケットが、何の処理をしているのかが分かりにくくなります。特に、他人の書いたプログラムをチェックしている際などは顕著です。こんなときに、Custom EventをマーカーとしてGPUViewのLogに埋め込むことが出来れば、CPU側が一体何をしているタイミングなのかを簡単に知ることが出来ます。

参考

ほぼこのBlogの記事の内容のままです。
KriScg – Krzysztof Narkowicz. Game engine and graphics programmer

Eventの登録

適当なGUIDを用意して、Eventとして登録します。

#include "Evntprov.h"
#pragma comment( lib, "Advapi32.lib" )
#pragma comment( lib, "Rpcrt4.lib" )

static int initialized;
static REGHANDLE gEventHandle;
if (!initialized) {
      GUID guid;
      UuidFromStringW((RPC_WSTR) L"a9744ea3-e5ac-4f2f-be6a-42aad08a9c6f", &guid);
      EventRegister(&guid, nullptr, nullptr, &gEventHandle);
      initialized = -1;
}

Eventを発行する

 最後の引数のStringが、EventのPrivate Data領域に格納されるので、何らかのデータを埋めておくと、後ほどGPUViewのEvent Listenerで確認することが出来ます。ただし、Private Dataの内容で簡単にフィルタリングすることは出来ないので、他のCustom Eventと区別したい場合は、別のGUIDを用意したほうが良いと思いますが、EventRegisterを通じたEventの登録は、プロセスあたり、1個か2個程度に留めるようにとMSDNに記述があるので、あまり大量のEventを登録するのは問題になるかもしれません。
 一応念のためですが、このEventはGPUとは一切関係ないので、記録される時間はCPU側でこのEventが発行された時間です。

EventWriteString(gEventHandle, 0, 0, L"Render");

Log.cmdを改変する

 このままでは、Eventが発行されても、GPUViewのLogに記録されないので、Custom EventがLogに記録されるように、Log.cmdを改変します。おそらく別途Xperfを起動しても良いと思われますが、とりあえずDXのEventを記録しているXperfに付け足します。

set TRACE_CUSTOM_GUID=a9744ea3-e5ac-4f2f-be6a-42aad08a9c6f
.
.
.
Xperf -start DxLogger -on %TRACE_CUSTOM_GUID%+%TRACE_DX%:0x2F %TRACE_LARGE_BUFFERS% -f DX.etl

Logを確認する

 CustomEventを発行するアプリを起動中にGPUViewでLogを記録します。正しくEventが記録できれば、EventListを確認すると登録したEventがGUID Listに表示されるはずです。EventのPrivateDataに、指定したStringが格納されているので確認することが出来ます。EventWriteStringは引数にWSTRを取りますが、GPUViewの表示はDump+ASCIIなので、この辺は適当に調整したほうが、GPUView上では読みやすいかもしれません。

gpuview_custom_01

Eventを選択すれば、記録された時間が赤い線で表示されるので、Eventの発行タイミングを簡単に確認することが出来ます。

gpuview_custom_03