Skip to content

Commit a87891e

Browse files
authored
Add DxDispatch PIX timing capture command line support on windows (#617)
* add timing capture command line support on windows
1 parent 1d738f7 commit a87891e

File tree

3 files changed

+35
-10
lines changed

3 files changed

+35
-10
lines changed

DxDispatch/src/dxdispatch/CommandLineArgs.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -437,9 +437,6 @@ CommandLineArgs::CommandLineArgs(int argc, char** argv)
437437
else if (pixCaptureTypeStr == "timing")
438438
{
439439
m_pixCaptureType = PixCaptureType::ProgrammaticTiming;
440-
#ifndef _GAMING_XBOX
441-
throw std::invalid_argument("Programmatic timing captures are not supported");
442-
#endif
443440
}
444441
else if (pixCaptureTypeStr == "manual")
445442
{

DxDispatch/src/dxdispatch/PixCaptureHelper.cpp

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ PixCaptureHelper::PixCaptureHelper(PixCaptureType captureType, std::string_view
3939
{
4040
m_gpuCaptureLibrary.reset(PIXLoadLatestWinPixGpuCapturerLibrary());
4141
}
42+
else if (captureType == PixCaptureType::ProgrammaticTiming)
43+
{
44+
m_timingCaptureLibrary.reset(PIXLoadLatestWinPixTimingCapturerLibrary());
45+
}
4246
#endif
4347
}
4448

@@ -61,7 +65,9 @@ HRESULT PixCaptureHelper::BeginCapturableWork()
6165
{
6266
case PixCaptureType::ProgrammaticTiming:
6367
{
64-
#ifdef _GAMING_XBOX
68+
#if defined(PIX_NONE)
69+
return E_NOTIMPL;
70+
#elif defined(_GAMING_XBOX)
6571
auto captureName = m_captureName + L".pevt";
6672
PIXCaptureParameters captureParams = {};
6773
captureParams.TimingCaptureParameters.CaptureGpuTiming = TRUE;
@@ -73,8 +79,26 @@ HRESULT PixCaptureHelper::BeginCapturableWork()
7379
captureParams.TimingCaptureParameters.MaximumToolingMemorySizeMb = 4096;
7480
return PIXBeginCapture(PIX_CAPTURE_TIMING, &captureParams);
7581
#else
76-
// There is currently no programmatic API for timing captures on Windows.
77-
return E_NOTIMPL;
82+
if (!m_timingCaptureLibrary)
83+
{
84+
throw std::runtime_error("The WinPix Timing capturer library was not found. Ensure that PIX version 2303.02 or later is installed.");
85+
}
86+
auto captureName = m_captureName + L".wpix";
87+
88+
PIXCaptureParameters captureParams = {};
89+
captureParams.TimingCaptureParameters.FileName = captureName.c_str();
90+
captureParams.TimingCaptureParameters.CaptureGpuTiming = TRUE;
91+
captureParams.TimingCaptureParameters.CaptureCallstacks = TRUE;
92+
captureParams.TimingCaptureParameters.CaptureCpuSamples = TRUE;
93+
captureParams.TimingCaptureParameters.CpuSamplesPerSecond = 4000;
94+
captureParams.TimingCaptureParameters.CaptureStorage = PIXCaptureParameters::Memory;
95+
captureParams.TimingCaptureParameters.MaximumToolingMemorySizeMb = 4096;
96+
HRESULT hr = PIXBeginCapture(PIX_CAPTURE_TIMING, &captureParams);
97+
if (hr == E_ACCESSDENIED)
98+
{
99+
throw std::runtime_error("E_ACCESSDENIED while attempting to begin PIX timing capture. Timing capture requires elevated privileges.");
100+
}
101+
return hr;
78102
#endif
79103
}
80104

@@ -95,7 +119,7 @@ HRESULT PixCaptureHelper::BeginCapturableWork()
95119

96120
// PIXBeginCapture can only be used for GPU captures on Windows.
97121
PIXCaptureParameters captureParams = {};
98-
captureParams.TimingCaptureParameters.FileName = captureName.c_str();
122+
captureParams.GpuCaptureParameters.FileName = captureName.c_str();
99123
return PIXBeginCapture(PIX_CAPTURE_GPU, &captureParams);
100124
#endif
101125
}
@@ -124,7 +148,9 @@ HRESULT PixCaptureHelper::EndCapturableWork()
124148
{
125149
case PixCaptureType::ProgrammaticTiming:
126150
{
127-
#if defined(_GAMING_XBOX)
151+
#if defined(PIX_NONE)
152+
return E_NOTIMPL;
153+
#elif defined(_GAMING_XBOX)
128154
HRESULT hr;
129155
do
130156
{
@@ -137,8 +163,9 @@ HRESULT PixCaptureHelper::EndCapturableWork()
137163

138164
return hr;
139165
#else
140-
// There is currently no programmatic API for timing captures on Windows.
141-
return E_NOTIMPL;
166+
// PIX on Windows ignores the discard parameter, and will flush internally,
167+
// no need for the loop xbox needs above.
168+
return PIXEndCapture(/*discard*/FALSE);
142169
#endif
143170
}
144171

DxDispatch/src/dxdispatch/PixCaptureHelper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class PixCaptureHelper
3535
Microsoft::WRL::ComPtr<ID3D12CommandQueue> m_commandQueue;
3636
#if !defined(_GAMING_XBOX) && !defined(PIX_NONE)
3737
wil::unique_hmodule m_gpuCaptureLibrary;
38+
wil::unique_hmodule m_timingCaptureLibrary;
3839
Microsoft::WRL::ComPtr<ID3D12SharingContract> m_sharingContract;
3940
#endif
4041
};

0 commit comments

Comments
 (0)