PIX on Windows

Performance tuning and debugging for DirectX 12 games on Windows

Programmatic Capture

PIX allows applications to take and configure GPU Captures programmatically using various APIs documented here. Starting with PIX on Windows version 2303.02, Timing Captures can also be taken programmatically.

Using pix3.h

pix3.h is included in the WinPixEventRuntime, which is documented here.

 

GPU Capture APIs in pix3.h

Before using the pix3 GPU Capture APIs, you must:

    1. Install PIX onto the target PC
    2. Add WinPixEventRuntime to your application (see docs here)
    3. Define one of these preprocessor symbols in your build: USE_PIX, DBG, _DEBUG, PROFILE, or PROFILE_BUILD.
    4. Include pix3.h in your application
    5. EITHER load a copy of WinPixGpuCapturer.dll into your application’s process before calling any D3D12 APIs, such as D3D12CreateDevice
      • WinPixGpuCapturer is shipped with PIX, and not with WinPixEventRuntime.
      • pix3.h contains a helper function, PIXLoadLatestWinPixGpuCapturerLibrary(), to find the library and load it for you. See docs below for details.
      • You can also use the sample code here to manually find and load the library.
    6. OR launch your application through PIX or pixtool
      • This will inject WinPixGpuCapturer.dll into your application for you.
    7. Use APIs like PIXBeginCapture(), PIXSetTargetWindow(), etc in your application.

 

Timing Capture APIs in pix3.h

Before using the pix3 GPU Capture APIs, you must:

    1. Install PIX onto the target PC
    2. Add WinPixEventRuntime to your application (see docs here)
    3. Define one of these preprocessor symbols in your build: USE_PIX, DBG, _DEBUG, PROFILE, or PROFILE_BUILD.
    4. Include pix3.h in your application
    5. Run your application as an Administrator (i.e. “elevated”)
    6. Load a copy of WinPixTimingCapturer.dll into your application’s process
      • WinPixTimingCapturer is shipped with PIX, and not with WinPixEventRuntime.
      • pix3.h contains a helper function, PIXLoadLatestWinPixTimingCapturerLibrary(), to find the library and load it for you. See docs below for details.
    7. Use APIs like PIXBeginCapture(), etc in your application to take programmatic Timing Captures

 

Programmatic Capture API Documentation

HMODULE PIXLoadLatestWinPixGpuCapturerLibrary()

This is a helper function that will find the latest PIX installation in Program Files on the current PC and LoadLibrary() its copy of WinPixGpuCapturer.dll for you. The function’s semantics are similar to LoadLibrary(): upon success, it increments the module’s reference count and returns a non-NULL module handle. This means that FreeLibrary() needs to be called on the module before it will be unloaded. Upon failure, the function returns nullptr and a detailed error can be accessed via GetLastError().

 

HMODULE PIXLoadLatestWinPixTimingCapturerLibrary()

This is similar to PIXLoadLatestWinPixGpuCapturerLibrary, except that it loads the latest copy of WinPixTimingCapturer.dll for you. This lets you take programmatic timing captures.

 

HRESULT WINAPI PIXBeginCapture(DWORD captureFlags, _In_opt_ const PPIXCaptureParameters captureParameters)

This API immediately starts a programmatic capture and outputs it to the capture file specified in the captureParameters struct. Other parts of that struct are ignored. For compatibility with Xbox, captureFlags must be set to PIX_CAPTURE_GPU or PIX_CAPTURE_TIMING otherwise the function will return E_NOTIMPL.

For GPU Captures:

  • The capture filename specified in the captureParameters struct should use the .wpix file extension
  • You may want to wait for all pending GPU work to finish executing before calling this API, to ensure that you capture everything that you expect to capture.

For Timing Captures:

PCWSTR FileName;  // should be a path to a .wpix file
UINT32 MaximumToolingMemorySizeMb; // ignored in PIX on Windows
PIXCaptureStorage CaptureStorage; // ignored in PIX on Windows

BOOL CaptureGpuTiming;

BOOL CaptureCallstacks;
BOOL CaptureCpuSamples;
UINT32 CpuSamplesPerSecond; // If CaptureCpuSamples is TRUE then this must be 1000u, 4000, or 8000u. It's otherwise ignored.

BOOL CaptureFileIO;

BOOL CaptureVirtualAllocEvents;
BOOL CaptureHeapAllocEvents;
BOOL CaptureXMemEvents; // ignored in PIX on Windows
BOOL CapturePixMemEvents; // ignored in PIX on Windows

 

HRESULT WINAPI PIXBeginCapture2(DWORD captureFlags, _In_opt_ const PPIXCaptureParameters captureParameters)

This API is functionally equivalent to PIXBeginCapture. It exists for compatibility reasons.

 

HRESULT WINAPI PIXEndCapture(BOOL discard)

This API immediately terminates any in-progress GPU Capture or Timing Capture started via PIXBeginCapture(). PIX on Windows ignores the discard parameter.

If you’re taking a GPU Capture then you may want to wait for all pending GPU work to finish executing before calling this API, to ensure that you capture everything that you expect to capture.

 

HRESULT WINAPI PIXGpuCaptureNextFrames(PCWSTR fileName, UINT32 numFrames)

*GPU Capture only*

This API enqueues a Present-to-Present GPU capture that will begin next time a qualifying Present() call is made. This is equivalent to pressing the Print-Screen key or hitting the capture button in the PIX UI.

The filename should use the .wpix file extension.

 

HRESULT WINAPI PIXSetTargetWindow(HWND hwnd)

*GPU Capture only*

This API tells PIX which target window the application is interesting in capturing. After calling this API, PIX will only start or stop Present-to-Present GPU Captures when the application presents the target HWND. Present() calls to other HWNDs will be captured when applicable, but they will not start or stop capture.

PIXSetTargetWindow is useful in multi-window applications such as game engine editors, where PIX users typically want to capture one particular window.

 

HRESULT WINAPI PIXSetHUDOptions(PIXHUDOptions hudOptions)

*GPU Capture only*

This API is used to set different display options for the PIX overlay. Valid options are

  • PIX_HUD_SHOW_ON_ALL_WINDOWS: Overlay displayed on the top left all the windows created by the test app.
  • PIX_HUD_SHOW_ON_TARGET_WINDOW_ONLY: Overlay should only be seen on the target window (set using PIXSetTargetWindow)
  • PIX_HUD_SHOW_ON_NO_WINDOWS: Overlay should not be seen on any window created by the test app.

 

HRESULT WINAPI PIXForceD3D11on12()

*GPU Capture only*

This API allows a D3D11 app to be captured by PIX using the 11on12 mapping layer

  • Important: Call the function before a D3D11 device is created.
  • Can be used to launch and take captures of a D3D11 app (leaving the Force11on12 checkbox empty).
  • Can also be used to attach to a running D3D11 app.

 

Legacy GPU Capture APIs

GPU Captures can also be taken via the IDXGraphicsAnalysis interface. The methods on this interface will only work after launching your application through PIX/pixtool, or after attaching PIX to your application.

The interface is defined in DXProgrammableCapture.h header, included with the Windows 10 SDK.

    #include <DXProgrammableCapture.h>

Alternatively, here is the definition:

    interface DECLSPEC_UUID("9f251514-9d4d-4902-9d60-18988ab7d4b5") DECLSPEC_NOVTABLE

    IDXGraphicsAnalysis : public IUnknown

    {

        STDMETHOD_(void, BeginCapture)() PURE;

        STDMETHOD_(void, EndCapture)() PURE;

    };

IDXGraphicsAnalysis can be retrieved using DXGIGetDebugInterface1:

    ComPtr<IDXGraphicsAnalysis> ga;

    HRESULT hr = DXGIGetDebugInterface1(0, IID_PPV_ARGS(&ga));

    // hr will be E_NOINTERFACE if not attached for GPU capture

Once you have the IDXGraphicsAnalysis*, then you can call BeginCapture and EndCapture on it to control when a GPU capture is taken:

    ga->BeginCapture();

    // Perform rendering work

    // ...

    ga->EndCapture();