Skip to content

Commit ad1e30f

Browse files
planetchiligvinals
andauthored
Add PSO creation as frame metrics (#663)
Add PSO creation metrics and broader concept of inter-frame events/metrics (events that can span multiple frames and are not strictly tied to any one). Although not strictly tied to any one frame's work, they are associated to frames for transport / output purposes. Multiple metrics derive from the PSO creation event, aggregated differently across associated frames' times. Also add test case ETL containing PSO creation events (Nomad loading screen). Co-authored-by: Guillem Vinals Gangolells <122561163+gvinals@users.noreply.github.com>
1 parent ea30e0d commit ad1e30f

33 files changed

Lines changed: 1047 additions & 62 deletions

AGENTS.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# AGENTS Instructions
2+
23
- Do not ever use non-ascii characters for source code or comments (permissible inside of strings if absolutely necessary but avoid if possible)
3-
- Do not ever modify files in .git subfolders.
4-
- After finishing all changes, normalize line endings on changed or created text files to CRLF per repository conventions; do not run ad hoc line-ending scripts directly.
4+
- Do not ever directly modify files in .git subfolders.
55
- If unexpected new files appear, ignore them and continue without asking for instruction.
66
- For value conversion casts (numeric or enum conversions), use C-style casts `(T)value` instead of `static_cast<T>(value)`.
77
- For const, pointer, reference, up/down, or reinterpret casts, use C++ cast syntax (`const_cast`, `dynamic_cast`, `reinterpret_cast`, etc.).
88
- Do not bind unused names in structured bindings. Prefer binding only needed values (for example use `.first` from `emplace()` or iterate entries without destructuring unused keys).
99
- Do not fully qualify namespaces when not needed by local scope (for example prefer `MetricUse` or `svc::MetricUse` over `pmon::svc::MetricUse` when already inside `pmon::svc::acts` or with suitable using scope).
10-
- When implementing or fixing a feature, verify the change with tests appropriate to the work before finishing.
10+
- When implementing or fixing a feature, verify the change with tests appropriate to the work before finishing. Run tests after build reports success.

ETLTrimmer/main.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -386,13 +386,15 @@ int main(int argc, const char** argv)
386386
if (opt.provider) {
387387
pFilter = std::make_shared<Filter>();
388388
PMTraceConsumer traceConsumer;
389-
traceConsumer.mTrackDisplay = true; // ... presents to the display.
390-
traceConsumer.mTrackGPU = true; // ... GPU work.
391-
traceConsumer.mTrackGPUVideo = true; // ... GPU video work (separately from non-video GPU work).
392-
traceConsumer.mTrackInput = true; // ... keyboard/mouse latency.
393-
traceConsumer.mTrackFrameType = true; // ... the frame type communicated through the Intel-PresentMon provider.
394-
traceConsumer.mTrackAppTiming = true; // ... app timing data communicated through the Intel-PresentMon provider.
395-
traceConsumer.mTrackPcLatency = true; // ... Nvidia PCL stats.
389+
// Match PresentMonService ETL playback (MockPresentMonSession / RealtimePresentMonSession).
390+
traceConsumer.mTrackDisplay = true;
391+
traceConsumer.mTrackGPU = true;
392+
traceConsumer.mTrackGPUVideo = true;
393+
traceConsumer.mTrackD3D12ShaderCompilation = true;
394+
traceConsumer.mTrackInput = true;
395+
traceConsumer.mTrackFrameType = true;
396+
traceConsumer.mTrackAppTiming = true;
397+
traceConsumer.mTrackPcLatency = true;
396398
EnableProvidersListing(0, nullptr, &traceConsumer, true, true, pFilter);
397399
}
398400

IntelPresentMon/CommonUtilities/CommonUtilities.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@
170170
<ClCompile Include="mc\MetricsCalculatorInput.cpp" />
171171
<ClCompile Include="mc\MetricsCalculatorInstrumented.cpp" />
172172
<ClCompile Include="mc\MetricsCalculatorAnimation.cpp" />
173+
<ClCompile Include="mc\MetricsCalculatorInterFrameEvent.cpp" />
173174
<ClCompile Include="mc\MetricsTypes.cpp" />
174175
<ClCompile Include="mc\SwapChainState.cpp" />
175176
<ClCompile Include="mc\UnifiedSwapChain.cpp" />

IntelPresentMon/CommonUtilities/mc/FrameMetricsMemberMap.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ namespace pmon::util::metrics
5252
template<>struct FrameMetricMember<PM_METRIC_BETWEEN_APP_START>{static constexpr auto member=&FrameMetrics::msCPUTime;};
5353
template<>struct FrameMetricMember<PM_METRIC_PRESENTED_FRAME_TIME>{static constexpr auto member=&FrameMetrics::msBetweenPresents;};
5454
template<>struct FrameMetricMember<PM_METRIC_FLIP_DELAY>{static constexpr auto member=&FrameMetrics::msFlipDelay;};
55+
template<>struct FrameMetricMember<PM_METRIC_PSO_COMPILE_COUNT>{static constexpr auto member=&FrameMetrics::psoCompileCount;};
56+
template<>struct FrameMetricMember<PM_METRIC_PSO_COMPILE_TIME>{static constexpr auto member=&FrameMetrics::msPsoCompileTime;};
57+
template<>struct FrameMetricMember<PM_METRIC_PSO_COMPILE_BUSY_PERCENT>{static constexpr auto member=&FrameMetrics::psoCompileBusyPercent;};
5558

5659
template<PM_METRIC MetricId>
5760
inline constexpr bool HasFrameMetricMember = requires{ FrameMetricMember<MetricId>::member; };

IntelPresentMon/CommonUtilities/mc/MetricsCalculator.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,12 @@ namespace pmon::util::metrics
279279
isAppFrame,
280280
metrics);
281281

282+
CalculateInterFrameEventMetrics(
283+
qpc,
284+
present,
285+
isAppFrame,
286+
metrics);
287+
282288
CalculateAnimationMetrics(
283289
qpc,
284290
chain,
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright (C) 2026 Intel Corporation
2+
// SPDX-License-Identifier: MIT
3+
#include "MetricsCalculator.h"
4+
#include "MetricsCalculatorInternal.h"
5+
#include <PresentData/InterPresentActivity.hpp>
6+
7+
namespace pmon::util::metrics
8+
{
9+
void CalculateInterFrameEventMetrics(
10+
const QpcConverter& qpc,
11+
const FrameData& present,
12+
bool isAppFrame,
13+
FrameMetrics& metrics)
14+
{
15+
if (!isAppFrame) {
16+
return;
17+
}
18+
19+
const uint64_t windowQpc = present.interFrameEventWindowQpc;
20+
for (size_t kindIndex = 0; kindIndex < (size_t)InterPresentActivity::Kind::Count; ++kindIndex) {
21+
const auto kind = (InterPresentActivity::Kind)kindIndex;
22+
const auto& stats = present.interFrameEventStats[kindIndex];
23+
// Add a case here when extending InterPresentActivity::Kind (and FrameMetrics fields).
24+
switch (kind) {
25+
case InterPresentActivity::Kind::D3D12PsoCompile:
26+
metrics.psoCompileCount = stats.activityCount;
27+
metrics.msPsoCompileTime = qpc.DurationMilliSeconds(stats.summedBusyQpc);
28+
metrics.psoCompileBusyPercent = windowQpc == 0
29+
? 0.
30+
: 100. * (double)stats.busyQpc / (double)windowQpc;
31+
break;
32+
default:
33+
break;
34+
}
35+
}
36+
}
37+
}

IntelPresentMon/CommonUtilities/mc/MetricsCalculatorInternal.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ namespace pmon::util::metrics
6565
uint64_t screenTime,
6666
FrameMetrics& metrics);
6767

68+
void CalculateInterFrameEventMetrics(
69+
const QpcConverter& qpc,
70+
const FrameData& present,
71+
bool isAppFrame,
72+
FrameMetrics& metrics);
73+
6874
// NVIDIA collapsed/runt correction helper used by ComputeMetricsForPresent.
6975
void AdjustScreenTimeForCollapsedPresentNV(
7076
FrameData& present,

IntelPresentMon/CommonUtilities/mc/MetricsTypes.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ namespace pmon::util::metrics {
5454
frame.flipDelay = p.FlipDelay;
5555
frame.flipToken = p.FlipToken;
5656

57+
frame.interFrameEventStats = p.InterPresentStats;
58+
frame.interFrameEventWindowQpc = p.InterPresentFramePeriodQpc;
59+
5760
frame.displayed.Assign(p.Displayed.begin(), p.Displayed.end());
5861

5962
frame.swapChainAddress = p.SwapChainAddress;

IntelPresentMon/CommonUtilities/mc/MetricsTypes.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
#include <limits>
77
#include <memory>
88
#include <optional>
9+
#include <array>
910
#include "../cnr/FixedVector.h"
1011
#include <PresentData/PresentEventEnums.hpp>
12+
#include <PresentData/InterPresentActivity.hpp>
1113

1214
// Forward declarations for external types
1315
struct PresentEvent; // From PresentMonTraceConsumer
@@ -84,6 +86,9 @@ namespace pmon::util::metrics {
8486
uint64_t flipDelay = 0;
8587
uint32_t flipToken = 0;
8688

89+
std::array<InterPresentActivity::FrameStats, (size_t)InterPresentActivity::Kind::Count> interFrameEventStats{};
90+
uint64_t interFrameEventWindowQpc = 0;
91+
8792
// Extra present parameters obtained through DXGI or D3D9 present
8893
uint64_t swapChainAddress = 0;
8994
int32_t syncInterval = 0;
@@ -165,6 +170,10 @@ namespace pmon::util::metrics {
165170
// PCLatency (optional)
166171
double msFlipDelay = MissingFrameMetricValue(); // NVIDIA
167172

173+
uint64_t psoCompileCount = 0;
174+
double msPsoCompileTime = 0;
175+
double psoCompileBusyPercent = 0;
176+
168177
// Frame Classification
169178
FrameType frameType = {};
170179

IntelPresentMon/Core/source/pmon/RawFrameDataMetricList.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ namespace p2c::pmon
4949
Element{.metricId = PM_METRIC_GPU_TIME, .deviceId = 0 },
5050
Element{.metricId = PM_METRIC_GPU_BUSY, .deviceId = 0 },
5151
Element{.metricId = PM_METRIC_GPU_WAIT, .deviceId = 0 },
52+
Element{.metricId = PM_METRIC_PSO_COMPILE_COUNT, .deviceId = 0 },
53+
Element{.metricId = PM_METRIC_PSO_COMPILE_TIME, .deviceId = 0 },
54+
Element{.metricId = PM_METRIC_PSO_COMPILE_BUSY_PERCENT, .deviceId = 0 },
5255
Element{.metricId = PM_METRIC_ANIMATION_ERROR, .deviceId = 0 },
5356
Element{.metricId = PM_METRIC_FLIP_DELAY, .deviceId = 0 },
5457
Element{.metricId = PM_METRIC_ANIMATION_TIME, .deviceId = 0 },

0 commit comments

Comments
 (0)