From 77cbec371afae3aefe5f0e39e2aa6eae11947fd9 Mon Sep 17 00:00:00 2001 From: "Galvan, Mark" Date: Wed, 3 Jun 2026 15:02:37 -0700 Subject: [PATCH 1/4] Updated Present attach method for non-PCL app provider events. --- PresentData/PresentMonTraceConsumer.cpp | 56 ++++++++++++++++++------- PresentData/PresentMonTraceConsumer.hpp | 4 +- 2 files changed, 43 insertions(+), 17 deletions(-) diff --git a/PresentData/PresentMonTraceConsumer.cpp b/PresentData/PresentMonTraceConsumer.cpp index a48db047..028d67a9 100644 --- a/PresentData/PresentMonTraceConsumer.cpp +++ b/PresentData/PresentMonTraceConsumer.cpp @@ -2235,6 +2235,7 @@ void PMTraceConsumer::CompletePresent(std::shared_ptr const& p) p->ProcessId, 0, p->PresentStartTime, + p->PresentStartTime + p->TimeInPresent, [this](const AppTimingData& d) { if (mUsingOutOfBoundPresentStart) { return d.PclOutOfBandPresentStartTime; @@ -2637,6 +2638,7 @@ void PMTraceConsumer::RuntimePresentStop(Runtime runtime, EVENT_HEADER const& hd return; } auto present = eventIter->second; + auto PresentStopTime = *(uint64_t*)&hdr.TimeStamp; if (mTrackAppTiming) { if (IsApplicationPresent(present)) { @@ -2645,7 +2647,9 @@ void PMTraceConsumer::RuntimePresentStop(Runtime runtime, EVENT_HEADER const& hd present->ProcessId, present->AppFrameId, present->PresentStartTime, - [](const AppTimingData& d) { return d.AppPresentStartTime; }); + PresentStopTime, + [](const AppTimingData& d) { return d.AppPresentStartTime; }, + false); if (appTimingData) { if (present->ProcessId == appTimingData->ProcessId) { if (present->AppFrameId == 0) { @@ -2683,7 +2687,7 @@ void PMTraceConsumer::RuntimePresentStop(Runtime runtime, EVENT_HEADER const& hd // Set the runtime and Present_Stop time. VerboseTraceBeforeModifyingPresent(present.get()); present->Runtime = runtime; - present->TimeInPresent = *(uint64_t*) &hdr.TimeStamp - present->PresentStartTime; + present->TimeInPresent = PresentStopTime - present->PresentStartTime; // If this present completed early and was deferred until the Present_Stop, then no more // analysis is needed; we just clear the deferral. @@ -3669,7 +3673,8 @@ PMTraceConsumer::EventProcessingScope::~EventProcessingScope() AppTimingData* PMTraceConsumer::ExtractAppTimingData( std::unordered_map, AppTimingData, PairHash>& timingDataByFrameId, - uint32_t processId, uint32_t appFrameId, uint64_t presentStartTime, std::function timingSelector) { + uint32_t processId, uint32_t appFrameId, uint64_t presentStartTime, uint64_t presentStopTime, std::function timingSelector, + bool isPcLatency) { if (appFrameId != 0) { // If the incoming app frame id is already assigned then we receiving // the information from version 2 of the PresentFrameType event. @@ -3682,19 +3687,38 @@ AppTimingData* PMTraceConsumer::ExtractAppTimingData( } } else { auto itToReturn = timingDataByFrameId.end(); - uint32_t earlierFrameId = std::numeric_limits::max(); - uint64_t smallestPresentStartDelta = std::numeric_limits::max(); - // Search for the timing data with the closest PresentStartTime to the passed - // in PresentStartTime that has not been assigned. This is a hack and will not work for x-platform. - for (auto it = timingDataByFrameId.begin(); it != timingDataByFrameId.end(); ++it) { - if (it->first.second == processId) { - if (it->second.AssignedToPresent == false) { - uint64_t timingValue = timingSelector(it->second); - if (timingValue != 0 && timingValue < presentStartTime) { - auto tempPresentStartDelta = presentStartTime - timingValue; - if (tempPresentStartDelta < smallestPresentStartDelta) { - smallestPresentStartDelta = tempPresentStartDelta; - earlierFrameId = it->first.first; + if (isPcLatency) { + // For PC latency we want to match the app timing data to the present based + uint64_t smallestPresentStartDelta = std::numeric_limits::max(); + // Search for the timing data with the closest PresentStartTime to the passed + // in PresentStartTime that has not been assigned. This is a hack and will not work for x-platform. + for (auto it = timingDataByFrameId.begin(); it != timingDataByFrameId.end(); ++it) { + if (it->first.second == processId) { + if (it->second.AssignedToPresent == false) { + uint64_t timingValue = timingSelector(it->second); + if (timingValue != 0 && timingValue < presentStartTime) { + auto tempPresentStartDelta = presentStartTime - timingValue; + if (tempPresentStartDelta < smallestPresentStartDelta) { + smallestPresentStartDelta = tempPresentStartDelta; + itToReturn = it; + } + } + } + } + } + } else { + // For non-PC latency metrics we match unassigned timing data whose selected time falls + // between present start and stop. If more than one qualifies, use the earliest. + uint64_t earliestTimingValueInWindow = std::numeric_limits::max(); + for (auto it = timingDataByFrameId.begin(); it != timingDataByFrameId.end(); ++it) { + if (it->first.second == processId) { + if (it->second.AssignedToPresent == false) { + uint64_t timingValue = timingSelector(it->second); + if (timingValue != 0 + && presentStartTime <= timingValue + && timingValue <= presentStopTime + && timingValue < earliestTimingValueInWindow) { + earliestTimingValueInWindow = timingValue; itToReturn = it; } } diff --git a/PresentData/PresentMonTraceConsumer.hpp b/PresentData/PresentMonTraceConsumer.hpp index 3af78068..034a07cf 100644 --- a/PresentData/PresentMonTraceConsumer.hpp +++ b/PresentData/PresentMonTraceConsumer.hpp @@ -611,7 +611,9 @@ struct PMTraceConsumer // ------------------------------------------------------------------------------------------- // Function for managing app provided events - AppTimingData* ExtractAppTimingData(std::unordered_map, AppTimingData, PairHash>& timingDataByFrameId, uint32_t processId, uint32_t appFrameId, uint64_t presentStartTime, std::function timingSelector); + AppTimingData* ExtractAppTimingData(std::unordered_map, AppTimingData, PairHash>& timingDataByFrameId, + uint32_t processId, uint32_t appFrameId, uint64_t presentStartTime, uint64_t presentStopTime, + std::function timingSelector, bool isPcLatency = true); bool IsApplicationPresent(std::shared_ptr const& present); void SetAppTimingDataAsComplete(uint32_t processId, uint32_t appFrameId); From 9a283f0aa03daa2a449ef23ab3aacf20234c27d1 Mon Sep 17 00:00:00 2001 From: markgalvan-intel Date: Fri, 5 Jun 2026 08:36:37 -0700 Subject: [PATCH 2/4] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- PresentData/PresentMonTraceConsumer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PresentData/PresentMonTraceConsumer.cpp b/PresentData/PresentMonTraceConsumer.cpp index 028d67a9..a8944133 100644 --- a/PresentData/PresentMonTraceConsumer.cpp +++ b/PresentData/PresentMonTraceConsumer.cpp @@ -2638,7 +2638,7 @@ void PMTraceConsumer::RuntimePresentStop(Runtime runtime, EVENT_HEADER const& hd return; } auto present = eventIter->second; - auto PresentStopTime = *(uint64_t*)&hdr.TimeStamp; + auto PresentStopTime = static_cast(hdr.TimeStamp.QuadPart); if (mTrackAppTiming) { if (IsApplicationPresent(present)) { From 1ecf349992981ddf6d28f085c4a2038b18f2d339 Mon Sep 17 00:00:00 2001 From: markgalvan-intel Date: Fri, 5 Jun 2026 08:37:03 -0700 Subject: [PATCH 3/4] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- PresentData/PresentMonTraceConsumer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PresentData/PresentMonTraceConsumer.cpp b/PresentData/PresentMonTraceConsumer.cpp index a8944133..44d1eaa6 100644 --- a/PresentData/PresentMonTraceConsumer.cpp +++ b/PresentData/PresentMonTraceConsumer.cpp @@ -3688,7 +3688,7 @@ AppTimingData* PMTraceConsumer::ExtractAppTimingData( } else { auto itToReturn = timingDataByFrameId.end(); if (isPcLatency) { - // For PC latency we want to match the app timing data to the present based + // For PC latency we match the app timing data to the present by selecting the unassigned entry whose selected time is closest to (but earlier than) PresentStartTime. uint64_t smallestPresentStartDelta = std::numeric_limits::max(); // Search for the timing data with the closest PresentStartTime to the passed // in PresentStartTime that has not been assigned. This is a hack and will not work for x-platform. From 43da558a93d41f3b542cea96ff6c6b93d6e819c3 Mon Sep 17 00:00:00 2001 From: "Galvan, Mark" Date: Fri, 5 Jun 2026 10:16:24 -0700 Subject: [PATCH 4/4] Adjusted comment style --- PresentData/PresentMonTraceConsumer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/PresentData/PresentMonTraceConsumer.cpp b/PresentData/PresentMonTraceConsumer.cpp index 44d1eaa6..942ada23 100644 --- a/PresentData/PresentMonTraceConsumer.cpp +++ b/PresentData/PresentMonTraceConsumer.cpp @@ -3688,7 +3688,8 @@ AppTimingData* PMTraceConsumer::ExtractAppTimingData( } else { auto itToReturn = timingDataByFrameId.end(); if (isPcLatency) { - // For PC latency we match the app timing data to the present by selecting the unassigned entry whose selected time is closest to (but earlier than) PresentStartTime. + // For PC latency we match the app timing data to the present by selecting the unassigned entry whose selected + // time is closest to (but earlier than) PresentStartTime. uint64_t smallestPresentStartDelta = std::numeric_limits::max(); // Search for the timing data with the closest PresentStartTime to the passed // in PresentStartTime that has not been assigned. This is a hack and will not work for x-platform.