Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion IntelPresentMon/CommonUtilities/mc/MetricsCalculatorDisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,15 @@ namespace pmon::util::metrics
return std::nullopt;
}


std::pair<uint32_t, uint32_t> GetDisplayId(const FrameData& present)
{
auto vidPnSourceId = uint32_t(present.vidPnLayerId >> 32); // vidPnSourceId
auto layerIndex = uint32_t(present.vidPnLayerId & 0xFFFFFFFF); // layerIndex
if (vidPnSourceId != 0 || layerIndex != 0) {
return {vidPnSourceId, layerIndex};
}
return {0, 0};
}
}

// ---- NV collapsed/runt correction ----
Expand Down Expand Up @@ -202,5 +210,7 @@ namespace pmon::util::metrics
metrics.msReadyTimeToDisplayLatency = ComputeMsReadyTimeToDisplayLatency(qpc, present, isDisplayed, screenTime);
metrics.isDroppedFrame = !isDisplayed;
metrics.screenTimeQpc = screenTime;
metrics.displayId = GetDisplayId(present);
metrics.presentId = present.presentId;
}
}
9 changes: 9 additions & 0 deletions IntelPresentMon/CommonUtilities/mc/MetricsTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ namespace pmon::util::metrics {

frame.runtime = p.Runtime;
frame.presentMode = p.PresentMode;

frame.presentStartTime = p.PresentStartTime;
frame.readyTime = p.ReadyTime;
frame.timeInPresent = p.TimeInPresent;
Expand Down Expand Up @@ -67,6 +68,14 @@ namespace pmon::util::metrics {
frame.appFrameId = p.AppFrameId;
frame.pclFrameId = p.PclFrameId;

// Extract VidPnSourceId and layer index from PresentIds if available for display identification
if (!p.ReportedPresentIds.empty()) {
auto presentIdEntry = p.ReportedPresentIds.begin();
// VidPnSourceId and Layer Index are encoded in the key
frame.vidPnLayerId = presentIdEntry->first;
frame.presentId = presentIdEntry->second;
}

return frame;
}
}
9 changes: 7 additions & 2 deletions IntelPresentMon/CommonUtilities/mc/MetricsTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ namespace pmon::util::metrics {
int32_t syncInterval = 0;
uint32_t presentFlags = 0;

uint64_t vidPnLayerId = 0;
uint64_t presentId = 0;

// Metadata
PresentResult finalState = {};
bool supportsTearing = 0;
Expand Down Expand Up @@ -113,8 +116,10 @@ namespace pmon::util::metrics {
double msUntilDisplayed = 0;
double msBetweenDisplayChange = 0;
uint64_t screenTimeQpc = 0;
std::optional<double> msReadyTimeToDisplayLatency;
std::optional<double> msReadyTimeToDisplayLatency = {};
bool isDroppedFrame = false;
std::pair<uint32_t, uint32_t> displayId = {}; // {vidPnSourceId, layerIndex}
uint64_t presentId = 0;

// CPU Metrics (app frames only)
double msCPUBusy = 0;
Expand All @@ -131,7 +136,7 @@ namespace pmon::util::metrics {
// Input Latency (optional, app+displayed only)
std::optional<double> msClickToPhotonLatency = {};
std::optional<double> msAllInputPhotonLatency = {};
std::optional<double> msInstrumentedInputTime;
std::optional<double> msInstrumentedInputTime = {};

// Animation (optional, app+displayed only)
std::optional<double> msAnimationError = {};
Expand Down
7 changes: 5 additions & 2 deletions PresentData/PresentMonTraceConsumer.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2017-2024 Intel Corporation
// Copyright (C) 2017-2024 Intel Corporation
// Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved
// SPDX-License-Identifier: MIT

Expand Down Expand Up @@ -1394,7 +1394,10 @@ void PMTraceConsumer::HandleDXGKEvent(EVENT_RECORD* pEventRecord)
// the present ids to it.
if (present != nullptr) {
VerboseTraceBeforeModifyingPresent(present.get());
present->PresentIds.emplace(vidPnLayerId, PresentId[i]);
auto inserted = present->PresentIds.emplace(vidPnLayerId, PresentId[i]);
if (inserted.second) {
present->ReportedPresentIds.push_back({ vidPnLayerId, PresentId[i] });
}
mPresentByVidPnLayerId.emplace(vidPnLayerId, present);
}

Expand Down
3 changes: 2 additions & 1 deletion PresentData/PresentMonTraceConsumer.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2017-2024 Intel Corporation
// Copyright (C) 2017-2024 Intel Corporation
// Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved
// SPDX-License-Identifier: MIT
#pragma once
Expand Down Expand Up @@ -220,6 +220,7 @@ struct PresentEvent {
uint32_t QueueSubmitSequence; // mPresentBySubmitSequence
uint32_t RingIndex; // mTrackedPresents and mCompletedPresents
std::unordered_map<uint64_t, uint64_t> PresentIds; // mPresentByVidPnLayerId
std::vector<std::pair<uint64_t, uint64_t>> ReportedPresentIds;
// Note: the following index tracking structures as well but are defined elsewhere:
// ProcessId -> mOrderedPresentsByProcessId
// ThreadId, DriverThreadId -> mPresentByThreadId
Expand Down
14 changes: 12 additions & 2 deletions PresentMon/CommandLine.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2017-2024 Intel Corporation
// Copyright (C) 2017-2024 Intel Corporation
// SPDX-License-Identifier: MIT

#include <generated/version.h>
Expand Down Expand Up @@ -275,6 +275,7 @@ void PrintUsage()
LR"(--exclude_dropped)", LR"(Exclude frames that were not displayed to the screen from the CSV output.)",
LR"(--v1_metrics)", LR"(Output a CSV using PresentMon 1.x metrics.)",
LR"(--v2_metrics)", LR"(Output a CSV using PresentMon 2.x metrics.)",
LR"(--write_display_metadata)", LR"(Write VidPnSourceId, LayerIndex, and PresentId columns to CSV output.)",

LR"(--Recording Options)", nullptr,
LR"(--hotkey key)", LR"(Use the specified key press to start and stop recording. 'key' is of the form MODIFIER+KEY, e.g., "ALT+SHIFT+F11".)",
Expand Down Expand Up @@ -408,6 +409,7 @@ bool ParseCommandLine(int argc, wchar_t** argv)
args->mUseV1Metrics = false;
args->mUseV2Metrics = false;
args->mStopExistingSession = false;
args->mWriteDisplayMetadata = false;
args->mWriteFrameId = false;
args->mWriteDisplayTime = false;
args->mDisableOfflineBackpressure = false;
Expand Down Expand Up @@ -446,6 +448,7 @@ bool ParseCommandLine(int argc, wchar_t** argv)
else if (ParseArg(argv[i], L"exclude_dropped")) { args->mExcludeDropped = true; continue; }
else if (ParseArg(argv[i], L"v1_metrics")) { args->mUseV1Metrics = true; continue; }
else if (ParseArg(argv[i], L"v2_metrics")) { args->mUseV2Metrics = true; continue; }
else if (ParseArg(argv[i], L"write_display_metadata")) { args->mWriteDisplayMetadata = true; continue; }

// Recording options:
else if (ParseArg(argv[i], L"hotkey")) { if (ParseValue(argv, argc, &i) && AssignHotkey(argv[i], args)) continue; }
Expand Down Expand Up @@ -536,13 +539,14 @@ bool ParseCommandLine(int argc, wchar_t** argv)
}

// Ignore CSV-only options when --no_csv is used
if (csvOutputNone && (qpcTime || qpcmsTime || dtTime || args->mMultiCsv || args->mHotkeySupport)) {
if (csvOutputNone && (qpcTime || qpcmsTime || dtTime || args->mMultiCsv || args->mHotkeySupport || args->mWriteDisplayMetadata)) {
PrintWarning(L"warning: ignoring CSV-related options due to --no_csv:");
if (qpcTime) { qpcTime = false; PrintWarning(L" --qpc_time"); }
if (qpcmsTime) { qpcmsTime = false; PrintWarning(L" --qpc_time_ms"); }
if (dtTime) { dtTime = false; PrintWarning(L" --date_time"); }
if (args->mMultiCsv) { args->mMultiCsv = false; PrintWarning(L" --multi_csv"); }
if (args->mHotkeySupport) { args->mHotkeySupport = false; PrintWarning(L" --hotkey"); }
if (args->mWriteDisplayMetadata) { args->mWriteDisplayMetadata = false; PrintWarning(L" --write_display_metadata"); }
PrintWarning(L"\n");
}

Expand Down Expand Up @@ -590,6 +594,12 @@ bool ParseCommandLine(int argc, wchar_t** argv)
PrintWarning(L"warning: ignoring --v1_metrics due to --v2_metrics.\n");
args->mUseV1Metrics = false;
}

if (args->mUseV1Metrics && args->mWriteDisplayMetadata) {
PrintWarning(L"warning: ignoring --write_display_metadata due to --v1_metrics.\n");
args->mWriteDisplayMetadata = false;
}

// Enable verbose trace if requested, and disable Full or Simple console output
#if PRESENTMON_ENABLE_DEBUG_TRACE
if (verboseTrace) {
Expand Down
21 changes: 20 additions & 1 deletion PresentMon/CsvOutput.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2017-2024 Intel Corporation
// Copyright (C) 2017-2024 Intel Corporation
// Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved
// SPDX-License-Identifier: MIT

Expand Down Expand Up @@ -519,6 +519,10 @@ void WriteCsvHeader<pmon::util::metrics::FrameMetrics>(FILE* fp)
L",PresentRuntime"
L",SyncInterval"
L",PresentFlags");
if (args.mWriteDisplayMetadata) {
fwprintf(fp, L",VidPnSourceId"
L",LayerIndex");
}
if (args.mTrackDisplay) {
fwprintf(fp, L",AllowsTearing"
L",PresentMode");
Expand Down Expand Up @@ -629,6 +633,11 @@ void WriteCsvHeader<pmon::util::metrics::FrameMetrics>(FILE* fp)
}
if (args.mWriteFrameId) {
fwprintf(fp, L",FrameId");
}
if (args.mWriteDisplayMetadata) {
fwprintf(fp, L",PresentId");
}
if (args.mWriteFrameId) {
if (args.mTrackAppTiming) {
fwprintf(fp, L",AppFrameId");
}
Expand Down Expand Up @@ -1098,6 +1107,11 @@ void WriteCsvRow<pmon::util::metrics::FrameMetrics>(
RuntimeToString(p.runtime),
p.syncInterval,
p.presentFlags);
if (args.mWriteDisplayMetadata) {
fwprintf(fp, L",%u,%u",
metrics.displayId.first,
metrics.displayId.second);
}
if (args.mTrackDisplay) {
fwprintf(fp, L",%d,%hs", p.supportsTearing,
PresentModeToString(p.presentMode));
Expand Down Expand Up @@ -1290,6 +1304,11 @@ void WriteCsvRow<pmon::util::metrics::FrameMetrics>(
}
if (args.mWriteFrameId) {
fwprintf(fp, L",%u", p.frameId);
}
if (args.mWriteDisplayMetadata) {
fwprintf(fp, L",%llu", metrics.presentId);
}
if (args.mWriteFrameId) {
if (args.mTrackAppTiming) {
fwprintf(fp, L",%u", p.appFrameId);
}
Expand Down
3 changes: 2 additions & 1 deletion PresentMon/PresentMon.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2017-2024 Intel Corporation
// Copyright (C) 2017-2024 Intel Corporation
// Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved
// SPDX-License-Identifier: MIT

Expand Down Expand Up @@ -107,6 +107,7 @@ struct CommandLineArgs {
bool mUseV1Metrics;
bool mUseV2Metrics;
bool mStopExistingSession;
bool mWriteDisplayMetadata;
bool mWriteFrameId;
bool mWriteDisplayTime;
bool mDisableOfflineBackpressure;
Expand Down
7 changes: 6 additions & 1 deletion README-ConsoleApplication.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# PresentMon Console Application
# PresentMon Console Application

The PresentMon/ directory contains source for a standalone console application that uses the
*PresentMon SDK* to capture and analyze graphics applications, outputting data to the console and/or
Expand Down Expand Up @@ -29,6 +29,7 @@ A binary of the console application is provided in the release, e.g.:
| `--exclude_dropped` | Exclude frames that were not displayed to the screen from the CSV output. |
| `--v1_metrics` | Output a CSV using PresentMon 1.x metrics. |
| `--v2_metrics` | Output a CSV using PresentMon 2.x metrics. |
| `--write_display_metadata` | Write VidPnSourceId, LayerIndex, and PresentId columns to CSV output. |

| Recording Options | |
| ------------------------------ | --- |
Expand Down Expand Up @@ -85,6 +86,8 @@ Default metrics include:
| *Application* | The name of the process that generated the frame. |
| *ProcessID* | The process ID of the process that generated the frame. |
| *SwapChainAddress* | The address of the swap chain used to present the frame. |
| *VidPnSourceId* | The display source identifier associated with the reported present. This column is written when `--write_display_metadata` is used. |
| *LayerIndex* | The display layer index associated with the reported present. This column is written when `--write_display_metadata` is used. |
| *PresentRuntime* | The API used to present the frame. |
| *SyncInterval* | The sync interval provided by the application when presenting the frame. Note: this value may be modified later by the driver, e.g., based on control panel overrides. |
| *PresentFlags* | The present flags provided by the application when presenting the frame. |
Expand Down Expand Up @@ -114,13 +117,15 @@ Default metrics include:
| *MsBetweenSimulationStart* | The time between the start of simulation processing of the previous frame and this one, in milliseconds. |
| *MsPCLatency* | Time between PC receiving input and frame being sent to the display, in milliseconds. |
| *MsBetweenAppStart* | How long it took from the start of this frame until the CPU started working on the next frame, in milliseconds. |
| *PresentId* | The present identifier associated with the reported VidPnSourceId and LayerIndex pair. This column is written when `--write_display_metadata` is used. |

Some metrics are enabled or disabled depending on the command line options:

| Command line option | Enabled metrics | Disabled metrics |
| -------------------- | --------------- | ---------------- |
| `--track_frame_type` | *FrameType* | |
| `--track_gpu_video` | *VideoBusy* | |
| `--write_display_metadata` | *VidPnSourceId<br>LayerIndex<br>PresentId* | |
| `--no_track_gpu` | | *GPULatency<br>GPUBusy<br>GPUWait<br>VideoBusy* |
| `--no_track_input` | | *ClickToPhotonLatency* |
| `--no_track_display`<br>(requires `--no_track_gpu` and `--no_track_input` as well) | | *AllowsTearing<br>PresentMode<br>DisplayLatency<br>DisplayedTime* |
Expand Down