From 21b5bd3f75790591acb0eee57f9af025aa35254a Mon Sep 17 00:00:00 2001 From: Michael Gharbharan Date: Wed, 1 Apr 2026 15:37:20 -0400 Subject: [PATCH] Add new "AMD FSR FG" frame type Signed-off-by: Michael Gharbharan --- .../source/metadata/EnumFrameType.h | 3 +- .../PresentMonAPI2/PresentMonAPI.h | 3 +- .../PresentMonAPI2Tests/CsvHelper.h | 5 ++++ .../SampleClient/PacedFramePlayback.cpp | 2 ++ IntelPresentMon/UnitTests/MetricsCore.cpp | 27 ++++++++++++++++++ PresentData/Debug.cpp | 2 ++ PresentData/ETW/Intel_PresentMon.h | 1 + PresentData/PresentEventEnums.hpp | 1 + PresentData/PresentMonTraceConsumer.cpp | 8 ++++-- PresentMon/CsvOutput.cpp | 1 + Provider/Intel-PresentMon.man | Bin 21586 -> 21944 bytes Provider/PresentMonProvider.cpp | 1 + Provider/PresentMonProvider.h | 1 + 13 files changed, 51 insertions(+), 4 deletions(-) diff --git a/IntelPresentMon/Interprocess/source/metadata/EnumFrameType.h b/IntelPresentMon/Interprocess/source/metadata/EnumFrameType.h index 837669994..153e8bbbf 100644 --- a/IntelPresentMon/Interprocess/source/metadata/EnumFrameType.h +++ b/IntelPresentMon/Interprocess/source/metadata/EnumFrameType.h @@ -8,4 +8,5 @@ X_(FRAME_TYPE, APPLICATION, "Application", "", "Frame rendered by the target application") \ X_(FRAME_TYPE, REPEATED, "Application", "", "Frame rendered by the taget application") \ X_(FRAME_TYPE, INTEL_XEFG, "Intel XeSS-FG", "", "Frame generated by Intel XeSS-FG") \ - X_(FRAME_TYPE, AMD_AFMF, "AMD AFMF", "", "Frame generated by AMD Fluid Motion Frames") + X_(FRAME_TYPE, AMD_AFMF, "AMD AFMF", "", "Frame generated by AMD Fluid Motion Frames") \ + X_(FRAME_TYPE, AMD_FSR_FG, "AMD FSR FG", "", "Frame generated by AMD FSR FG") diff --git a/IntelPresentMon/PresentMonAPI2/PresentMonAPI.h b/IntelPresentMon/PresentMonAPI2/PresentMonAPI.h index e60a71a12..5274fd112 100644 --- a/IntelPresentMon/PresentMonAPI2/PresentMonAPI.h +++ b/IntelPresentMon/PresentMonAPI2/PresentMonAPI.h @@ -256,7 +256,8 @@ extern "C" { PM_FRAME_TYPE_APPLICATION, PM_FRAME_TYPE_REPEATED, PM_FRAME_TYPE_INTEL_XEFG = 50, - PM_FRAME_TYPE_AMD_AFMF = 100, + PM_FRAME_TYPE_AMD_AFMF = 100, + PM_FRAME_TYPE_AMD_FSR_FG = 101, }; enum PM_DEVICE_TYPE diff --git a/IntelPresentMon/PresentMonAPI2Tests/CsvHelper.h b/IntelPresentMon/PresentMonAPI2Tests/CsvHelper.h index b3f2cd617..8515d8f98 100644 --- a/IntelPresentMon/PresentMonAPI2Tests/CsvHelper.h +++ b/IntelPresentMon/PresentMonAPI2Tests/CsvHelper.h @@ -362,6 +362,9 @@ void CharConvert::Convert(const std::string data, T& convertedData, Header co else if (data == "Intel XeSS-FG") { convertedData = PM_FRAME_TYPE_INTEL_XEFG; } + else if (data == "AMD_FSR_FG") { + convertedData = PM_FRAME_TYPE_AMD_FSR_FG; + } else { throw CsvConversionException(Header_FrameType, line, data); } @@ -629,6 +632,8 @@ std::string TranslateFrameType(PM_FRAME_TYPE frameType) { return "AMD_AFMF"; case PM_FRAME_TYPE_INTEL_XEFG: return "Intel XeSS-FG"; + case PM_FRAME_TYPE_AMD_FSR_FG: + return "AMD_FSR_FG"; default: return ""; } diff --git a/IntelPresentMon/SampleClient/PacedFramePlayback.cpp b/IntelPresentMon/SampleClient/PacedFramePlayback.cpp index e2e566a49..68d599463 100644 --- a/IntelPresentMon/SampleClient/PacedFramePlayback.cpp +++ b/IntelPresentMon/SampleClient/PacedFramePlayback.cpp @@ -101,6 +101,8 @@ namespace return "AMD_AFMF"; case PM_FRAME_TYPE_INTEL_XEFG: return "Intel XeSS-FG"; + case PM_FRAME_TYPE_AMD_FSR_FG: + return "AMD_FSR_FG"; default: return "Other"; } diff --git a/IntelPresentMon/UnitTests/MetricsCore.cpp b/IntelPresentMon/UnitTests/MetricsCore.cpp index 2b4ac586b..e9c284017 100644 --- a/IntelPresentMon/UnitTests/MetricsCore.cpp +++ b/IntelPresentMon/UnitTests/MetricsCore.cpp @@ -782,6 +782,33 @@ TEST_CLASS(ComputeMetricsForPresentTests) Assert::AreEqual(uint64_t(1'500), swapChain.swapChain.lastDisplayedScreenTime, L"Should remain unchanged."); } + + TEST_METHOD(DisplayIndexing_AmdFsrFg_Multi_WithNext_AppIndexProcessed) + { + // 3x AMD_FSR_FG then a single Application + FrameData present = MakeFrame( + PresentResult::Presented, + 20'000, 600, 30'000, + { + { FrameType::AMD_FSR_FG, 21'000 }, + { FrameType::AMD_FSR_FG, 21'500 }, + { FrameType::AMD_FSR_FG, 22'000 }, + { FrameType::Application, 22'500 }, + }); + + FrameData nextDisplayed = MakeFrame( + PresentResult::Presented, + 23'000, 400, 30'500, + { { FrameType::Application, 24'000 } }); + + auto idx = DisplayIndexing::Calculate(present, &nextDisplayed); + + // With nextDisplayed: process postponed last only => [N-1, N) => [3, 4) + Assert::AreEqual(size_t(3), idx.startIndex); + Assert::AreEqual(size_t(4), idx.endIndex); + Assert::AreEqual(size_t(3), idx.appIndex); + Assert::IsTrue(idx.hasNextDisplayed); + } }; TEST_CLASS(UpdateAfterBootstrapPresentV2Tests) diff --git a/PresentData/Debug.cpp b/PresentData/Debug.cpp index 398cf258f..3eefb9528 100644 --- a/PresentData/Debug.cpp +++ b/PresentData/Debug.cpp @@ -182,6 +182,7 @@ wchar_t const* PMPFrameTypeToString(Intel_PresentMon::FrameType type) case Intel_PresentMon::FrameType::Repeated: return L"Repeated"; case Intel_PresentMon::FrameType::Intel_XEFG: return L"Intel XeSS-FG"; case Intel_PresentMon::FrameType::AMD_AFMF: return L"AMD AFMF"; + case Intel_PresentMon::FrameType::AMD_FSR_FG: return L"AMD FSR FG"; } assert(false); @@ -196,6 +197,7 @@ void PrintFrameType(FrameType type) case FrameType::Repeated: wprintf(L"Repeated"); break; case FrameType::Intel_XEFG: wprintf(L"Intel XeSS-FG"); break; case FrameType::AMD_AFMF: wprintf(L"AMD AFMF"); break; + case FrameType::AMD_FSR_FG: wprintf(L"AMD FSR FG"); break; default: wprintf(L"Unknown (%u)", type); assert(false); break; } } diff --git a/PresentData/ETW/Intel_PresentMon.h b/PresentData/ETW/Intel_PresentMon.h index 33f35cffa..35af1ba72 100644 --- a/PresentData/ETW/Intel_PresentMon.h +++ b/PresentData/ETW/Intel_PresentMon.h @@ -55,6 +55,7 @@ enum class FrameType : uint8_t { Repeated = 2, Intel_XEFG = 50, AMD_AFMF = 100, + AMD_FSR_FG = 101, }; enum class InputType : uint32_t { diff --git a/PresentData/PresentEventEnums.hpp b/PresentData/PresentEventEnums.hpp index ff808f590..49f85a8dd 100644 --- a/PresentData/PresentEventEnums.hpp +++ b/PresentData/PresentEventEnums.hpp @@ -40,4 +40,5 @@ enum class FrameType { Repeated = 3, Intel_XEFG = 50, AMD_AFMF = 100, + AMD_FSR_FG = 101, }; \ No newline at end of file diff --git a/PresentData/PresentMonTraceConsumer.cpp b/PresentData/PresentMonTraceConsumer.cpp index 0a05137e1..37a52ac9c 100644 --- a/PresentData/PresentMonTraceConsumer.cpp +++ b/PresentData/PresentMonTraceConsumer.cpp @@ -39,6 +39,7 @@ static inline FrameType ConvertPMPFrameTypeToFrameType(Intel_PresentMon::FrameTy case Intel_PresentMon::FrameType::Repeated: return FrameType::Repeated; case Intel_PresentMon::FrameType::Intel_XEFG: return FrameType::Intel_XEFG; case Intel_PresentMon::FrameType::AMD_AFMF: return FrameType::AMD_AFMF; + case Intel_PresentMon::FrameType::AMD_FSR_FG: return FrameType::AMD_FSR_FG; } DebugAssert(false); @@ -70,7 +71,8 @@ static inline bool ShouldAppendApplicationAfterGeneratedDisplay(std::shared_ptr< { bool hasGeneratedFrame = HasDisplayedFrameType(p, FrameType::Intel_XEFG) || - HasDisplayedFrameType(p, FrameType::AMD_AFMF); + HasDisplayedFrameType(p, FrameType::AMD_AFMF) || + HasDisplayedFrameType(p, FrameType::AMD_FSR_FG); bool hasApplicationFrame = HasDisplayedFrameType(p, FrameType::Application); @@ -3900,7 +3902,9 @@ bool PMTraceConsumer::IsApplicationPresent(std::shared_ptr const& } auto frameType = present->Displayed[0]; - return ((frameType.first != FrameType::Intel_XEFG) && (frameType.first != FrameType::AMD_AFMF)); + return ((frameType.first != FrameType::Intel_XEFG) && + (frameType.first != FrameType::AMD_AFMF) && + (frameType.first != FrameType::AMD_FSR_FG)); } void PMTraceConsumer::SetAppTimingDataAsComplete(uint32_t processId, uint32_t appFrameId) { diff --git a/PresentMon/CsvOutput.cpp b/PresentMon/CsvOutput.cpp index 4b9cc9801..e2223b9ca 100644 --- a/PresentMon/CsvOutput.cpp +++ b/PresentMon/CsvOutput.cpp @@ -64,6 +64,7 @@ const char* FrameTypeToString(FrameType ft) case FrameType::Application: return "Application"; case FrameType::Intel_XEFG: return "Intel XeSS-FG"; case FrameType::AMD_AFMF: return "AMD AFMF"; + case FrameType::AMD_FSR_FG: return "AMD FSR FG"; } return "Unknown"; diff --git a/Provider/Intel-PresentMon.man b/Provider/Intel-PresentMon.man index c9b01f0f3f31377517b83dd4901a053258764ecc..5b96a0c3ea8531a35f59812837b9ea81bc055cb0 100644 GIT binary patch delta 99 zcmcb#f^o-c#tj!dCLdtunEb&@VzPk;%j5trpUDj#5|cN0S!}-GA;SscC>t^;F(@#U zF(fkNFqAT+GS~w7jtssGE)4MuZVbT;K@9Pe?+0X0e&8uK`JCS*AT6?aMbIin0I1_3 A2LJ#7 delta 31 mcmdn7n(@*K#tj!dHc#-B;hem{OKftV|0EzSvY9Vr6(a!UQVl-< diff --git a/Provider/PresentMonProvider.cpp b/Provider/PresentMonProvider.cpp index 5eef26c76..1e5eb55a3 100644 --- a/Provider/PresentMonProvider.cpp +++ b/Provider/PresentMonProvider.cpp @@ -187,6 +187,7 @@ bool IsValid( frameType == PresentMonProvider_FrameType_Repeated || frameType == PresentMonProvider_FrameType_Intel_XEFG || frameType == PresentMonProvider_FrameType_AMD_AFMF || + frameType == PresentMonProvider_FrameType_AMD_FSR_FG || frameType == PresentMonProvider_FrameType_NVIDIA_DLSS; } diff --git a/Provider/PresentMonProvider.h b/Provider/PresentMonProvider.h index bf2449d37..9dc62b880 100644 --- a/Provider/PresentMonProvider.h +++ b/Provider/PresentMonProvider.h @@ -71,6 +71,7 @@ enum PresentMonProvider_FrameType { PresentMonProvider_FrameType_Repeated, // The frame rendered by the application is being repeated. PresentMonProvider_FrameType_Intel_XEFG = 50, // Frame generated by Intel Xe Frame Generation. PresentMonProvider_FrameType_AMD_AFMF = 100, // Frame generated by AMD Fluid Motion Frames. + PresentMonProvider_FrameType_AMD_FSR_FG = 101, // Frame generated by AMD FSR Frame Generation. PresentMonProvider_FrameType_NVIDIA_DLSS = 150, // Frame generated by NVIDIA DLSS. };