WinPixEventRuntime
PIX events are used to instrument your game, labeling regions of CPU or GPU work and marking important occurrences. Including this instrumentation while developing the game can make PIX captures far nicer to work with.
An “event” represents a region of time – so an event has a begin and an end. A “marker” is used to represent a single point in time.
Installation
The PIX event runtime is distributed as a NuGet package. If your project builds in Visual Studio, you can use Visual Studio to add this package:
- Right-click on the project in Solution Explorer.
- Manage NuGet Packages.
- Select the Browse tab.
- Type “WinPixEventRuntime” into the search box.
- Select the package and click Install.
- You can now #include “pix3.h” to access the PIX event APIs.
If your project uses some other build technology than Visual Studio, you can manually consume the NuGet package contents:
- Click the Download link on https://www.nuget.org/packages/WinPixEventRuntime
- Rename the .nupkg file to a .zip extension, then extract its contents.
- Include the header file: Include\WinPixEventRuntime\pix3.h
- Link with the library:
- For desktop apps: bin\WinPixEventRuntime.lib
- For Universal Windows Platform (UWP) apps: bin\WinPixEventRuntime_UAP.lib
- Place the corresponding .dll next to your game.
PIX instrumentation is only enabled if one of the preprocessor symbols USE_PIX, DBG, _DEBUG, PROFILE, or PROFILE_BUILD is defined. Otherwise the marker APIs compile out to nothing, which is typically what you want for final release builds of the game. It is often useful to maintain an intermediate build flavor for profiling purposes, which is fully optimized and leaves out self-checks such as ASSERT, but does include the PIX marker instrumentation. To do this, define one of the symbols USE_PIX or PROFILE before including pix3.h.
Note that the Windows SDK provides an older header named pix.h. This defines similar functions to pix3.h, but is obsolete and not compatible with PIX.
API Reference
PIXBeginEvent
PIXBeginEvent marks the start of a user-defined region of CPU or GPU work. There are overloads of PIXBeginEvent that support different types of strings and CPU and GPU events. Use PIXEndEvent to mark the end of the region. The paired calls to PIXBeginEvent and PIXEndEvent must be made from the same thread.
// CPU only void PIXBeginEvent(UINT64 color, char const* formatString, ...) void PIXBeginEvent(UINT64 color, wchar_t const* formatString, ...) // GPU and CPU void PIXBeginEvent(ID3D12CommandList* commandList, UINT64 color, char const* formatString, ...) void PIXBeginEvent(ID3D12CommandList* commandList, UINT64 color, wchar_t const* formatString, ...) void PIXBeginEvent(ID3D12CommandQueue* commandQueue, UINT64 color, char const* formatString, ...) void PIXBeginEvent(ID3D12CommandQueue* commandQueue, UINT64 color, wchar_t const* formatString, ...)
The GPU overloads also start an implicit CPU region.
PIXEndEvent
PIXEndEvent marks the end of a user-defined region of CPU or GPU work. There are overloads of PIXEndEvent that support different types of CPU and GPU events. Note that a GPU region that was started on a command list may be ended on a command list or a command queue, and vice versa.
// CPU only void PIXEndEvent() // GPU and CPU void PIXEndEvent(ID3D12CommandList* commandList) void PIXEndEvent(ID3D12CommandQueue* commandQueue)
The GPU overloads also end an implicit CPU region.
PIXSetMarker
PIXSetMarker inserts a user-defined marker into the CPU or GPU timeline:
// CPU void PIXSetMarker(UINT64 color, char const* formatString, ...) void PIXSetMarker(UINT64 color, wchar_t const* formatString, ...) // GPU and CPU void PIXSetMarker(ID3D12GraphicsCommandList* commandList, UINT64 color, char const* formatString, ...) void PIXSetMarker(ID3D12GraphicsCommandList* commandList, UINT64 color, wchar_t const* formatString, ...) void PIXSetMarker(ID3D12CommandQueue* commandQueue, UINT64 color, char const* formatString, ...) void PIXSetMarker(ID3D12CommandQueue* commandQueue, UINT64 color, wchar_t const* formatString, ...)
PIXScopedEvent
The PIXScopedEvent macro has the same overloads as PixBeginEvent, but will automatically issue a matching PixEndEvent call at the end of the C++ code scope where it is used:
PIXScopedEvent(UINT64 color, char const* formatString, ...) PIXScopedEvent(UINT64 color, wchar_t const* formatString, ...) PIXScopedEvent(ID3D12GraphicsCommandList* commandList, UINT64 color, char const* formatString, ...) PIXScopedEvent(ID3D12GraphicsCommandList* commandList, UINT64 color, wchar_t const* formatString, ...) PIXScopedEvent(ID3D12CommandQueue* commandQueue, UINT64 color, char const* formatString, ...) PIXScopedEvent(ID3D12CommandQueue* commandQueue, UINT64 color, wchar_t const* formatString, ...)
PIXReportCounter
PIXReportCounter allows a custom value to be graphed in System Monitor or timing captures.
void PIXReportCounter(wchar_t const* name, float value)
Note that PIXReportCounter does not has a char const* overload.
PIXNotifyWakeFromFenceSignal
Timing captures can show when a thread wakes up as the result of a fence being signaled. This needs some help from the application in the form of PIXNotifyWakeFromFenceSignal. This notifies PIX that an event handle was set as a result of a D3D12 fence being signaled. The event specified must have the same handle value as the handle used in ID3D12Fence::SetEventOnCompletion.
void PIXNotifyWakeFromFenceSignal(HANDLE event)
Color
The color parameter controls how the event will be displayed in timeline lanes when it appears in the PIX timing capture user interface. Suitable values can be obtained from one of these helpers, or you can pass in a raw DWORD noting that the format is ARGB and the alpha channel value must be 0xff:
// Returns a color for a PIX event or marker from the specified red, green and blue values INT PIX_COLOR(BYTE r, BYTE g, BYTE b) // Returns an arbitrary color value for the given index. // PIX allocates a unique color for each index. UINT PIX_COLOR_INDEX(BYTE i)
Formatted Strings
In order to minimize instrumentation overhead, the PIXBeginEvent and PIXSetMarker functions directly save their format string and format parameters instead of formatting the string at runtime. Formatting is then done when reading the capture file in PIX. Use 16-byte aligned strings (preferable) or 8-byte aligned strings to get the best performance. To print a char* or wchar_t* as a pointer using %p format specifier, cast the pointer to void* when passing it to these functions.
Other functions
PIX on Windows supports programmatic capture APIs (such as PIXBeginCapture) for GPU Captures. Please see this page for more details.
ABI Usage
Most of the implementation of PIX markers is in the header file with the DLL providing support functionality. The stable interface though is in the header file. If for some reason it is necessary to use a stable ABI then these entry points are available. These have a stronger compatability guarantee than the other WinPixEventRuntime.dll exports.
Most users should continue to use pix3.h. This will provide richer and more optimized functionality.
The source snippet below is subject to the MIT license
Use LoadLibrary to load the dll and GetProcAddress to access the exports:
typedef void(WINAPI* BeginEventOnCommandList)(ID3D12GraphicsCommandList* commandList, UINT64 color, _In_ PCSTR formatString); typedef void(WINAPI* EndEventOnCommandList)(ID3D12GraphicsCommandList* commandList); typedef void(WINAPI* SetMarkerOnCommandList)(ID3D12GraphicsCommandList* commandList, UINT64 color, _In_ PCSTR formatString); HMODULE module = LoadLibrary(L"WinPixEventRuntime.dll"); BeginEventOnCommandList pixBeginEventOnCommandList = (BeginEventOnCommandList)GetProcAddress(module, "PIXBeginEventOnCommandList"); EndEventOnCommandList pixEndEventOnCommandList = (EndEventOnCommandList)GetProcAddress(module, "PIXEndEventOnCommandList"); SetMarkerOnCommandList pixSetMarkerOnCommandList = (SetMarkerOnCommandList)GetProcAddress(module, "PIXSetMarkerOnCommandList");
Error handling and more careful resource management is left as an exercise for the reader.
Release History
- 1.0.220810001 – Support for new programmatic APIs (HUD control, 11On12). Support for BeginEventOnCommandQueue (and similar) ABIs
- 1.0.220124001 – Support for WinPixEventRuntime’s ABI (BeginEventOnCommandList etc.) in UWP.
- 1.0.210209001
- 1.0.200127001
- 1.0.190604001 – Fix compatability with old versions of PIX and the debug layer, fix building with /permissive-
- 1.0.190510001 – Add ABI exports to DLL
- 1.0.190425002 – ARM64 support
- 1.0.181206001 – Add PIXNotifyWakeFromFenceSignal
Further Reading
- Visit the DirectX Landing Page for more resources for DirectX developers.