diff --git a/ETLTrimmer/main.cpp b/ETLTrimmer/main.cpp
index a1b96ce8..812c5798 100644
--- a/ETLTrimmer/main.cpp
+++ b/ETLTrimmer/main.cpp
@@ -374,6 +374,8 @@ int main(int argc, const char** argv)
traceConsumer.mTrackGPUVideo = true; // ... GPU video work (separately from non-video GPU work).
traceConsumer.mTrackInput = true; // ... keyboard/mouse latency.
traceConsumer.mTrackFrameType = true; // ... the frame type communicated through the Intel-PresentMon provider.
+ traceConsumer.mTrackAppTiming = true; // ... app timing data communicated through the Intel-PresentMon provider.
+ traceConsumer.mTrackPcLatency = true; // ... Nvidia PCL stats.
EnableProvidersListing(0, nullptr, &traceConsumer, true, true, pFilter);
}
diff --git a/IntelPresentMon/AppCef/CefNano.vcxproj b/IntelPresentMon/AppCef/CefNano.vcxproj
index d2a56538..3db54ac3 100644
--- a/IntelPresentMon/AppCef/CefNano.vcxproj
+++ b/IntelPresentMon/AppCef/CefNano.vcxproj
@@ -170,7 +170,7 @@
Windows
true
Cef\Lib\Debug;%(AdditionalLibraryDirectories)
- libcef.lib;libcef_dll_wrapper.lib;Dwrite.lib;%(AdditionalDependencies)
+ libcef.lib;libcef_dll_wrapper.lib;Dwrite.lib;shcore.lib;%(AdditionalDependencies)
Executing Post Build
@@ -200,7 +200,7 @@
true
true
Cef\Lib\Release;%(AdditionalLibraryDirectories)
- libcef.lib;libcef_dll_wrapper.lib;Dwrite.lib;%(AdditionalDependencies)
+ libcef.lib;libcef_dll_wrapper.lib;Dwrite.lib;shcore.lib;%(AdditionalDependencies)
Executing Post Build
diff --git a/IntelPresentMon/AppCef/ipm-ui-vue/BlockLists/TargetBlockList.txt b/IntelPresentMon/AppCef/ipm-ui-vue/BlockLists/TargetBlockList.txt
index ed118597..35ac5ad1 100644
--- a/IntelPresentMon/AppCef/ipm-ui-vue/BlockLists/TargetBlockList.txt
+++ b/IntelPresentMon/AppCef/ipm-ui-vue/BlockLists/TargetBlockList.txt
@@ -25,6 +25,7 @@ bethesdanethelper.exe
bethesdanetlauncher.exe
blend.exe
blender.exe
+bootstrapperui_v2.exe
bsglauncher.exe
calculator.exe
calculatorapp.exe
diff --git a/IntelPresentMon/CommonUtilities/CommonUtilities.vcxproj b/IntelPresentMon/CommonUtilities/CommonUtilities.vcxproj
index e88c91e2..d8f81ad5 100644
--- a/IntelPresentMon/CommonUtilities/CommonUtilities.vcxproj
+++ b/IntelPresentMon/CommonUtilities/CommonUtilities.vcxproj
@@ -216,20 +216,22 @@
- ..\..\build\obj\$(ProjectName)-$(Platform)-$(Configuration)\
- ..\..\build\obj\$(ProjectName)-$(Platform)-$(Configuration)\
+ $(SolutionDir)build\lib\$(ProjectName)-$(Platform)-$(Configuration)\
+ $(SolutionDir)build\obj\$(ProjectName)-$(Platform)-$(Configuration)\
- ..\..\build\obj\$(ProjectName)-$(Platform)-$(Configuration)\
- ..\..\build\obj\$(ProjectName)-$(Platform)-$(Configuration)\
+ $(SolutionDir)build\lib\$(ProjectName)-$(Platform)-$(Configuration)\
+ $(SolutionDir)build\obj\$(ProjectName)-$(Platform)-$(Configuration)\
+ $(SolutionDir)build\lib\$(ProjectName)-$(Platform)-$(Configuration)\
+ $(SolutionDir)build\lib\$(ProjectName)-$(Platform)-$(Configuration)\
@@ -294,7 +296,8 @@
- shcore.lib
+
+
@@ -327,7 +330,8 @@
- shcore.lib
+
+
diff --git a/IntelPresentMon/CommonUtilities/CommonUtilities.vcxproj.filters b/IntelPresentMon/CommonUtilities/CommonUtilities.vcxproj.filters
index 74bcfece..69eaf1cd 100644
--- a/IntelPresentMon/CommonUtilities/CommonUtilities.vcxproj.filters
+++ b/IntelPresentMon/CommonUtilities/CommonUtilities.vcxproj.filters
@@ -171,9 +171,6 @@
Header Files
-
- Header Files
-
Header Files
@@ -234,6 +231,9 @@
Header Files
+
+ Header Files
+
Header Files
@@ -395,6 +395,9 @@
Source Files
+
+ Source Files
+
diff --git a/IntelPresentMon/CommonUtilities/Math.h b/IntelPresentMon/CommonUtilities/Math.h
index 4f5a4271..4730011e 100644
--- a/IntelPresentMon/CommonUtilities/Math.h
+++ b/IntelPresentMon/CommonUtilities/Math.h
@@ -1,6 +1,7 @@
#pragma once
#include
#include
+#include
namespace pmon::util
{
@@ -53,4 +54,9 @@ namespace pmon::util
const auto conversionFactor = srcFactor / dstFactor;
return To(fromExtended * conversionFactor);
}
+ template
+ T CalculateEma(T prevEma, T newSample, T alpha)
+ {
+ return prevEma + alpha * (newSample - prevEma);
+ }
}
\ No newline at end of file
diff --git a/IntelPresentMon/CommonUtilities/Meta.h b/IntelPresentMon/CommonUtilities/Meta.h
index 9dd18a37..69f26bc5 100644
--- a/IntelPresentMon/CommonUtilities/Meta.h
+++ b/IntelPresentMon/CommonUtilities/Meta.h
@@ -4,6 +4,10 @@
namespace pmon::util
{
+ // Helper: dependent_false for static_assert in templates.
+ template
+ struct dependent_false : std::false_type {};
+
// deconstruct member pointer into the object type the pointer works with and the member type
template struct MemberPointerInfo;
template
diff --git a/IntelPresentMon/Core/source/pmon/RawFrameDataMetricList.h b/IntelPresentMon/Core/source/pmon/RawFrameDataMetricList.h
index 3a0f70a9..90ca5659 100644
--- a/IntelPresentMon/Core/source/pmon/RawFrameDataMetricList.h
+++ b/IntelPresentMon/Core/source/pmon/RawFrameDataMetricList.h
@@ -47,10 +47,12 @@ namespace p2c::pmon
Element{.metricId = PM_METRIC_GPU_BUSY, .deviceId = 0 },
Element{.metricId = PM_METRIC_GPU_WAIT, .deviceId = 0 },
Element{.metricId = PM_METRIC_ANIMATION_ERROR, .deviceId = 0 },
+ Element{.metricId = PM_METRIC_FLIP_DELAY, .deviceId = 0 },
Element{.metricId = PM_METRIC_ANIMATION_TIME, .deviceId = 0 },
Element{.metricId = PM_METRIC_ALL_INPUT_TO_PHOTON_LATENCY, .deviceId = 0 },
Element{.metricId = PM_METRIC_CLICK_TO_PHOTON_LATENCY, .deviceId = 0 },
Element{.metricId = PM_METRIC_INSTRUMENTED_LATENCY, .deviceId = 0 },
+ Element{.metricId = PM_METRIC_PC_LATENCY, .deviceId = 0 },
Element{.metricId = PM_METRIC_GPU_POWER, .deviceId = activeDeviceId },
Element{.metricId = PM_METRIC_GPU_VOLTAGE, .deviceId = activeDeviceId },
diff --git a/IntelPresentMon/Core/source/win/HotkeyListener.cpp b/IntelPresentMon/Core/source/win/HotkeyListener.cpp
index b01ca2b0..bb901922 100644
--- a/IntelPresentMon/Core/source/win/HotkeyListener.cpp
+++ b/IntelPresentMon/Core/source/win/HotkeyListener.cpp
@@ -5,6 +5,8 @@
#include
#include
#include
+// disable faulty warnings on lock
+#pragma warning(disable: 26117 26110)
namespace rn = std::ranges;
namespace vi = rn::views;
diff --git a/IntelPresentMon/Interprocess/source/metadata/MetricList.h b/IntelPresentMon/Interprocess/source/metadata/MetricList.h
index 22a7bebb..e945a12d 100644
--- a/IntelPresentMon/Interprocess/source/metadata/MetricList.h
+++ b/IntelPresentMon/Interprocess/source/metadata/MetricList.h
@@ -93,3 +93,4 @@
X_(PM_METRIC_DISPLAYED_FRAME_TIME, PM_METRIC_TYPE_DYNAMIC, PM_UNIT_MILLISECONDS, PM_DATA_TYPE_DOUBLE, PM_DATA_TYPE_DOUBLE, 0, PM_DEVICE_TYPE_INDEPENDENT, FULL_STATS) \
X_(PM_METRIC_PRESENTED_FRAME_TIME, PM_METRIC_TYPE_DYNAMIC, PM_UNIT_MILLISECONDS, PM_DATA_TYPE_DOUBLE, PM_DATA_TYPE_DOUBLE, 0, PM_DEVICE_TYPE_INDEPENDENT, FULL_STATS) \
X_(PM_METRIC_BETWEEN_APP_START, PM_METRIC_TYPE_FRAME_EVENT, PM_UNIT_MILLISECONDS, PM_DATA_TYPE_DOUBLE, PM_DATA_TYPE_DOUBLE, 0, PM_DEVICE_TYPE_INDEPENDENT, FULL_STATS) \
+ X_(PM_METRIC_FLIP_DELAY, PM_METRIC_TYPE_FRAME_EVENT, PM_UNIT_MILLISECONDS, PM_DATA_TYPE_DOUBLE, PM_DATA_TYPE_DOUBLE, 0, PM_DEVICE_TYPE_INDEPENDENT, FULL_STATS) \
diff --git a/IntelPresentMon/PresentMonAPI2/PresentMonAPI.h b/IntelPresentMon/PresentMonAPI2/PresentMonAPI.h
index 3ec8a3f5..6247a754 100644
--- a/IntelPresentMon/PresentMonAPI2/PresentMonAPI.h
+++ b/IntelPresentMon/PresentMonAPI2/PresentMonAPI.h
@@ -132,6 +132,7 @@ extern "C" {
PM_METRIC_DISPLAYED_FRAME_TIME,
PM_METRIC_BETWEEN_APP_START,
PM_METRIC_PRESENTED_FRAME_TIME,
+ PM_METRIC_FLIP_DELAY,
};
enum PM_METRIC_TYPE
diff --git a/IntelPresentMon/PresentMonAPI2Tests/CsvHelper.h b/IntelPresentMon/PresentMonAPI2Tests/CsvHelper.h
index 3a6d9bb8..aab924b1 100644
--- a/IntelPresentMon/PresentMonAPI2Tests/CsvHelper.h
+++ b/IntelPresentMon/PresentMonAPI2Tests/CsvHelper.h
@@ -306,18 +306,22 @@ void CharConvert::Convert(const std::string data, T& convertedData, Header co
}
size_t countDecimalPlaces(double value) {
- // Convert double to string
std::string str = std::to_string(value);
+ auto dotPos = str.find('.');
+ if (dotPos == std::string::npos) return 0;
- char const* a = str.c_str();
+ // Get the decimal part
+ std::string decimals = str.substr(dotPos + 1);
- double testNumber = 0.0;
- double goldNumber = 0.0;
- int testSucceededCount = sscanf_s(a, "%lf", &testNumber);
+ // Remove trailing zeros
+ decimals.erase(decimals.find_last_not_of('0') + 1);
- const char* testDecimalAddr = strchr(a, '.');
- size_t testDecimalNumbersCount = testDecimalAddr == nullptr ? 0 : ((a + strlen(a)) - testDecimalAddr - 1);
- return testDecimalNumbersCount;
+ // Count non-zero decimal digits
+ size_t count = 0;
+ for (char c : decimals) {
+ if (c != '0') ++count;
+ }
+ return count;
}
template
@@ -357,7 +361,7 @@ std::optional CreateCsvFile(std::string& output_dir, std::string&
",MsBetweenDisplayChange,MsInPresent,MsRenderPresentLatency"
",MsUntilDisplayed,MsPCLatency,CPUStartQPC,MsBetweenAppStart"
",MsCPUBusy,MsCPUWait,MsGPULatency,MsGPUTime,MsGPUBusy,MsGPUWait"
- ",MsVideoBusy,MsAnimationError,AnimationTime,MsAllInputToPhotonLatency"
+ ",MsVideoBusy,MsAnimationError,AnimationTime,MsFlipDelay,MsAllInputToPhotonLatency"
",MsClickToPhotonLatency,MsInstrumentedLatency";
csvFile << std::endl;
return csvFile;
@@ -416,7 +420,7 @@ std::string TranslateFrameType(PM_FRAME_TYPE frameType) {
}
void WriteToCSV(std::optional& debugCsvFile, const std::string& processName, const unsigned int& processId,
- PM_QUERY_ELEMENT(&queryElements)[28], pmapi::BlobContainer& blobs)
+ PM_QUERY_ELEMENT(&queryElements)[29], pmapi::BlobContainer& blobs)
{
if (!debugCsvFile.has_value()) {
@@ -449,9 +453,10 @@ void WriteToCSV(std::optional& debugCsvFile, const std::string& p
const auto msGpuWait = *reinterpret_cast(&pBlob[queryElements[22].dataOffset]);
const auto msAnimationError = *reinterpret_cast(&pBlob[queryElements[23].dataOffset]);
const auto animationTime = *reinterpret_cast(&pBlob[queryElements[24].dataOffset]);
- const auto msAllInputToPhotonLatency = *reinterpret_cast(&pBlob[queryElements[25].dataOffset]);
- const auto msClickToPhotonLatency = *reinterpret_cast(&pBlob[queryElements[26].dataOffset]);
- const auto msInstrumentedLatency = *reinterpret_cast(&pBlob[queryElements[27].dataOffset]);
+ const auto msFlipDelay = *reinterpret_cast(&pBlob[queryElements[25].dataOffset]);
+ const auto msAllInputToPhotonLatency = *reinterpret_cast(&pBlob[queryElements[26].dataOffset]);
+ const auto msClickToPhotonLatency = *reinterpret_cast(&pBlob[queryElements[27].dataOffset]);
+ const auto msInstrumentedLatency = *reinterpret_cast(&pBlob[queryElements[28].dataOffset]);
*debugCsvFile << processName << ",";
*debugCsvFile << processId << ",";
*debugCsvFile << std::hex << "0x" << std::dec << swapChain << ",";
@@ -480,6 +485,7 @@ void WriteToCSV(std::optional& debugCsvFile, const std::string& p
*debugCsvFile << 0 << ",";
*debugCsvFile << msAnimationError << ",";
*debugCsvFile << animationTime << ",";
+ *debugCsvFile << msFlipDelay << ",";
*debugCsvFile << msAllInputToPhotonLatency << ",";
*debugCsvFile << msClickToPhotonLatency << ",";
*debugCsvFile << msInstrumentedLatency << std::endl;
@@ -497,7 +503,7 @@ class CsvParser {
bool Open(std::wstring const& path, uint32_t processId);
void Close();
bool VerifyBlobAgainstCsv(const std::string& processName, const unsigned int& processId,
- PM_QUERY_ELEMENT(&queryElements)[28], pmapi::BlobContainer& blobs, std::optional& debugCsvFile);
+ PM_QUERY_ELEMENT(&queryElements)[29], pmapi::BlobContainer& blobs, std::optional& debugCsvFile);
bool ResetCsv();
private:
@@ -526,7 +532,7 @@ CsvParser::CsvParser()
{}
bool CsvParser::VerifyBlobAgainstCsv(const std::string& processName, const unsigned int& processId,
- PM_QUERY_ELEMENT(&queryElements)[28], pmapi::BlobContainer& blobs, std::optional& debugCsvFile)
+ PM_QUERY_ELEMENT(&queryElements)[29], pmapi::BlobContainer& blobs, std::optional& debugCsvFile)
{
if (debugCsvFile.has_value()) {
WriteToCSV(debugCsvFile, processName, processId, queryElements, blobs);
@@ -559,11 +565,10 @@ bool CsvParser::VerifyBlobAgainstCsv(const std::string& processName, const unsig
const auto msGpuWait = *reinterpret_cast(&pBlob[queryElements[22].dataOffset]);
const auto msAnimationError = *reinterpret_cast(&pBlob[queryElements[23].dataOffset]);
const auto animationTime = *reinterpret_cast(&pBlob[queryElements[24].dataOffset]);
- const auto msAllInputToPhotonLatency = *reinterpret_cast(&pBlob[queryElements[25].dataOffset]);
- const auto msClickToPhotonLatency = *reinterpret_cast(&pBlob[queryElements[26].dataOffset]);
- const auto msInstrumentedLatency = *reinterpret_cast(&pBlob[queryElements[27].dataOffset]);
-
-
+ const auto msFrameDelay = *reinterpret_cast(&pBlob[queryElements[25].dataOffset]);
+ const auto msAllInputToPhotonLatency = *reinterpret_cast(&pBlob[queryElements[26].dataOffset]);
+ const auto msClickToPhotonLatency = *reinterpret_cast(&pBlob[queryElements[27].dataOffset]);
+ const auto msInstrumentedLatency = *reinterpret_cast(&pBlob[queryElements[28].dataOffset]);
// Read rows until we find one with the process we are interested in
// or we are out of data.
@@ -689,6 +694,9 @@ bool CsvParser::VerifyBlobAgainstCsv(const std::string& processName, const unsig
case Header_MsPCLatency:
if (v2MetricRow_.msPcLatency.has_value()) {
columnsMatch = Validate(v2MetricRow_.msPcLatency.value(), msPcLatency);
+ if (!columnsMatch) {
+ OutputDebugStringA("What!?\n");
+ }
}
else
{
@@ -780,6 +788,11 @@ bool CsvParser::VerifyBlobAgainstCsv(const std::string& processName, const unsig
columnsMatch = true;
break;
}
+ if (columnsMatch == false) {
+ // If the columns do not match, create an error string
+ // and assert failure.
+ Assert::Fail(CreateErrorString(pair.second, line_).c_str());
+ }
Assert::IsTrue(columnsMatch, CreateErrorString(pair.second, line_).c_str());
}
}
@@ -1185,7 +1198,6 @@ void CsvParser::ConvertToMetricDataType(const char* data, Header columnId)
}
}
break;
-
default:
Assert::Fail(CreateErrorString(UnknownHeader, line_).c_str());
}
diff --git a/IntelPresentMon/PresentMonAPI2Tests/EtlTests.cpp b/IntelPresentMon/PresentMonAPI2Tests/EtlTests.cpp
index 2771e00c..42164243 100644
--- a/IntelPresentMon/PresentMonAPI2Tests/EtlTests.cpp
+++ b/IntelPresentMon/PresentMonAPI2Tests/EtlTests.cpp
@@ -21,7 +21,7 @@ namespace EtlTests
std::optional& debugCsvFile) {
using namespace std::chrono_literals;
pmapi::ProcessTracker processTracker;
- static constexpr uint32_t numberOfBlobs = 4000u;
+ static constexpr uint32_t numberOfBlobs = 10000u;
uint32_t totalFramesValidated = 0;
PM_QUERY_ELEMENT queryElements[]{
@@ -51,6 +51,7 @@ namespace EtlTests
{ PM_METRIC_GPU_WAIT, PM_STAT_NONE, 0, 0},
{ PM_METRIC_ANIMATION_ERROR, PM_STAT_NONE, 0, 0 },
{ PM_METRIC_ANIMATION_TIME, PM_STAT_NONE, 0, 0 },
+ { PM_METRIC_FLIP_DELAY, PM_STAT_NONE, 0, 0 },
{ PM_METRIC_ALL_INPUT_TO_PHOTON_LATENCY, PM_STAT_NONE, 0, 0},
{ PM_METRIC_CLICK_TO_PHOTON_LATENCY, PM_STAT_NONE, 0, 0},
{ PM_METRIC_INSTRUMENTED_LATENCY, PM_STAT_NONE, 0, 0 },
@@ -1657,10 +1658,6 @@ namespace EtlTests
return;
}
- std::string outputdir = "F:\\EtlTesting\\"s;
- std::string csvFileName = "test_output_6.csv";
- debugCsv = CreateCsvFile(outputdir, csvFileName);
-
oChild.emplace("PresentMonService.exe"s,
"--timed-stop"s, "60000"s,
"--control-pipe"s, pipeName,
@@ -1853,14 +1850,14 @@ namespace EtlTests
debugCsv->close();
}
}
- TEST_METHOD(Tc010v2ReprojLatency9688Ext)
+ TEST_METHOD(Tc010MarvelOnNvPcl1FgOnExt)
{
namespace bp = boost::process;
using namespace std::string_literals;
using namespace std::chrono_literals;
- const uint32_t processId = 9688;
- const std::string processName = "basic_xell_sample.exe";
+ const uint32_t processId = 42132;
+ const std::string processName = "Marvel-Win64-Shipping.exe";
std::optional debugCsv; // Empty optional
bp::ipstream out; // Stream for reading the process's output
@@ -1908,6 +1905,117 @@ namespace EtlTests
debugCsv->close();
}
}
- };
+ TEST_METHOD(Tc011CP2077Pcl2FgOffRelexOffExt)
+ {
+ namespace bp = boost::process;
+ using namespace std::string_literals;
+ using namespace std::chrono_literals;
+ const uint32_t processId = 12524;
+ const std::string processName = "Cyberpunk2077.exe";
+ std::optional debugCsv; // Empty optional
+
+ bp::ipstream out; // Stream for reading the process's output
+ bp::opstream in; // Stream for writing to the process's input
+
+ const auto pipeName = R"(\\.\pipe\test-pipe-pmsvc-2)"s;
+ const auto introName = "PM_intro_test_nsm_2"s;
+ const auto etlName = "F:\\EtlTesting\\test_case_11.etl";
+ const auto goldCsvName = L"F:\\EtlTesting\\test_case_11.csv";
+
+ CsvParser goldCsvFile;
+ if (!goldCsvFile.Open(goldCsvName, processId)) {
+ return;
+ }
+
+ oChild.emplace("PresentMonService.exe"s,
+ "--timed-stop"s, "60000"s,
+ "--control-pipe"s, pipeName,
+ "--nsm-prefix"s, "pmon_nsm_utest_"s,
+ "--intro-nsm"s, introName,
+ "--etl-test-file"s, etlName,
+ bp::std_out > out, bp::std_in < in);
+
+ std::this_thread::sleep_for(1000ms);
+
+ std::unique_ptr pSession;
+ {
+ try
+ {
+ pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll");
+ pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false);
+ pSession = std::make_unique(pipeName);
+ }
+ catch (const std::exception& e) {
+ std::cout << "Error: " << e.what() << std::endl;
+ Assert::AreEqual(false, true, L"*** Connecting to service via named pipe");
+ return;
+ }
+ }
+
+ RunTestCaseV2(std::move(pSession), processId, processName, goldCsvFile, debugCsv);
+ goldCsvFile.Close();
+ if (debugCsv.has_value()) {
+ debugCsv->close();
+ }
+ }
+ TEST_METHOD(Tc012MarvelOnNvPcl3FgOnAutoReflexOnFrameDelayExt)
+ {
+ namespace bp = boost::process;
+ using namespace std::string_literals;
+ using namespace std::chrono_literals;
+
+ const uint32_t processId = 24412;
+ const std::string processName = "Marvel-Win64-Shipping.exe";
+ std::optional debugCsv; // Empty optional
+
+ bp::ipstream out; // Stream for reading the process's output
+ bp::opstream in; // Stream for writing to the process's input
+
+ const auto pipeName = R"(\\.\pipe\test-pipe-pmsvc-2)"s;
+ const auto introName = "PM_intro_test_nsm_2"s;
+ const auto etlName = "F:\\EtlTesting\\test_case_12.etl";
+ const auto goldCsvName = L"F:\\EtlTesting\\test_case_12.csv";
+
+ CsvParser goldCsvFile;
+ if (!goldCsvFile.Open(goldCsvName, processId)) {
+ return;
+ }
+
+ std::string folder = "F:\\EtlTesting\\ETLDebugging\\testcase12\\"s;
+ std::string csvName = "debug.csv"s;
+ debugCsv = CreateCsvFile(folder,csvName);
+
+ oChild.emplace("PresentMonService.exe"s,
+ //"--timed-stop"s, "60000"s,
+ "--control-pipe"s, pipeName,
+ "--nsm-prefix"s, "pmon_nsm_utest_"s,
+ "--intro-nsm"s, introName,
+ "--etl-test-file"s, etlName,
+ bp::std_out > out, bp::std_in < in);
+
+ std::this_thread::sleep_for(1000ms);
+
+ std::unique_ptr pSession;
+ {
+ try
+ {
+ pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll");
+ pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false);
+ pSession = std::make_unique(pipeName);
+ }
+ catch (const std::exception& e) {
+ std::cout << "Error: " << e.what() << std::endl;
+ Assert::AreEqual(false, true, L"*** Connecting to service via named pipe");
+ return;
+ }
+ }
+
+ RunTestCaseV2(std::move(pSession), processId, processName, goldCsvFile, debugCsv);
+ goldCsvFile.Close();
+ if (debugCsv.has_value()) {
+ debugCsv->close();
+ }
+ }
+ };
}
\ No newline at end of file
diff --git a/IntelPresentMon/PresentMonMiddleware/ConcreteMiddleware.cpp b/IntelPresentMon/PresentMonMiddleware/ConcreteMiddleware.cpp
index 83f23979..c75dd8ad 100644
--- a/IntelPresentMon/PresentMonMiddleware/ConcreteMiddleware.cpp
+++ b/IntelPresentMon/PresentMonMiddleware/ConcreteMiddleware.cpp
@@ -133,6 +133,8 @@ namespace pmon::mid
if (iter != presentMonStreamClients.end()) {
presentMonStreamClients.erase(std::move(iter));
}
+ // Remove the input to frame start data for this process.
+ mPclI2FsManager.RemoveProcess(targetPid);
}
catch (...) {
const auto code = util::GeneratePmStatus();
@@ -532,6 +534,8 @@ struct FrameMetrics {
double mAllInputPhotonLatency;
FrameType mFrameType;
double mInstrumentedDisplayLatency;
+ double mPcLatency;
+ double mMsBetweenSimStarts;
double mInstrumentedRenderLatency;
double mInstrumentedSleep;
@@ -548,14 +552,38 @@ void UpdateChain(
if (p.DisplayedCount > 0) {
if (p.Displayed_FrameType[p.DisplayedCount - 1] == FrameType::NotSet ||
p.Displayed_FrameType[p.DisplayedCount - 1] == FrameType::Application) {
- // Used when calculating animation error
- if (p.AppSimStartTime != 0) {
- chain->mLastDisplayedSimStart = p.AppSimStartTime;
- } else if (chain->mLastAppPresentIsValid == true) {
- chain->mLastDisplayedSimStart = chain->mLastAppPresent.PresentStartTime +
- chain->mLastAppPresent.TimeInPresent;
+ // If the chain animation error source has been set to either
+ // app provider or PCL latency then set the last displayed simulation start time and the
+ // first app simulation start time based on the animation error source type.
+ if (chain->mAnimationErrorSource == AnimationErrorSource::AppProvider) {
+ chain->mLastDisplayedSimStartTime = p.AppSimStartTime;
+ chain->mLastDisplayedAppScreenTime = p.Displayed_ScreenTime[p.DisplayedCount - 1];
+ } else if (chain->mAnimationErrorSource == AnimationErrorSource::PCLatency) {
+ // In the case of PCLatency only set values if pcl sim start time is not zero.
+ if (p.PclSimStartTime != 0) {
+ chain->mLastDisplayedSimStartTime = p.PclSimStartTime;
+ chain->mLastDisplayedAppScreenTime = p.Displayed_ScreenTime[p.DisplayedCount - 1];
+ }
+ } else {
+ // Currently sourcing animation error from CPU start time, however check
+ // to see if we have a valid app provider or PCL sim start time and set the
+ // new animation source and set the first app sim start time
+ if (p.AppSimStartTime != 0) {
+ chain->mAnimationErrorSource = AnimationErrorSource::AppProvider;
+ chain->mLastDisplayedSimStartTime = p.AppSimStartTime;
+ chain->mLastDisplayedAppScreenTime = p.Displayed_ScreenTime[p.DisplayedCount - 1];
+ } else if (p.PclSimStartTime != 0) {
+ chain->mAnimationErrorSource = AnimationErrorSource::PCLatency;
+ chain->mLastDisplayedSimStartTime = p.PclSimStartTime;
+ chain->mLastDisplayedAppScreenTime = p.Displayed_ScreenTime[p.DisplayedCount - 1];
+ } else {
+ if (chain->mLastAppPresentIsValid == true) {
+ chain->mLastDisplayedSimStartTime = chain->mLastAppPresent.PresentStartTime +
+ chain->mLastAppPresent.TimeInPresent;
+ }
+ chain->mLastDisplayedAppScreenTime = p.Displayed_ScreenTime[p.DisplayedCount - 1];
+ }
}
- chain->mLastDisplayedAppScreenTime = p.Displayed_ScreenTime[p.DisplayedCount - 1];
}
}
// TODO: This used to be p.Displayed_ScreenTime[0]. That seems incorrect.
@@ -583,6 +611,14 @@ void UpdateChain(
chain->mLastAppPresentIsValid = true;
}
+ // Set chain->mLastSimStartTime to either p->PclSimStartTime or p->AppSimStartTime depending on
+ // if either are not zero. If both are zero, do not set.
+ if (p.PclSimStartTime != 0) {
+ chain->mLastSimStartTime = p.PclSimStartTime;
+ } else if (p.AppSimStartTime != 0) {
+ chain->mLastSimStartTime = p.AppSimStartTime;
+ }
+
chain->mLastPresent = p;
chain->mLastPresentIsValid = true;
chain->mIncludeFrameData = true;
@@ -591,6 +627,7 @@ void UpdateChain(
// Copied from: PresentMon/OutputThread.cpp
static void ReportMetricsHelper(
FakePMTraceSession const& pmSession,
+ InputToFsManager& pclI2FsManager,
fpsSwapChainData* chain,
PmNsmPresentEvent* p,
PmNsmPresentEvent const* nextDisplayedPresent)
@@ -700,6 +737,14 @@ static void ReportMetricsHelper(
// way to calculate the Xell Gpu latency
metrics.mInstrumentedGpuLatency = instrumentedStartTime == 0 ? 0 :
pmSession.TimestampDeltaToUnsignedMilliSeconds(instrumentedStartTime, p->GPUStartTime);
+
+ // If we have both a valid pcl sim start time and a valid app sim start time, we use the pcl sim start time.
+ if (p->PclSimStartTime != 0) {
+ metrics.mMsBetweenSimStarts = pmSession.TimestampDeltaToUnsignedMilliSeconds(chain->mLastSimStartTime, p->PclSimStartTime);
+ }
+ else if (p->AppSimStartTime != 0) {
+ metrics.mMsBetweenSimStarts = pmSession.TimestampDeltaToUnsignedMilliSeconds(chain->mLastSimStartTime, p->AppSimStartTime);
+ }
} else {
metrics.mCPUBusy = 0;
metrics.mCPUWait = 0;
@@ -709,8 +754,11 @@ static void ReportMetricsHelper(
metrics.mGPUWait = 0;
metrics.mInstrumentedSleep = 0;
metrics.mInstrumentedGpuLatency = 0;
+ metrics.mMsBetweenSimStarts = 0;
}
+ // If the frame was displayed regardless of how it was produced, calculate the following
+ // metrics
if (displayed) {
metrics.mDisplayLatency = pmSession.TimestampDeltaToUnsignedMilliSeconds(metrics.mCPUStart, screenTime);
metrics.mDisplayedTime = pmSession.TimestampDeltaToUnsignedMilliSeconds(screenTime, nextScreenTime);
@@ -723,11 +771,46 @@ static void ReportMetricsHelper(
pmSession.TimestampDeltaToUnsignedMilliSeconds(p->AppRenderSubmitStartTime, screenTime);
metrics.mInstrumentedReadyTimeToDisplayLatency = pmSession.TimestampDeltaToUnsignedMilliSeconds(p->ReadyTime, screenTime);
// If there isn't a valid sleep end time use the sim start time
- auto xellStartTime = p->AppSleepEndTime != 0 ? p->AppSleepEndTime : p->AppSimStartTime;
+ auto InstrumentedStartTime = p->AppSleepEndTime != 0 ? p->AppSleepEndTime : p->AppSimStartTime;
// If neither the sleep end time or sim start time is valid, there is no
// way to calculate the Xell Gpu latency
- metrics.mInstrumentedDisplayLatency = xellStartTime == 0 ? 0 :
- pmSession.TimestampDeltaToUnsignedMilliSeconds(xellStartTime, screenTime);
+ metrics.mInstrumentedDisplayLatency = InstrumentedStartTime == 0 ? 0 :
+ pmSession.TimestampDeltaToUnsignedMilliSeconds(InstrumentedStartTime, screenTime);
+
+ metrics.mPcLatency = 0.f;
+ // Check to see if we have a valid pc latency sim start time
+ if (p->PclSimStartTime != 0) {
+ if (p->PclInputPingTime == 0) {
+ if (chain->mAccumulatedInput2FrameStartTime != 0) {
+ // This frame was displayed but we don't have a pc latency input time. However, there is accumulated time
+ // so there is a pending input that will now hit the screen. Add in the time from the last not
+ // displayed pc simulation start to this frame's pc simulation start.
+ chain->mAccumulatedInput2FrameStartTime +=
+ pmSession.TimestampDeltaToUnsignedMilliSeconds(chain->mLastReceivedNotDisplayedPclSimStart, p->PclSimStartTime);
+ // Add all of the accumlated time to the average input to frame start time.
+ pclI2FsManager.AddI2FsValueForProcess(
+ p->ProcessId,
+ chain->mLastReceivedNotDisplayedPclInputTime,
+ chain->mAccumulatedInput2FrameStartTime);
+ // Reset the tracking variables for when we have a dropped frame with a pc latency input
+ chain->mAccumulatedInput2FrameStartTime = 0.f;
+ chain->mLastReceivedNotDisplayedPclSimStart = 0;
+ chain->mLastReceivedNotDisplayedPclInputTime = 0;
+ }
+ } else {
+ pclI2FsManager.AddI2FsValueForProcess(
+ p->ProcessId,
+ p->PclInputPingTime,
+ pmSession.TimestampDeltaToUnsignedMilliSeconds(p->PclInputPingTime, p->PclSimStartTime));
+ }
+ }
+ // If we have a non-zero average input to frame start time and a PC Latency simulation
+ // start time calculate the PC Latency
+ auto i2Fs = pclI2FsManager.GetI2FsForProcess(p->ProcessId);
+ auto simStartTime = p->PclSimStartTime != 0 ? p->PclSimStartTime : chain->mLastSimStartTime;
+ if (i2Fs != 0.f && simStartTime != 0) {
+ metrics.mPcLatency = i2Fs + pmSession.TimestampDeltaToMilliSeconds(simStartTime, screenTime);
+ }
} else {
metrics.mDisplayLatency = 0;
metrics.mDisplayedTime = 0;
@@ -736,10 +819,36 @@ static void ReportMetricsHelper(
metrics.mInstrumentedRenderLatency = 0;
metrics.mInstrumentedReadyTimeToDisplayLatency = 0;
metrics.mInstrumentedDisplayLatency = 0;
+ metrics.mPcLatency = 0;
+ if (p->PclSimStartTime != 0) {
+ if (p->PclInputPingTime != 0) {
+ // This frame was dropped but we have valid pc latency input and simulation start
+ // times. Calculate the initial input to sim start time.
+ chain->mAccumulatedInput2FrameStartTime =
+ pmSession.TimestampDeltaToUnsignedMilliSeconds(p->PclInputPingTime, p->PclSimStartTime);
+ chain->mLastReceivedNotDisplayedPclInputTime = p->PclInputPingTime;
+ } else if (chain->mAccumulatedInput2FrameStartTime != 0.f) {
+ // This frame was also dropped and there is no pc latency input time. However, since we have
+ // accumulated time this means we have a pending input that has had multiple dropped frames
+ // and has not yet hit the screen. Calculate the time between the last not displayed sim start and
+ // this sim start and add it to our accumulated total
+ chain->mAccumulatedInput2FrameStartTime +=
+ pmSession.TimestampDeltaToUnsignedMilliSeconds(chain->mLastReceivedNotDisplayedPclSimStart, p->PclSimStartTime);
+ }
+ chain->mLastReceivedNotDisplayedPclSimStart = p->PclSimStartTime;
+ }
}
+ // The following metrics use both the frame's displayed and origin information.
+ metrics.mClickToPhotonLatency = 0;
+ metrics.mAllInputPhotonLatency = 0;
+ metrics.mAnimationError = 0;
+
if (displayIndex == appIndex) {
if (displayed) {
+ // For all input device metrics check to see if there were any previous device input times
+ // that were attached to a dropped frame and if so use the last received times for the
+ // metric calculations
auto updatedInputTime = chain->mLastReceivedNotDisplayedAllInputTime == 0 ? 0 :
pmSession.TimestampDeltaToUnsignedMilliSeconds(chain->mLastReceivedNotDisplayedAllInputTime, screenTime);
metrics.mAllInputPhotonLatency = p->InputTime == 0 ? updatedInputTime :
@@ -750,12 +859,38 @@ static void ReportMetricsHelper(
metrics.mClickToPhotonLatency = p->MouseClickTime == 0 ? updatedInputTime :
pmSession.TimestampDeltaToUnsignedMilliSeconds(p->MouseClickTime, screenTime);
+ // Reset all last received device times
chain->mLastReceivedNotDisplayedAllInputTime = 0;
chain->mLastReceivedNotDisplayedMouseClickTime = 0;
+
+ // Next calculate the animation error and animation time. First calculate the simulation
+ // start time. Simulation start can be either an app provided sim start time via the provider or
+ // PCL stats or, if not present,the cpu start.
+ uint64_t simStartTime = 0;
+ if (chain->mAnimationErrorSource == AnimationErrorSource::PCLatency) {
+ // If the pcl latency is the source of the animation error then use the pcl sim start time.
+ simStartTime = p->PclSimStartTime;
+ }
+ else if (chain->mAnimationErrorSource == AnimationErrorSource::AppProvider) {
+ // If the app provider is the source of the animation error then use the app sim start time.
+ simStartTime = p->AppSimStartTime;
+ }
+ else if (chain->mAnimationErrorSource == AnimationErrorSource::CpuStart) {
+ // If the cpu start time is the source of the animation error then use the cpu start time.
+ simStartTime = metrics.mCPUStart;
+ }
+
+ if (chain->mLastDisplayedSimStartTime != 0) {
+ // If the simulation start time is less than the last displayed simulation start time it means
+ // we are transitioning to app provider events.
+ if (simStartTime > chain->mLastDisplayedSimStartTime) {
+ metrics.mAnimationError = pmSession.TimestampDeltaToMilliSeconds(screenTime - chain->mLastDisplayedScreenTime,
+ simStartTime - chain->mLastDisplayedSimStartTime);
+ chain->mAnimationError.push_back(std::abs(metrics.mAnimationError));
+ }
+ }
}
else {
- metrics.mClickToPhotonLatency = 0;
- metrics.mAllInputPhotonLatency = 0;
if (p->InputTime != 0) {
chain->mLastReceivedNotDisplayedAllInputTime = p->InputTime;
}
@@ -763,19 +898,6 @@ static void ReportMetricsHelper(
chain->mLastReceivedNotDisplayedMouseClickTime = p->MouseClickTime;
}
}
- } else {
- metrics.mClickToPhotonLatency = 0;
- metrics.mAllInputPhotonLatency = 0;
- }
-
- if (displayed && displayIndex == appIndex && chain->mLastDisplayedSimStart != 0) {
- // Calculate the sim start time based on if AppSimStartTime is non-zero
- auto simStartTime = p->AppSimStartTime != 0 ? p->AppSimStartTime : metrics.mCPUStart;
- metrics.mAnimationError = pmSession.TimestampDeltaToMilliSeconds(screenTime - chain->mLastDisplayedAppScreenTime,
- simStartTime - chain->mLastDisplayedSimStart);
- chain->mAnimationError.push_back(std::abs(metrics.mAnimationError));
- } else {
- metrics.mAnimationError = 0;
}
if (p->DisplayedCount == 0) {
@@ -821,9 +943,12 @@ static void ReportMetricsHelper(
if (displayed) {
if (chain->mAppDisplayedTime.empty() || displayIndex == appIndex) {
chain->mAppDisplayedTime.push_back(metrics.mDisplayedTime);
- } else {
+ }
+ else {
chain->mAppDisplayedTime.back() += metrics.mDisplayedTime;
}
+ } else {
+ chain->mDropped .push_back(1.0);
}
if (displayed && displayIndex == appIndex) {
@@ -842,6 +967,9 @@ static void ReportMetricsHelper(
if (metrics.mInstrumentedReadyTimeToDisplayLatency != 0) {
chain->mInstrumentedReadyTimeToDisplayLatency.push_back(metrics.mInstrumentedReadyTimeToDisplayLatency);
}
+ if (metrics.mPcLatency != 0) {
+ chain->mMsPcLatency.push_back(metrics.mPcLatency);
+ }
}
displayIndex += 1;
@@ -852,6 +980,7 @@ static void ReportMetricsHelper(
static void ReportMetrics(
FakePMTraceSession const& pmSession,
+ InputToFsManager& pclI2FsManager,
fpsSwapChainData* chain,
PmNsmPresentEvent* p)
{
@@ -875,14 +1004,14 @@ static void ReportMetrics(
// well.
if (p->FinalState == PresentResult::Presented) {
for (auto& p2 : chain->mPendingPresents) {
- ReportMetricsHelper(pmSession, chain, &p2, p);
+ ReportMetricsHelper(pmSession, pclI2FsManager, chain, &p2, p);
}
- ReportMetricsHelper(pmSession, chain, p, nullptr);
+ ReportMetricsHelper(pmSession, pclI2FsManager, chain, p, nullptr);
chain->mPendingPresents.clear();
chain->mPendingPresents.push_back(*p);
} else {
if (chain->mPendingPresents.empty()) {
- ReportMetricsHelper(pmSession, chain, p, nullptr);
+ ReportMetricsHelper(pmSession, pclI2FsManager, chain, p, nullptr);
} else {
chain->mPendingPresents.push_back(*p);
}
@@ -982,9 +1111,9 @@ static void ReportMetrics(
// The following code block copied from: PresentMon/OutputThread.cpp
if (chain->mLastPresentIsValid) {
- ReportMetrics(pmSession, chain, presentEvent);
+ ReportMetrics(pmSession, mPclI2FsManager, chain, presentEvent);
} else {
- UpdateChain(chain, *presentEvent);
+ pmon::mid::UpdateChain(chain, *presentEvent);
}
// end
}
@@ -1184,14 +1313,20 @@ static void ReportMetrics(
SetActiveGraphicsAdapter(*devId);
}
- uint64_t simStartTime = 0;
- auto iter = appSimStartTime.find(processId);
- if (iter != appSimStartTime.end()) {
- simStartTime = iter->second;
+ FrameTimingData currentFrameTimingData{};
+ auto iter = frameTimingData.find(processId);
+ if (iter != frameTimingData.end()) {
+ currentFrameTimingData = iter->second;
}
+ FakePMTraceSession pmSession;
+ pmSession.mMilliSecondsPerTimestamp = 1000.0 / pShmClient->GetQpcFrequency().QuadPart;
+
// context transmits various data that applies to each gather command in the query
- PM_FRAME_QUERY::Context ctx{ nsm_hdr->start_qpc, pShmClient->GetQpcFrequency().QuadPart, simStartTime };
+ PM_FRAME_QUERY::Context ctx{
+ nsm_hdr->start_qpc,
+ pShmClient->GetQpcFrequency().QuadPart,
+ currentFrameTimingData };
while (frames_copied < frames_to_copy) {
const PmNsmFrameData* pCurrentFrameData = nullptr;
@@ -1221,16 +1356,44 @@ static void ReportMetrics(
pFrameDataOfLastAppDisplayed,
pFrameDataOfPreviousAppFrameOfLastAppDisplayed);
- if (simStartTime == 0 && ctx.firstAppSimStartTime != 0) {
- simStartTime = ctx.firstAppSimStartTime;
- }
-
if (ctx.dropped && ctx.pSourceFrameData->present_event.DisplayedCount == 0) {
pQuery->GatherToBlob(ctx, pBlob);
pBlob += pQuery->GetBlobSize();
frames_copied++;
} else {
while (ctx.sourceFrameDisplayIndex < ctx.pSourceFrameData->present_event.DisplayedCount) {
+ if (ctx.pSourceFrameData->present_event.PclSimStartTime != 0) {
+ // If we are calculating PC Latency then we need to update the input to frame start
+ // time.
+ if (ctx.pSourceFrameData->present_event.PclInputPingTime == 0) {
+ if (ctx.mAccumulatedInput2FrameStartTime != 0) {
+ // This frame was displayed but we don't have a pc latency input time. However, there is accumulated time
+ // so there is a pending input that will now hit the screen. Add in the time from the last not
+ // displayed pc simulation start to this frame's pc simulation start.
+ ctx.mAccumulatedInput2FrameStartTime +=
+ pmSession.TimestampDeltaToUnsignedMilliSeconds(
+ ctx.mLastReceivedNotDisplayedPclSimStart,
+ ctx.pSourceFrameData->present_event.PclSimStartTime);
+ // Add all of the accumlated time to the average input to frame start time.
+ mPclI2FsManager.AddI2FsValueForProcess(
+ ctx.pSourceFrameData->present_event.ProcessId,
+ ctx.mLastReceivedNotDisplayedPclInputTime,
+ ctx.mAccumulatedInput2FrameStartTime);
+ // Reset the tracking variables for when we have a dropped frame with a pc latency input
+ ctx.mAccumulatedInput2FrameStartTime = 0.f;
+ ctx.mLastReceivedNotDisplayedPclSimStart = 0;
+ ctx.mLastReceivedNotDisplayedPclInputTime = 0;
+ }
+ } else {
+ mPclI2FsManager.AddI2FsValueForProcess(
+ ctx.pSourceFrameData->present_event.ProcessId,
+ ctx.pSourceFrameData->present_event.PclInputPingTime,
+ pmSession.TimestampDeltaToUnsignedMilliSeconds(
+ ctx.pSourceFrameData->present_event.PclInputPingTime,
+ ctx.pSourceFrameData->present_event.PclSimStartTime));
+ }
+ }
+ ctx.avgInput2Fs = mPclI2FsManager.GetI2FsForProcess(ctx.pSourceFrameData->present_event.ProcessId);
pQuery->GatherToBlob(ctx, pBlob);
pBlob += pQuery->GetBlobSize();
frames_copied++;
@@ -1247,9 +1410,16 @@ static void ReportMetrics(
}
// Set to the actual number of frames copied
numFrames = frames_copied;
- if (simStartTime != 0) {
- appSimStartTime[processId] = simStartTime;
+ // Trim off any old flip delay data that resides in the FrameTimingData::flipDelayDataMap map
+ // that is older than the last displayed frame id.
+ for (auto it = ctx.frameTimingData.flipDelayDataMap.begin(); it != ctx.frameTimingData.flipDelayDataMap.end();) {
+ if (it->first < ctx.frameTimingData.lastDisplayedFrameId) {
+ it = ctx.frameTimingData.flipDelayDataMap.erase(it); // Erase and move to the next element
+ } else {
+ ++it; // Move to the next element
+ }
}
+ frameTimingData[processId] = ctx.frameTimingData;
}
void ConcreteMiddleware::StopPlayback()
diff --git a/IntelPresentMon/PresentMonMiddleware/ConcreteMiddleware.h b/IntelPresentMon/PresentMonMiddleware/ConcreteMiddleware.h
index 22b81ac2..9130626c 100644
--- a/IntelPresentMon/PresentMonMiddleware/ConcreteMiddleware.h
+++ b/IntelPresentMon/PresentMonMiddleware/ConcreteMiddleware.h
@@ -7,6 +7,8 @@
#include
#include
#include "../CommonUtilities/Hash.h"
+#include "../CommonUtilities/Math.h"
+#include "FrameTimingData.h"
namespace pmapi::intro
{
@@ -21,6 +23,53 @@ namespace pmon::mid
uint64_t metricOffset = 0;
};
+ class InputToFsManager {
+ public:
+ void AddI2FsValueForProcess(uint32_t processId, uint64_t timeStamp, double value) {
+ auto it = mProcessIdToI2FsValue.find(processId);
+ if (it == mProcessIdToI2FsValue.end()) {
+ auto firstEmaValue = pmon::util::CalculateEma(
+ 0.,
+ value,
+ mEmaAlpha);
+ it = mProcessIdToI2FsValue.emplace(processId, I2FsValueContainer{ firstEmaValue, timeStamp }).first;
+ return;
+ }
+ if (timeStamp > it->second.timestamp) {
+ it->second.i2FsValue = pmon::util::CalculateEma(
+ it->second.i2FsValue,
+ value,
+ mEmaAlpha);
+ it->second.timestamp = timeStamp;
+ }
+ }
+
+ // Retrieve the current input to frame start for a given process id.
+ double GetI2FsForProcess(uint32_t processId) const {
+ auto it = mProcessIdToI2FsValue.find(processId);
+ if (it == mProcessIdToI2FsValue.end()) {
+ return 0.f;
+ }
+ return it->second.i2FsValue;
+ }
+
+ // Remove a process from the map if it�s no longer needed.
+ void RemoveProcess(uint32_t processId) {
+ mProcessIdToI2FsValue.erase(processId);
+ }
+
+ private:
+ struct I2FsValueContainer {
+ double i2FsValue = 0.f;
+ uint64_t timestamp = 0;
+ };
+
+ double const mEmaAlpha = 0.1;
+
+ std::map mProcessIdToI2FsValue; // Map from a process id to the current input to frame start value.
+ };
+
+
// Copied from: PresentMon/PresentMon.hpp
// We store SwapChainData per process and per swapchain, where we maintain:
// - information on previous presents needed for console output or to compute metrics for upcoming
@@ -74,15 +123,28 @@ namespace pmon::mid
// QPC of last received input data that did not make it to the screen due
// to the Present() being dropped
- uint64_t mLastReceivedNotDisplayedAllInputTime;
- uint64_t mLastReceivedNotDisplayedMouseClickTime;
+ uint64_t mLastReceivedNotDisplayedAllInputTime = 0;
+ uint64_t mLastReceivedNotDisplayedMouseClickTime = 0;
+ // QPC of the last PC Latency simulation start
+ uint64_t mLastReceivedNotDisplayedPclSimStart = 0;
+ uint64_t mLastReceivedNotDisplayedPclInputTime = 0;
+
+ // Animation error source. Start with CPU start QPC and switch if
+ // we receive a valid PCL or App Provider simulation start time.
+ AnimationErrorSource mAnimationErrorSource = AnimationErrorSource::CpuStart;
+
+ // Accumulated PC latency input to frame start time due to the
+ // Present() being dropped
+ double mAccumulatedInput2FrameStartTime = 0.f;
// begin/end screen times to optimize average calculation:
uint64_t mLastDisplayedScreenTime = 0; // The last presented frame's ScreenTime (qpc)
uint64_t mLastDisplayedAppScreenTime = 0; // The last presented app frame's ScreenTime (qpc)
uint64_t display_0_screen_time = 0; // The first presented frame's ScreenTime (qpc)
- uint64_t mLastDisplayedSimStart = 0; // The simulation start of the last presented frame
+ uint64_t mLastDisplayedSimStartTime = 0; // The simulation start of the last displayed frame
uint32_t display_count = 0; // The number of presented frames
+ // QPC of the last simulation start time iregardless of whether it was displayed or not
+ uint64_t mLastSimStartTime = 0;
};
struct DeviceInfo
@@ -151,8 +213,8 @@ namespace pmon::mid
uint32_t clientProcessId = 0;
// Stream clients mapping to process id
std::map> presentMonStreamClients;
- // App sim start time for each process id
- std::map appSimStartTime;
+ // Frame timing data for each process id
+ std::map frameTimingData;
std::unique_ptr pComms;
// Dynamic query handle to frame data delta
std::unordered_map, uint64_t> queryFrameDataDeltas;
@@ -163,5 +225,6 @@ namespace pmon::mid
uint32_t currentGpuInfoIndex = UINT32_MAX;
std::optional activeDevice;
std::unique_ptr pIntroRoot;
+ InputToFsManager mPclI2FsManager;
};
}
diff --git a/IntelPresentMon/PresentMonMiddleware/FrameEventQuery.cpp b/IntelPresentMon/PresentMonMiddleware/FrameEventQuery.cpp
index 483cf95d..a15cc945 100644
--- a/IntelPresentMon/PresentMonMiddleware/FrameEventQuery.cpp
+++ b/IntelPresentMon/PresentMonMiddleware/FrameEventQuery.cpp
@@ -409,8 +409,13 @@ namespace
return;
}
if (ctx.sourceFrameDisplayIndex == ctx.appIndex) {
+ auto ScreenTime = ctx.pSourceFrameData->present_event.Displayed_ScreenTime[ctx.sourceFrameDisplayIndex];
+ auto ii = ctx.frameTimingData.flipDelayDataMap.find(ctx.pSourceFrameData->present_event.FrameId);
+ if (ii != ctx.frameTimingData.flipDelayDataMap.end()) {
+ ScreenTime = ii->second.displayQpc;
+ }
const auto val = TimestampDeltaToUnsignedMilliSeconds(start,
- ctx.pSourceFrameData->present_event.Displayed_ScreenTime[ctx.sourceFrameDisplayIndex], ctx.performanceCounterPeriodMs);
+ ScreenTime, ctx.performanceCounterPeriodMs);
reinterpret_cast(pDestBlob[outputOffset_]) = val;
}
else
@@ -458,7 +463,7 @@ namespace
private:
uint32_t outputOffset_;
};
- template
+ template
class StartDifferenceGatherCommand_ : public pmon::mid::GatherCommand_
{
public:
@@ -469,36 +474,11 @@ namespace
}
void Gather(Context& ctx, uint8_t* pDestBlob) const override
{
- if constexpr (calcAnimationTime) {
- if constexpr (doDroppedCheck) {
- if (ctx.dropped) {
- reinterpret_cast(pDestBlob[outputOffset_]) = std::numeric_limits::quiet_NaN();
- return;
- }
- }
- // Calculate the current frame's displayed time
- auto ScreenTime = ctx.pSourceFrameData->present_event.Displayed_ScreenTime[ctx.sourceFrameDisplayIndex];
- auto NextScreenTime = ctx.sourceFrameDisplayIndex == ctx.pSourceFrameData->present_event.DisplayedCount - 1
- ? ctx.nextDisplayedQpc
- : ctx.pSourceFrameData->present_event.Displayed_ScreenTime[ctx.sourceFrameDisplayIndex + 1];
- const auto displayedTime = TimestampDeltaToUnsignedMilliSeconds(ScreenTime, NextScreenTime, ctx.performanceCounterPeriodMs);
- if (ctx.sourceFrameDisplayIndex != ctx.appIndex ||
- displayedTime == 0.0) {
- reinterpret_cast(pDestBlob[outputOffset_]) = std::numeric_limits::quiet_NaN();
- return;
- }
- const auto firstSimStartTime = ctx.firstAppSimStartTime != 0 ? ctx.firstAppSimStartTime :
- ctx.qpcStart;
- const auto currentSimTime = ctx.pSourceFrameData->present_event.*pEnd != 0 ? ctx.pSourceFrameData->present_event.*pEnd :
- ctx.cpuStart;
- const auto val = TimestampDeltaToUnsignedMilliSeconds(firstSimStartTime, currentSimTime, ctx.performanceCounterPeriodMs);
- reinterpret_cast(pDestBlob[outputOffset_]) = val;
- } else if constexpr (calcPresentStartTime) {
+ if constexpr (calcPresentStartTime) {
const auto qpcDuration = ctx.pSourceFrameData->present_event.*pEnd - ctx.qpcStart;
const auto val = ctx.performanceCounterPeriodMs * double(qpcDuration);
reinterpret_cast(pDestBlob[outputOffset_]) = val;
- }
- else {
+ } else {
const auto qpcDuration = ctx.cpuStart - ctx.qpcStart;
const auto val = ctx.performanceCounterPeriodMs * double(qpcDuration);
reinterpret_cast(pDestBlob[outputOffset_]) = val;
@@ -611,6 +591,10 @@ namespace
// Calculate the current frame's displayed time
auto ScreenTime = ctx.pSourceFrameData->present_event.Displayed_ScreenTime[ctx.sourceFrameDisplayIndex];
+ auto ii = ctx.frameTimingData.flipDelayDataMap.find(ctx.pSourceFrameData->present_event.FrameId);
+ if (ii != ctx.frameTimingData.flipDelayDataMap.end()) {
+ ScreenTime = ii->second.displayQpc;
+ }
auto NextScreenTime = ctx.sourceFrameDisplayIndex == ctx.pSourceFrameData->present_event.DisplayedCount - 1
? ctx.nextDisplayedQpc
: ctx.pSourceFrameData->present_event.Displayed_ScreenTime[ctx.sourceFrameDisplayIndex + 1];
@@ -664,6 +648,10 @@ namespace
// Calculate the current frame's displayed time
auto ScreenTime = ctx.pSourceFrameData->present_event.Displayed_ScreenTime[ctx.sourceFrameDisplayIndex];
+ auto ii = ctx.frameTimingData.flipDelayDataMap.find(ctx.pSourceFrameData->present_event.FrameId);
+ if (ii != ctx.frameTimingData.flipDelayDataMap.end()) {
+ ScreenTime = ii->second.displayQpc;
+ }
auto NextScreenTime = ctx.sourceFrameDisplayIndex == ctx.pSourceFrameData->present_event.DisplayedCount - 1
? ctx.nextDisplayedQpc
: ctx.pSourceFrameData->present_event.Displayed_ScreenTime[ctx.sourceFrameDisplayIndex + 1];
@@ -770,6 +758,10 @@ namespace
return;
}
auto ScreenTime = ctx.pSourceFrameData->present_event.Displayed_ScreenTime[ctx.sourceFrameDisplayIndex];
+ auto ii = ctx.frameTimingData.flipDelayDataMap.find(ctx.pSourceFrameData->present_event.FrameId);
+ if (ii != ctx.frameTimingData.flipDelayDataMap.end()) {
+ ScreenTime = ii->second.displayQpc;
+ }
auto NextScreenTime = ctx.sourceFrameDisplayIndex == ctx.pSourceFrameData->present_event.DisplayedCount - 1
? ctx.nextDisplayedQpc
: ctx.pSourceFrameData->present_event.Displayed_ScreenTime[ctx.sourceFrameDisplayIndex + 1];
@@ -817,13 +809,18 @@ namespace
}
}
if constexpr (doZeroCheck) {
- if (ctx.previousDisplayedSimStartQpc == 0 && ctx.lastDisplayedCpuStart == 0) {
- reinterpret_cast(pDestBlob[outputOffset_]) = 0.0;
+ if (ctx.frameTimingData.lastDisplayedAppSimStartTime == 0 && ctx.lastDisplayedCpuStart == 0) {
+ reinterpret_cast(pDestBlob[outputOffset_]) =
+ std::numeric_limits::quiet_NaN();
return;
}
}
if (ctx.sourceFrameDisplayIndex == ctx.appIndex) {
auto ScreenTime = ctx.pSourceFrameData->present_event.Displayed_ScreenTime[ctx.sourceFrameDisplayIndex];
+ auto ii = ctx.frameTimingData.flipDelayDataMap.find(ctx.pSourceFrameData->present_event.FrameId);
+ if (ii != ctx.frameTimingData.flipDelayDataMap.end()) {
+ ScreenTime = ii->second.displayQpc;
+ }
auto NextScreenTime = ctx.sourceFrameDisplayIndex == ctx.pSourceFrameData->present_event.DisplayedCount - 1
? ctx.nextDisplayedQpc
: ctx.pSourceFrameData->present_event.Displayed_ScreenTime[ctx.sourceFrameDisplayIndex + 1];
@@ -833,21 +830,36 @@ namespace
std::numeric_limits::quiet_NaN();
return;
}
- auto PrevScreenTime = ctx.previousDisplayedAppQpc; // Always use application display time for animation error
- auto SimStartTime = ctx.pSourceFrameData->present_event.AppSimStartTime != 0 ?
- ctx.pSourceFrameData->present_event.AppSimStartTime :
- ctx.cpuStart;
- auto PrevSimStartTime = ctx.previousDisplayedSimStartQpc != 0 ?
- ctx.previousDisplayedSimStartQpc :
+ auto PrevScreenTime = ctx.frameTimingData.lastDisplayedAppScreenTime;
+ // Next calculate the animation error. First calculate the simulation
+ // start time. Simulation start can be either an app provided sim start time via the provider or
+ // PCL stats or, if not present,the cpu start.
+ uint64_t simStartTime = 0;
+ if (ctx.frameTimingData.animationErrorSource == AnimationErrorSource::AppProvider &&
+ ctx.frameTimingData.lastDisplayedAppSimStartTime != 0) {
+ // If the app provider is the source of the animation error then use the app sim start time.
+ simStartTime = ctx.pSourceFrameData->present_event.AppSimStartTime;
+ }
+ else if (ctx.frameTimingData.animationErrorSource == AnimationErrorSource::PCLatency &&
+ ctx.frameTimingData.lastDisplayedAppSimStartTime != 0) {
+ // If the pcl latency is the source of the animation error then use the pcl sim start time.
+ simStartTime = ctx.pSourceFrameData->present_event.PclSimStartTime;
+ }
+ else if (ctx.frameTimingData.lastDisplayedAppSimStartTime == 0) {
+ // If the cpu start time is the source of the animation error then use the cpu start time.
+ simStartTime = ctx.cpuStart;
+ }
+ auto PrevSimStartTime = ctx.frameTimingData.lastDisplayedAppSimStartTime != 0 ?
+ ctx.frameTimingData.lastDisplayedAppSimStartTime :
ctx.lastDisplayedCpuStart;
// If the simulation start time is less than the last displated simulation start time it means
// we are transitioning to app provider events.
- if (SimStartTime > PrevSimStartTime) {
+ if (simStartTime > PrevSimStartTime) {
const auto val = TimestampDeltaToMilliSeconds(ScreenTime - PrevScreenTime,
- SimStartTime - PrevSimStartTime, ctx.performanceCounterPeriodMs);
+ simStartTime - PrevSimStartTime, ctx.performanceCounterPeriodMs);
reinterpret_cast(pDestBlob[outputOffset_]) = val;
} else {
- reinterpret_cast(pDestBlob[outputOffset_]) = 0.0;
+ reinterpret_cast(pDestBlob[outputOffset_]) = std::numeric_limits::quiet_NaN();
return;
}
}
@@ -872,6 +884,85 @@ namespace
uint32_t outputOffset_;
uint16_t outputPaddingSize_;
};
+ class AnimationTimeGatherCommand_ : public pmon::mid::GatherCommand_
+ {
+ public:
+ AnimationTimeGatherCommand_(size_t nextAvailableByteOffset)
+ {
+ outputPaddingSize_ = (uint16_t)util::GetPadding(nextAvailableByteOffset, alignof(double));
+ outputOffset_ = uint32_t(nextAvailableByteOffset) + outputPaddingSize_;
+ }
+ void Gather(Context& ctx, uint8_t* pDestBlob) const override
+ {
+ if (ctx.dropped) {
+ reinterpret_cast(pDestBlob[outputOffset_]) = std::numeric_limits::quiet_NaN();
+ return;
+ }
+
+ // Calculate the current frame's displayed time
+
+ // Check to see if the current present is collapsed and if so use the correct display qpc.
+ auto ScreenTime = ctx.pSourceFrameData->present_event.Displayed_ScreenTime[ctx.sourceFrameDisplayIndex];
+ auto ii = ctx.frameTimingData.flipDelayDataMap.find(ctx.pSourceFrameData->present_event.FrameId);
+ if (ii != ctx.frameTimingData.flipDelayDataMap.end()) {
+ ScreenTime = ii->second.displayQpc;
+ }
+ auto NextScreenTime = ctx.sourceFrameDisplayIndex == ctx.pSourceFrameData->present_event.DisplayedCount - 1
+ ? ctx.nextDisplayedQpc
+ : ctx.pSourceFrameData->present_event.Displayed_ScreenTime[ctx.sourceFrameDisplayIndex + 1];
+ const auto displayedTime = TimestampDeltaToUnsignedMilliSeconds(ScreenTime, NextScreenTime, ctx.performanceCounterPeriodMs);
+ if (ctx.sourceFrameDisplayIndex != ctx.appIndex ||
+ displayedTime == 0.0) {
+ reinterpret_cast(pDestBlob[outputOffset_]) = std::numeric_limits::quiet_NaN();
+ return;
+ }
+ const auto firstSimStartTime = ctx.frameTimingData.firstAppSimStartTime != 0 ?
+ ctx.frameTimingData.firstAppSimStartTime :
+ ctx.qpcStart;
+ uint64_t currentSimTime = 0;
+ if (ctx.frameTimingData.animationErrorSource == AnimationErrorSource::AppProvider) {
+ if (ctx.frameTimingData.lastDisplayedAppSimStartTime != 0) {
+ // If the app provider is the source of the animation error then use the app sim start time.
+ currentSimTime = ctx.pSourceFrameData->present_event.AppSimStartTime;
+ }
+ else {
+ reinterpret_cast(pDestBlob[outputOffset_]) = 0.;
+ return;
+ }
+ }
+ else if (ctx.frameTimingData.animationErrorSource == AnimationErrorSource::PCLatency) {
+ if (ctx.frameTimingData.lastDisplayedAppSimStartTime != 0) {
+ // If the pcl latency is the source of the animation error then use the pcl sim start time.
+ currentSimTime = ctx.pSourceFrameData->present_event.PclSimStartTime;
+ }
+ else {
+ reinterpret_cast(pDestBlob[outputOffset_]) = 0.;
+ return;
+ }
+ }
+ else if (ctx.frameTimingData.lastDisplayedAppSimStartTime == 0) {
+ // If the cpu start time is the source of the animation error then use the cpu start time.
+ currentSimTime = ctx.cpuStart;
+ }
+ const auto val = TimestampDeltaToUnsignedMilliSeconds(firstSimStartTime, currentSimTime, ctx.performanceCounterPeriodMs);
+ reinterpret_cast(pDestBlob[outputOffset_]) = val;
+ }
+ uint32_t GetBeginOffset() const override
+ {
+ return outputOffset_ - outputPaddingSize_;
+ }
+ uint32_t GetEndOffset() const override
+ {
+ return outputOffset_ + alignof(double);
+ }
+ uint32_t GetOutputOffset() const override
+ {
+ return outputOffset_;
+ }
+ private:
+ uint32_t outputOffset_;
+ uint16_t outputPaddingSize_;
+ };
class CpuFrameQpcFrameTimeCommand_ : public pmon::mid::GatherCommand_
{
public:
@@ -980,28 +1071,35 @@ namespace
}
}
+ // Check to see if the current present is collapsed and if so use the correct display qpc.
+ uint64_t displayQpc = ctx.pSourceFrameData->present_event.Displayed_ScreenTime[ctx.sourceFrameDisplayIndex];
+ auto ii = ctx.frameTimingData.flipDelayDataMap.find(ctx.pSourceFrameData->present_event.FrameId);
+ if (ii != ctx.frameTimingData.flipDelayDataMap.end()) {
+ displayQpc = ii->second.displayQpc;
+ }
+
double updatedInputTime = 0.;
double val = 0.;
if (ctx.sourceFrameDisplayIndex == ctx.appIndex) {
if (isMouseClick) {
updatedInputTime = ctx.lastReceivedNotDisplayedClickQpc == 0 ? 0. :
TimestampDeltaToUnsignedMilliSeconds(ctx.lastReceivedNotDisplayedClickQpc,
- ctx.pSourceFrameData->present_event.Displayed_ScreenTime[ctx.sourceFrameDisplayIndex],
+ displayQpc,
ctx.performanceCounterPeriodMs);
val = ctx.pSourceFrameData->present_event.*pStart == 0 ? updatedInputTime :
TimestampDeltaToUnsignedMilliSeconds(ctx.pSourceFrameData->present_event.*pStart,
- ctx.pSourceFrameData->present_event.Displayed_ScreenTime[ctx.sourceFrameDisplayIndex],
+ displayQpc,
ctx.performanceCounterPeriodMs);
ctx.lastReceivedNotDisplayedClickQpc = 0;
}
else {
updatedInputTime = ctx.lastReceivedNotDisplayedAllInputTime == 0 ? 0. :
TimestampDeltaToUnsignedMilliSeconds(ctx.lastReceivedNotDisplayedAllInputTime,
- ctx.pSourceFrameData->present_event.Displayed_ScreenTime[ctx.sourceFrameDisplayIndex],
+ displayQpc,
ctx.performanceCounterPeriodMs);
val = ctx.pSourceFrameData->present_event.*pStart == 0 ? updatedInputTime :
TimestampDeltaToUnsignedMilliSeconds(ctx.pSourceFrameData->present_event.*pStart,
- ctx.pSourceFrameData->present_event.Displayed_ScreenTime[ctx.sourceFrameDisplayIndex],
+ displayQpc,
ctx.performanceCounterPeriodMs);
ctx.lastReceivedNotDisplayedAllInputTime = 0;
}
@@ -1031,6 +1129,171 @@ namespace
uint32_t outputOffset_;
uint16_t outputPaddingSize_;
};
+ class PcLatencyGatherCommand_ : public pmon::mid::GatherCommand_
+ {
+ public:
+ PcLatencyGatherCommand_(size_t nextAvailableByteOffset)
+ {
+ outputPaddingSize_ = (uint16_t)util::GetPadding(nextAvailableByteOffset, alignof(double));
+ outputOffset_ = uint32_t(nextAvailableByteOffset) + outputPaddingSize_;
+ }
+ void Gather(Context& ctx, uint8_t* pDestBlob) const override
+ {
+ if (ctx.dropped) {
+ reinterpret_cast(pDestBlob[outputOffset_]) =
+ std::numeric_limits::quiet_NaN();
+ return;
+ }
+
+ double val = 0.;
+ auto simStartTime = ctx.pSourceFrameData->present_event.PclSimStartTime != 0 ?
+ ctx.pSourceFrameData->present_event.PclSimStartTime :
+ ctx.frameTimingData.lastAppSimStartTime;
+ if (ctx.avgInput2Fs == 0. || simStartTime == 0) {
+ reinterpret_cast(pDestBlob[outputOffset_]) =
+ std::numeric_limits::quiet_NaN();
+ return;
+ }
+
+ // Check to see if the current present is collapsed and if so use the correct display qpc.
+ uint64_t displayQpc = ctx.pSourceFrameData->present_event.Displayed_ScreenTime[ctx.sourceFrameDisplayIndex];
+ auto ii = ctx.frameTimingData.flipDelayDataMap.find(ctx.pSourceFrameData->present_event.FrameId);
+ if (ii != ctx.frameTimingData.flipDelayDataMap.end()) {
+ displayQpc = ii->second.displayQpc;
+ }
+
+ val = ctx.avgInput2Fs +
+ TimestampDeltaToUnsignedMilliSeconds(simStartTime,
+ displayQpc,
+ ctx.performanceCounterPeriodMs);
+
+ if (val == 0.) {
+ reinterpret_cast(pDestBlob[outputOffset_]) =
+ std::numeric_limits::quiet_NaN();
+ }
+ else {
+ reinterpret_cast(pDestBlob[outputOffset_]) = val;
+ }
+ }
+ uint32_t GetBeginOffset() const override
+ {
+ return outputOffset_ - outputPaddingSize_;
+ }
+ uint32_t GetEndOffset() const override
+ {
+ return outputOffset_ + alignof(double);
+ }
+ uint32_t GetOutputOffset() const override
+ {
+ return outputOffset_;
+ }
+ private:
+ uint32_t outputOffset_;
+ uint16_t outputPaddingSize_;
+ };
+ class BetweenSimStartsGatherCommand_ : public pmon::mid::GatherCommand_
+ {
+ public:
+ BetweenSimStartsGatherCommand_(size_t nextAvailableByteOffset)
+ {
+ outputPaddingSize_ = (uint16_t)util::GetPadding(nextAvailableByteOffset, alignof(double));
+ outputOffset_ = uint32_t(nextAvailableByteOffset) + outputPaddingSize_;
+ }
+ void Gather(Context& ctx, uint8_t* pDestBlob) const override
+ {
+ double val = 0.;
+ uint64_t currentSimStartTime = 0;
+ if (ctx.pSourceFrameData->present_event.PclSimStartTime != 0) {
+ currentSimStartTime = ctx.pSourceFrameData->present_event.PclSimStartTime;
+ } else if (ctx.pSourceFrameData->present_event.AppSimStartTime != 0) {
+ currentSimStartTime = ctx.pSourceFrameData->present_event.AppSimStartTime;
+ }
+
+ if (ctx.frameTimingData.lastAppSimStartTime == 0 || currentSimStartTime == 0) {
+ reinterpret_cast(pDestBlob[outputOffset_]) =
+ std::numeric_limits::quiet_NaN();
+ return;
+ }
+
+ val = TimestampDeltaToUnsignedMilliSeconds(
+ ctx.frameTimingData.lastAppSimStartTime, currentSimStartTime,
+ ctx.performanceCounterPeriodMs);
+
+ if (val == 0.) {
+ reinterpret_cast(pDestBlob[outputOffset_]) =
+ std::numeric_limits::quiet_NaN();
+ }
+ else {
+ reinterpret_cast(pDestBlob[outputOffset_]) = val;
+ }
+ }
+ uint32_t GetBeginOffset() const override
+ {
+ return outputOffset_ - outputPaddingSize_;
+ }
+ uint32_t GetEndOffset() const override
+ {
+ return outputOffset_ + alignof(double);
+ }
+ uint32_t GetOutputOffset() const override
+ {
+ return outputOffset_;
+ }
+ private:
+ uint32_t outputOffset_;
+ uint16_t outputPaddingSize_;
+ };
+ class FlipDelayGatherCommand_ : public pmon::mid::GatherCommand_
+ {
+ public:
+ FlipDelayGatherCommand_(size_t nextAvailableByteOffset)
+ {
+ outputPaddingSize_ = (uint16_t)util::GetPadding(nextAvailableByteOffset, alignof(double));
+ outputOffset_ = uint32_t(nextAvailableByteOffset) + outputPaddingSize_;
+ }
+ void Gather(Context& ctx, uint8_t* pDestBlob) const override
+ {
+
+ if (ctx.dropped) {
+ reinterpret_cast(pDestBlob[outputOffset_]) =
+ std::numeric_limits::quiet_NaN();
+ return;
+ }
+
+ // Calculate the current frame's flip delay
+ uint64_t flipDelay = ctx.pSourceFrameData->present_event.FlipDelay;
+ auto ii = ctx.frameTimingData.flipDelayDataMap.find(ctx.pSourceFrameData->present_event.FrameId);
+ if (ii != ctx.frameTimingData.flipDelayDataMap.end()) {
+ flipDelay = ii->second.flipDelay;
+ }
+
+ double val = 0.;
+ val = TimestampDeltaToMilliSeconds(flipDelay, ctx.performanceCounterPeriodMs);
+
+ if (val == 0.) {
+ reinterpret_cast(pDestBlob[outputOffset_]) =
+ std::numeric_limits::quiet_NaN();
+ }
+ else {
+ reinterpret_cast(pDestBlob[outputOffset_]) = val;
+ }
+ }
+ uint32_t GetBeginOffset() const override
+ {
+ return outputOffset_ - outputPaddingSize_;
+ }
+ uint32_t GetEndOffset() const override
+ {
+ return outputOffset_ + alignof(double);
+ }
+ uint32_t GetOutputOffset() const override
+ {
+ return outputOffset_;
+ }
+ private:
+ uint32_t outputOffset_;
+ uint16_t outputPaddingSize_;
+ };
}
PM_FRAME_QUERY::PM_FRAME_QUERY(std::span queryElements)
@@ -1188,7 +1451,7 @@ std::unique_ptr PM_FRAME_QUERY::MapQueryElementToGatherComm
case PM_METRIC_PRESENT_FLAGS:
return std::make_unique>(pos);
case PM_METRIC_CPU_START_TIME:
- return std::make_unique>(pos);
+ return std::make_unique>(pos);
case PM_METRIC_CPU_FRAME_TIME:
case PM_METRIC_BETWEEN_APP_START:
return std::make_unique(pos);
@@ -1205,7 +1468,7 @@ std::unique_ptr PM_FRAME_QUERY::MapQueryElementToGatherComm
case PM_METRIC_ANIMATION_ERROR:
return std::make_unique>(pos);
case PM_METRIC_ANIMATION_TIME:
- return std::make_unique>(pos);
+ return std::make_unique(pos);
case PM_METRIC_GPU_LATENCY:
return std::make_unique>(pos);
case PM_METRIC_DISPLAY_LATENCY:
@@ -1217,7 +1480,7 @@ std::unique_ptr PM_FRAME_QUERY::MapQueryElementToGatherComm
case PM_METRIC_INSTRUMENTED_LATENCY:
return std::make_unique>(pos);
case PM_METRIC_PRESENT_START_TIME:
- return std::make_unique>(pos);
+ return std::make_unique>(pos);
case PM_METRIC_PRESENT_START_QPC:
return std::make_unique>(pos);
case PM_METRIC_IN_PRESENT_API:
@@ -1231,9 +1494,11 @@ std::unique_ptr PM_FRAME_QUERY::MapQueryElementToGatherComm
case PM_METRIC_RENDER_PRESENT_LATENCY:
return std::make_unique>(pos);
case PM_METRIC_BETWEEN_SIMULATION_START:
- return std::make_unique(pos);
+ return std::make_unique(pos);
case PM_METRIC_PC_LATENCY:
- return std::make_unique(pos);
+ return std::make_unique(pos);
+ case PM_METRIC_FLIP_DELAY:
+ return std::make_unique(pos);
default:
pmlog_error("unknown metric id").pmwatch((int)q.metric).diag();
return {};
@@ -1258,9 +1523,34 @@ void PM_FRAME_QUERY::Context::UpdateSourceData(const PmNsmFrameData* pSourceFram
if (pSourceFrameData->present_event.InputTime != 0) {
lastReceivedNotDisplayedAllInputTime = pSourceFrameData->present_event.InputTime;
}
+ if (pSourceFrameData->present_event.PclSimStartTime != 0) {
+ if (pSourceFrameData->present_event.PclInputPingTime != 0) {
+ // This frame was dropped but we have valid pc latency input and simulation start
+ // times. Calculate the initial input to sim start time.
+ mAccumulatedInput2FrameStartTime =
+ TimestampDeltaToUnsignedMilliSeconds(
+ pSourceFrameData->present_event.PclInputPingTime,
+ pSourceFrameData->present_event.PclSimStartTime,
+ performanceCounterPeriodMs);
+ mLastReceivedNotDisplayedPclInputTime = pSourceFrameData->present_event.PclInputPingTime;
+ }
+ else if (mAccumulatedInput2FrameStartTime != 0.f) {
+ // This frame was also dropped and there is no pc latency input time. However, since we have
+ // accumulated time this means we have a pending input that has had multiple dropped frames
+ // and has not yet hit the screen. Calculate the time between the last not displayed sim start and
+ // this sim start and add it to our accumulated total
+ mAccumulatedInput2FrameStartTime +=
+ TimestampDeltaToUnsignedMilliSeconds(
+ mLastReceivedNotDisplayedPclSimStart,
+ pSourceFrameData->present_event.PclSimStartTime,
+ performanceCounterPeriodMs);
+ }
+ mLastReceivedNotDisplayedPclSimStart = pSourceFrameData->present_event.PclSimStartTime;
+ }
}
- if (firstAppSimStartTime == 0) {
+ AnimationErrorSource initAmimationErrorSource = frameTimingData.animationErrorSource;
+ if (frameTimingData.firstAppSimStartTime == 0) {
// Handle this rare case at the start of consuming frames and the application is
// producing app frame data:
// [0] Frame - Not Dropped - Valid App Data -> Start of raw frame data
@@ -1270,12 +1560,25 @@ void PM_FRAME_QUERY::Context::UpdateSourceData(const PmNsmFrameData* pSourceFram
// and therefore not enter this function to update source the data. However the correct
// app sim start time is at [0] regardless if [1] or [2] are dropped or not
if (pFrameDataOfLastDisplayed) {
- firstAppSimStartTime = pFrameDataOfLastDisplayed->present_event.AppSimStartTime;
+ if (pFrameDataOfLastDisplayed->present_event.AppSimStartTime != 0) {
+ frameTimingData.firstAppSimStartTime = pFrameDataOfLastDisplayed->present_event.AppSimStartTime;
+ frameTimingData.animationErrorSource = AnimationErrorSource::AppProvider;
+ } else if (pFrameDataOfLastDisplayed->present_event.PclSimStartTime != 0){
+ frameTimingData.firstAppSimStartTime = pFrameDataOfLastDisplayed->present_event.PclSimStartTime;
+ frameTimingData.animationErrorSource = AnimationErrorSource::PCLatency;
+ }
}
// In the case where [0] does not set the firstAppSimStartTime and the current frame is
// either [1] or [2] and is not dropped set the firstAppSimStartTime
- if (firstAppSimStartTime == 0 && !dropped) {
- firstAppSimStartTime = pSourceFrameData->present_event.AppSimStartTime;
+ if (frameTimingData.firstAppSimStartTime == 0 && !dropped) {
+ if (pSourceFrameData->present_event.AppSimStartTime != 0) {
+ frameTimingData.firstAppSimStartTime = pSourceFrameData->present_event.AppSimStartTime;
+ frameTimingData.animationErrorSource = AnimationErrorSource::AppProvider;
+ }
+ else if (pSourceFrameData->present_event.PclSimStartTime != 0) {
+ frameTimingData.firstAppSimStartTime = pSourceFrameData->present_event.PclSimStartTime;
+ frameTimingData.animationErrorSource = AnimationErrorSource::PCLatency;
+ }
}
}
@@ -1295,6 +1598,11 @@ void PM_FRAME_QUERY::Context::UpdateSourceData(const PmNsmFrameData* pSourceFram
cpuStart = pFrameDataOfLastAppPresented->present_event.PresentStartTime +
pFrameDataOfLastAppPresented->present_event.TimeInPresent;
}
+ if (pFrameDataOfLastPresented->present_event.PclSimStartTime != 0) {
+ frameTimingData.lastAppSimStartTime = pFrameDataOfLastAppPresented->present_event.PclSimStartTime;
+ } else if (pFrameDataOfLastPresented->present_event.AppSimStartTime != 0) {
+ frameTimingData.lastAppSimStartTime = pFrameDataOfLastAppPresented->present_event.AppSimStartTime;
+ }
}
else {
// TODO: log issue or invalidate related columns or drop frame (or some combination)
@@ -1303,7 +1611,35 @@ void PM_FRAME_QUERY::Context::UpdateSourceData(const PmNsmFrameData* pSourceFram
}
if (pFrameDataOfNextDisplayed) {
- nextDisplayedQpc = pFrameDataOfNextDisplayed->present_event.Displayed_ScreenTime[0];
+ if (!dropped) {
+ uint64_t flipDelay = 0;
+ uint64_t currentDisplayQpc = 0;
+ uint64_t nextDisplayQpc = 0;
+ // Check to see if the current frame had it's flip delay and display qpc set due to a
+ // collapsed present. If so use those values to calculate the next displayed qpc.
+ auto ii = frameTimingData.flipDelayDataMap.find(pSourceFrameData->present_event.FrameId);
+ if (ii != frameTimingData.flipDelayDataMap.end()) {
+ flipDelay = ii->second.flipDelay;
+ currentDisplayQpc = ii->second.displayQpc;
+ } else {
+ flipDelay = pSourceFrameData->present_event.FlipDelay;
+ currentDisplayQpc = pSourceFrameData->present_event.Displayed_ScreenTime[0];
+ }
+ if (flipDelay != 0 && (currentDisplayQpc > pFrameDataOfNextDisplayed->present_event.Displayed_ScreenTime[0])) {
+ // The next displayed frame is a collapsed present. Update the flip delay data map with the
+ // current frame's flip delay and display qpc.
+ FlipDelayData flipDelayData {};
+ flipDelayData.flipDelay = pFrameDataOfNextDisplayed->present_event.FlipDelay +
+ (currentDisplayQpc - pFrameDataOfNextDisplayed->present_event.Displayed_ScreenTime[0]);
+ flipDelayData.displayQpc = pSourceFrameData->present_event.Displayed_ScreenTime[0];
+ nextDisplayedQpc = currentDisplayQpc;
+ frameTimingData.flipDelayDataMap[pFrameDataOfNextDisplayed->present_event.FrameId] = flipDelayData;
+ } else {
+ nextDisplayedQpc = pFrameDataOfNextDisplayed->present_event.Displayed_ScreenTime[0];
+ }
+ } else {
+ nextDisplayedQpc = pFrameDataOfNextDisplayed->present_event.Displayed_ScreenTime[0];
+ }
}
else {
// TODO: log issue or invalidate related columns or drop frame (or some combination)
@@ -1312,27 +1648,64 @@ void PM_FRAME_QUERY::Context::UpdateSourceData(const PmNsmFrameData* pSourceFram
}
if (pFrameDataOfLastDisplayed && pFrameDataOfLastDisplayed->present_event.DisplayedCount > 0) {
- previousDisplayedQpc = pFrameDataOfLastDisplayed->present_event.Displayed_ScreenTime[pFrameDataOfLastDisplayed->present_event.DisplayedCount - 1];
- }
- else {
+ // Check to see if the current frame had it's flip delay and display qpc set due to a
+ // collapsed present. If so use those values to calculate the next displayed qpc.
+ auto ii = frameTimingData.flipDelayDataMap.find(pFrameDataOfLastDisplayed->present_event.FrameId);
+ if (ii != frameTimingData.flipDelayDataMap.end()) {
+ previousDisplayedQpc = ii->second.displayQpc;
+ }
+ else {
+ previousDisplayedQpc = pFrameDataOfLastDisplayed->present_event.Displayed_ScreenTime[pFrameDataOfLastDisplayed->present_event.DisplayedCount - 1];
+ }
+ // Save off the frame id of the last displayed frame to allow for deletion of old flip delay data
+ frameTimingData.lastDisplayedFrameId = pFrameDataOfLastDisplayed->present_event.FrameId;
+ } else {
// TODO: log issue or invalidate related columns or drop frame (or some combination)
pmlog_info("null pFrameDataOfLastDisplayed");
previousDisplayedQpc = 0;
}
if (pFrameDataOfLastAppDisplayed && pFrameDataOfLastAppDisplayed->present_event.DisplayedCount > 0) {
- previousDisplayedAppQpc = pFrameDataOfLastAppDisplayed->present_event.Displayed_ScreenTime[pFrameDataOfLastAppDisplayed->present_event.DisplayedCount - 1];
- previousDisplayedSimStartQpc = pFrameDataOfLastAppDisplayed->present_event.AppSimStartTime;
+ // Use the animation error source to set the various last displayed sim start and app screen times
+ uint64_t displayQpc = 0;
+ // Check to see if the current frame had it's flip delay and display qpc set due to a
+ // collapsed present. If so use those values to calculate the next displayed qpc.
+ auto ii = frameTimingData.flipDelayDataMap.find(pFrameDataOfLastAppDisplayed->present_event.FrameId);
+ if (ii != frameTimingData.flipDelayDataMap.end()) {
+ displayQpc = ii->second.displayQpc;
+ }
+ else {
+ displayQpc = pFrameDataOfLastAppDisplayed->present_event.Displayed_ScreenTime[pFrameDataOfLastAppDisplayed->present_event.DisplayedCount - 1];
+ }
+ if (frameTimingData.animationErrorSource == AnimationErrorSource::PCLatency) {
+ // Special handling is required for application data provided by PCL events. In the PCL events
+ // case we use a non-zero PclSimStartTime as an indicator for an application generated frame.
+ if (pFrameDataOfLastAppDisplayed->present_event.PclSimStartTime != 0) {
+ frameTimingData.lastDisplayedAppSimStartTime = pFrameDataOfLastAppDisplayed->present_event.PclSimStartTime;
+
+ frameTimingData.lastDisplayedAppScreenTime = displayQpc;
+ } else {
+ // If we are transistioning from CPU Start time based animation error source to PCL then we need to update the last displayed app screen time
+ // for the animation error.
+ if (initAmimationErrorSource != frameTimingData.animationErrorSource) {
+ frameTimingData.lastDisplayedAppScreenTime = displayQpc;
+ }
+ }
+ } else if (frameTimingData.animationErrorSource == AnimationErrorSource::AppProvider) {
+ // The above transition check in the PCL case is not needed for the AppProvider case as with the app provided
+ // we know which frames are applicatoin generated.
+ frameTimingData.lastDisplayedAppSimStartTime = pFrameDataOfLastAppDisplayed->present_event.AppSimStartTime;
+ frameTimingData.lastDisplayedAppScreenTime = displayQpc;
+ } else {
+ frameTimingData.lastDisplayedAppScreenTime = displayQpc;
+ }
}
else {
// TODO: log issue or invalidate related columns or drop frame (or some combination)
pmlog_info("null pFrameDataOfLastAppDisplayed");
- previousDisplayedAppQpc = 0;
- previousDisplayedSimStartQpc = 0;
}
if (pFrameDataOfPreviousAppFrameOfLastAppDisplayed) {
- // TODO -> Add a comment here!!
if (pFrameDataOfPreviousAppFrameOfLastAppDisplayed->present_event.AppPropagatedPresentStartTime != 0) {
lastDisplayedCpuStart = pFrameDataOfPreviousAppFrameOfLastAppDisplayed->present_event.AppPropagatedPresentStartTime +
pFrameDataOfPreviousAppFrameOfLastAppDisplayed->present_event.AppPropagatedTimeInPresent;
diff --git a/IntelPresentMon/PresentMonMiddleware/FrameEventQuery.h b/IntelPresentMon/PresentMonMiddleware/FrameEventQuery.h
index 51795f89..46d0a6af 100644
--- a/IntelPresentMon/PresentMonMiddleware/FrameEventQuery.h
+++ b/IntelPresentMon/PresentMonMiddleware/FrameEventQuery.h
@@ -4,6 +4,7 @@
#include
#include
#include
+#include "FrameTimingData.h"
namespace pmapi::intro
{
@@ -22,9 +23,9 @@ struct PM_FRAME_QUERY
struct Context
{
// functions
- Context(uint64_t qpcStart, long long perfCounterFrequency, uint64_t appSimStartTime) : qpcStart{ qpcStart },
+ Context(uint64_t qpcStart, long long perfCounterFrequency, FrameTimingData& frameTimingData) : qpcStart{ qpcStart },
performanceCounterPeriodMs{ perfCounterFrequency != 0.f ? 1000.0 / perfCounterFrequency : 0.f },
- firstAppSimStartTime { appSimStartTime} {}
+ frameTimingData{ frameTimingData } {}
void UpdateSourceData(const PmNsmFrameData* pSourceFrameData_in,
const PmNsmFrameData* pFrameDataOfNextDisplayed,
const PmNsmFrameData* pFrameDataofLastPresented,
@@ -42,14 +43,10 @@ struct PM_FRAME_QUERY
uint64_t cpuStart = 0;
// Present start qpc of the previous frame, displayed or not
uint64_t previousPresentStartQpc = 0;
- // The simulation start of the last displayed frame
- uint64_t previousDisplayedSimStartQpc = 0;
// Start cpustart qpc of the previously displayed frame
uint64_t lastDisplayedCpuStart = 0;
// Screen time qpc of the previously displayed frame.
uint64_t previousDisplayedQpc = 0;
- // Screen time qpc of the last displayed application frame.
- uint64_t previousDisplayedAppQpc = 0;
// Screen time qpc of the first display in the next displayed PmNsmFrameData
uint64_t nextDisplayedQpc = 0;
// Display index to attribute cpu work, gpu work, animation error and
@@ -59,8 +56,16 @@ struct PM_FRAME_QUERY
uint64_t lastReceivedNotDisplayedClickQpc = 0;
// All other input time qpc of non displayed frame
uint64_t lastReceivedNotDisplayedAllInputTime = 0;
- // The first app sim start time
- uint64_t firstAppSimStartTime = 0;
+ // QPC of the last PC Latency simulation start
+ uint64_t mLastReceivedNotDisplayedPclSimStart = 0;
+ // QPC of the last PC Latency pc input
+ uint64_t mLastReceivedNotDisplayedPclInputTime = 0;
+ FrameTimingData frameTimingData{};
+
+ // Accumlated input to frame start time
+ double mAccumulatedInput2FrameStartTime = 0.f;
+ // Current input to frame start average
+ double avgInput2Fs{};
};
// functions
PM_FRAME_QUERY(std::span queryElements);
diff --git a/IntelPresentMon/PresentMonMiddleware/FrameTimingData.h b/IntelPresentMon/PresentMonMiddleware/FrameTimingData.h
new file mode 100644
index 00000000..ac5f0a4f
--- /dev/null
+++ b/IntelPresentMon/PresentMonMiddleware/FrameTimingData.h
@@ -0,0 +1,33 @@
+#pragma once
+
+// What the animation error calculation is based on
+enum class AnimationErrorSource {
+ CpuStart,
+ AppProvider,
+ PCLatency,
+};
+
+struct FlipDelayData {
+ uint64_t flipDelay = 0;
+ uint64_t displayQpc = 0;
+};
+
+struct FrameTimingData {
+ // QPC of the very first AppSimStartTime. This will either be from
+ // the app provider or the PCL simulation start time.
+ uint64_t firstAppSimStartTime = 0;
+ // QPC of the latest AppSimStartTime. This needs to be tracked because
+ // not every present is guaranteed to have an app provider or
+ // PCL simulation start time attached to it. Used when calculating
+ // ms between simulation starts
+ uint64_t lastAppSimStartTime = 0;
+ // QPC of the last displayed AppSimStartTime. Similar to lastAppSimStartTime
+ // but this is only updated when the present is displayed. Used in calculating
+ // animation error and time.
+ uint64_t lastDisplayedAppSimStartTime = 0;
+ uint64_t lastDisplayedAppScreenTime = 0;
+ AnimationErrorSource animationErrorSource = AnimationErrorSource::CpuStart;
+ // NVIDIA Flip Delay related data
+ std::unordered_map flipDelayDataMap{};
+ uint32_t lastDisplayedFrameId = 0;
+};
\ No newline at end of file
diff --git a/IntelPresentMon/PresentMonMiddleware/PresentMonMiddleware.vcxproj b/IntelPresentMon/PresentMonMiddleware/PresentMonMiddleware.vcxproj
index 37470b3c..2c0825fd 100644
--- a/IntelPresentMon/PresentMonMiddleware/PresentMonMiddleware.vcxproj
+++ b/IntelPresentMon/PresentMonMiddleware/PresentMonMiddleware.vcxproj
@@ -12,6 +12,7 @@
+
diff --git a/IntelPresentMon/PresentMonMiddleware/PresentMonMiddleware.vcxproj.filters b/IntelPresentMon/PresentMonMiddleware/PresentMonMiddleware.vcxproj.filters
index 116898d4..76c84a6a 100644
--- a/IntelPresentMon/PresentMonMiddleware/PresentMonMiddleware.vcxproj.filters
+++ b/IntelPresentMon/PresentMonMiddleware/PresentMonMiddleware.vcxproj.filters
@@ -36,6 +36,9 @@
Header Files
+
+ Header Files
+
diff --git a/IntelPresentMon/PresentMonService/MockPresentMonSession.cpp b/IntelPresentMon/PresentMonService/MockPresentMonSession.cpp
index 56bdc3d8..0eddc67a 100644
--- a/IntelPresentMon/PresentMonService/MockPresentMonSession.cpp
+++ b/IntelPresentMon/PresentMonService/MockPresentMonSession.cpp
@@ -130,6 +130,7 @@ PM_STATUS MockPresentMonSession::StartTraceSession(uint32_t processId, const std
pm_consumer_->mTrackInput = true;
pm_consumer_->mTrackFrameType = true;
pm_consumer_->mTrackAppTiming = true;
+ pm_consumer_->mTrackPcLatency = true;
pm_consumer_->mPaceEvents = isPlaybackPaced;
pm_consumer_->mRetimeEvents = isPlaybackRetimed;
diff --git a/IntelPresentMon/PresentMonService/RealtimePresentMonSession.cpp b/IntelPresentMon/PresentMonService/RealtimePresentMonSession.cpp
index e6b2b3b2..40ef5537 100644
--- a/IntelPresentMon/PresentMonService/RealtimePresentMonSession.cpp
+++ b/IntelPresentMon/PresentMonService/RealtimePresentMonSession.cpp
@@ -128,6 +128,7 @@ PM_STATUS RealtimePresentMonSession::StartTraceSession() {
pm_consumer_->mTrackInput = true;
pm_consumer_->mTrackFrameType = true;
pm_consumer_->mTrackAppTiming = true;
+ pm_consumer_->mTrackPcLatency = true;
auto& opt = clio::Options::Get();
if (opt.etwSessionName.AsOptional().has_value()) {
diff --git a/IntelPresentMon/PresentMonUtils/StreamFormat.h b/IntelPresentMon/PresentMonUtils/StreamFormat.h
index ef0bbcff..408ddf9f 100644
--- a/IntelPresentMon/PresentMonUtils/StreamFormat.h
+++ b/IntelPresentMon/PresentMonUtils/StreamFormat.h
@@ -96,6 +96,11 @@ struct PmNsmPresentEvent
uint64_t AppInputTime; // QPC value of app input time provided by Intel App Provider
InputDeviceType AppInputType; // Input type provided by Intel App Provider
+ uint64_t PclInputPingTime; // QPC value of input ping time provided by the PC Latency ETW event
+ uint64_t PclSimStartTime; // QPC value of app sim start time provided by the PC Latency ETW event
+ uint64_t FlipDelay; // QPC timestamp delta of FlipDelay calculated using the NV DisplayDriver FlipRequest event.
+ uint32_t FlipToken; // Flip token from the NV DisplayDriver FlipRequest event.
+
// Extra present parameters obtained through DXGI or D3D9 present
uint64_t SwapChainAddress;
int32_t SyncInterval;
diff --git a/IntelPresentMon/Streamer/Streamer.cpp b/IntelPresentMon/Streamer/Streamer.cpp
index 96d74843..d6bdf566 100644
--- a/IntelPresentMon/Streamer/Streamer.cpp
+++ b/IntelPresentMon/Streamer/Streamer.cpp
@@ -100,6 +100,12 @@ void Streamer::CopyFromPresentMonPresentEvent(
nsm_present_event->AppInputTime = present_event->AppInputSample.first;
nsm_present_event->AppInputType = present_event->AppInputSample.second;
+ nsm_present_event->PclInputPingTime = present_event->PclInputPingTime;
+ nsm_present_event->PclSimStartTime = present_event->PclSimStartTime;
+
+ nsm_present_event->FlipDelay = present_event->FlipDelay;
+ nsm_present_event->FlipToken = present_event->FlipToken;
+
nsm_present_event->SwapChainAddress = present_event->SwapChainAddress;
nsm_present_event->SyncInterval = present_event->SyncInterval;
nsm_present_event->PresentFlags = present_event->PresentFlags;
diff --git a/IntelPresentMon/metrics.csv b/IntelPresentMon/metrics.csv
index bf9f1ab2..7b1cc0b3 100644
--- a/IntelPresentMon/metrics.csv
+++ b/IntelPresentMon/metrics.csv
@@ -103,3 +103,4 @@ PM_METRIC_PC_LATENCY,,Ms PC Latency,"Time between PC receiving input and frame b
PM_METRIC_DISPLAYED_FRAME_TIME,1,FrameTime-Display,"The time between when the previous frame was displayed and this frame was, in milliseconds."
PM_METRIC_PRESENTED_FRAME_TIME,1,FrameTime-Presents,"The time between this Present call and the previous one, in milliseconds."
PM_METRIC_BETWEEN_APP_START,,Ms Between App Start,"How long it took from the start of this frame until the CPU started working on the next frame, in milliseconds."
+PM_METRIC_FLIP_DELAY,,Ms Flip Delay,"Delay added to when the Present() was displayed."
diff --git a/PresentData/Debug.hpp b/PresentData/Debug.hpp
index 55ce5711..24fca1e8 100644
--- a/PresentData/Debug.hpp
+++ b/PresentData/Debug.hpp
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: MIT
#pragma once
#include
+#include "../IntelPresentMon/CommonUtilities/log/Log.h"
#ifndef PRESENTMON_ENABLE_DEBUG_TRACE
#ifdef NDEBUG
@@ -43,7 +44,7 @@ void VerboseTraceEventImpl(PMTraceConsumer* pmConsumer, _EVENT_RECORD* eventReco
// When PRESENTMON_ENABLE_DEBUG_TRACE==0, all of the the verbose trace infrastructure should
// get optimized away.
#define IsVerboseTraceEnabled() false
-#define DebugAssert(condition)
+#define DebugAssert(condition) !!(condition) || pmlog_warn("PresentData Assert Failed: "#condition)
#define VerboseTraceBeforeModifyingPresent(p)
#define VerboseTraceEvent(c, e, m)
diff --git a/PresentData/ETW/Nvidia_PCL.h b/PresentData/ETW/Nvidia_PCL.h
new file mode 100644
index 00000000..149a16d5
--- /dev/null
+++ b/PresentData/ETW/Nvidia_PCL.h
@@ -0,0 +1,24 @@
+// Copyright (C) 2024 Intel Corporation
+// SPDX-License-Identifier: MIT
+//
+// This file is manually created from the streamline definitions of PCL Stats found here:
+// https://github.com/NVIDIAGameWorks/Streamline/blob/main/include/sl_pcl.h
+
+#pragma once
+
+namespace Nvidia_PCL {
+
+ struct __declspec(uuid("{0D216F06-82A6-4D49-BC4F-8F38AE56EFAB}")) GUID_STRUCT;
+ static const auto GUID = __uuidof(GUID_STRUCT);
+
+ enum class PCLMarker : uint32_t {
+ SimulationStart = 0,
+ SimulationEnd = 1,
+ RenderSubmitStart = 2,
+ RenderSubmitEnd = 3,
+ PresentStart = 4,
+ PresentEnd = 5,
+ PCLLatencyPing = 8,
+ OutOfBandPresentStart = 11
+ };
+}
\ No newline at end of file
diff --git a/PresentData/PresentData.vcxproj b/PresentData/PresentData.vcxproj
index 52cb7732..433d479c 100644
--- a/PresentData/PresentData.vcxproj
+++ b/PresentData/PresentData.vcxproj
@@ -1,4 +1,4 @@
-
+
@@ -353,12 +353,14 @@
+
+
@@ -367,6 +369,7 @@
+
diff --git a/PresentData/PresentData.vcxproj.filters b/PresentData/PresentData.vcxproj.filters
index f6158e32..6480632d 100644
--- a/PresentData/PresentData.vcxproj.filters
+++ b/PresentData/PresentData.vcxproj.filters
@@ -1,4 +1,4 @@
-
+
@@ -43,6 +43,10 @@
ETW
+
+ ETW
+
+
@@ -51,6 +55,7 @@
+
diff --git a/PresentData/PresentMonTraceConsumer.cpp b/PresentData/PresentMonTraceConsumer.cpp
index 80050b99..b47f79f7 100644
--- a/PresentData/PresentMonTraceConsumer.cpp
+++ b/PresentData/PresentMonTraceConsumer.cpp
@@ -14,6 +14,7 @@
#include "ETW/Microsoft_Windows_EventMetadata.h"
#include "ETW/Microsoft_Windows_Kernel_Process.h"
#include "ETW/Microsoft_Windows_Win32k.h"
+#include "ETW/Nvidia_PCL.h"
#include
#include
@@ -2019,7 +2020,6 @@ void PMTraceConsumer::StopTrackingPresent(std::shared_ptr const& p
if (p->AppFrameId != 0) {
SetAppTimingDataAsComplete(p->ProcessId, p->AppFrameId);
}
-
}
void PMTraceConsumer::RemoveLostPresent(std::shared_ptr p)
@@ -2155,6 +2155,35 @@ void PMTraceConsumer::CompletePresent(std::shared_ptr const& p)
}
}
+ if (mTrackPcLatency) {
+ auto* pclTimingData = ExtractAppTimingData(
+ mPclTimingDataByPclFrameId,
+ p->ProcessId,
+ 0,
+ p->PresentStartTime,
+ [this](const AppTimingData& d) {
+ if (mUsingOutOfBoundPresentStart) {
+ return d.PclOutOfBandPresentStartTime;
+ }
+ else {
+ return d.PclPresentStartTime;
+ }
+ });
+ if (pclTimingData) {
+ if (p->ProcessId == pclTimingData->ProcessId) {
+ p->PclFrameId = pclTimingData->FrameId;
+ p->PclSimStartTime = pclTimingData->PclSimStartTime;
+ p->PclSimEndTime = pclTimingData->PclSimEndTime;
+ p->PclRenderSubmitStartTime = pclTimingData->PclRenderSubmitStartTime;
+ p->PclRenderSubmitEndTime = pclTimingData->PclRenderSubmitEndTime;
+ p->PclPresentStartTime = pclTimingData->PclPresentStartTime;
+ p->PclPresentEndTime = pclTimingData->PclPresentEndTime;
+ p->PclInputPingTime = pclTimingData->PclInputPingTime;
+ p->PclInputReceivedTime = pclTimingData->PclInputReceivedTime;
+ }
+ }
+ }
+
// Remove the present from tracking structures.
StopTrackingPresent(p);
@@ -2280,11 +2309,11 @@ void PMTraceConsumer::CompletePresent(std::shared_ptr const& p)
// Prune out old app frame data
for (auto it = mAppTimingDataByAppFrameId.begin(); it != mAppTimingDataByAppFrameId.end();) {
- if (appFrameId != 0 && it->second.AppProcessId == processId &&
- static_cast(appFrameId - it->second.AppFrameId) >= 10) {
+ if (appFrameId != 0 && it->second.ProcessId == processId &&
+ static_cast(appFrameId - it->second.FrameId) >= 10) {
// Remove the app frame data if the app frame id is too old
it = mAppTimingDataByAppFrameId.erase(it); // Erase and move to the next element
- } else if (appFrameId == 0 && it->second.AppProcessId == processId &&
+ } else if (appFrameId == 0 && it->second.ProcessId == processId &&
it->second.AssignedToPresent == false && it->second.AppPresentStartTime != 0 &&
presentStartTime >= it->second.AppPresentStartTime &&
presentStartTime - it->second.AppPresentStartTime >= mDeferralTimeLimit) {
@@ -2487,11 +2516,16 @@ void PMTraceConsumer::RuntimePresentStop(Runtime runtime, EVENT_HEADER const& hd
if (mTrackAppTiming) {
if (IsApplicationPresent(present)) {
- auto* appTimingData = ExtractAppTimingData(present->ProcessId, present->AppFrameId, present->PresentStartTime);
+ auto* appTimingData = ExtractAppTimingData(
+ mAppTimingDataByAppFrameId,
+ present->ProcessId,
+ present->AppFrameId,
+ present->PresentStartTime,
+ [](const AppTimingData& d) { return d.AppPresentStartTime; });
if (appTimingData) {
- if (present->ProcessId == appTimingData->AppProcessId) {
+ if (present->ProcessId == appTimingData->ProcessId) {
if (present->AppFrameId == 0) {
- present->AppFrameId = appTimingData->AppFrameId;
+ present->AppFrameId = appTimingData->FrameId;
}
present->AppSimStartTime = appTimingData->AppSimStartTime;
present->AppSimEndTime = appTimingData->AppSimEndTime;
@@ -2693,8 +2727,8 @@ void PMTraceConsumer::SetAppTimingData(const EVENT_RECORD* pEventRecord) {
} else {
AppTimingData data;
data.AppSleepStartTime = timestamp;
- data.AppProcessId = processId;
- data.AppFrameId = props->FrameId;
+ data.ProcessId = processId;
+ data.FrameId = props->FrameId;
mAppTimingDataByAppFrameId.emplace(key, data);
}
}
@@ -2715,8 +2749,8 @@ void PMTraceConsumer::SetAppTimingData(const EVENT_RECORD* pEventRecord) {
} else {
AppTimingData data;
data.AppSleepEndTime = timestamp;
- data.AppProcessId = processId;
- data.AppFrameId = props->FrameId;
+ data.ProcessId = processId;
+ data.FrameId = props->FrameId;
mAppTimingDataByAppFrameId.emplace(key, data);
}
}
@@ -2737,8 +2771,8 @@ void PMTraceConsumer::SetAppTimingData(const EVENT_RECORD* pEventRecord) {
} else {
AppTimingData data;
data.AppSimStartTime = timestamp;
- data.AppProcessId = processId;
- data.AppFrameId = props->FrameId;
+ data.ProcessId = processId;
+ data.FrameId = props->FrameId;
mAppTimingDataByAppFrameId.emplace(key, data);
}
}
@@ -2759,8 +2793,8 @@ void PMTraceConsumer::SetAppTimingData(const EVENT_RECORD* pEventRecord) {
} else {
AppTimingData data;
data.AppSimEndTime = timestamp;
- data.AppProcessId = processId;
- data.AppFrameId = props->FrameId;
+ data.ProcessId = processId;
+ data.FrameId = props->FrameId;
mAppTimingDataByAppFrameId.emplace(key, data);
}
}
@@ -2781,8 +2815,8 @@ void PMTraceConsumer::SetAppTimingData(const EVENT_RECORD* pEventRecord) {
} else {
AppTimingData data;
data.AppRenderSubmitStartTime = timestamp;
- data.AppProcessId = processId;
- data.AppFrameId = props->FrameId;
+ data.ProcessId = processId;
+ data.FrameId = props->FrameId;
mAppTimingDataByAppFrameId.emplace(key, data);
}
}
@@ -2803,8 +2837,8 @@ void PMTraceConsumer::SetAppTimingData(const EVENT_RECORD* pEventRecord) {
} else {
AppTimingData data;
data.AppRenderSubmitEndTime = timestamp;
- data.AppProcessId = processId;
- data.AppFrameId = props->FrameId;
+ data.ProcessId = processId;
+ data.FrameId = props->FrameId;
mAppTimingDataByAppFrameId.emplace(key, data);
}
}
@@ -2825,8 +2859,8 @@ void PMTraceConsumer::SetAppTimingData(const EVENT_RECORD* pEventRecord) {
} else {
AppTimingData data;
data.AppPresentStartTime = timestamp;
- data.AppProcessId = processId;
- data.AppFrameId = props->FrameId;
+ data.ProcessId = processId;
+ data.FrameId = props->FrameId;
mAppTimingDataByAppFrameId.emplace(key, data);
}
}
@@ -2847,8 +2881,8 @@ void PMTraceConsumer::SetAppTimingData(const EVENT_RECORD* pEventRecord) {
} else {
AppTimingData data;
data.AppPresentEndTime = timestamp;
- data.AppProcessId = processId;
- data.AppFrameId = props->FrameId;
+ data.ProcessId = processId;
+ data.FrameId = props->FrameId;
mAppTimingDataByAppFrameId.emplace(key, data);
}
}
@@ -2870,8 +2904,8 @@ void PMTraceConsumer::SetAppTimingData(const EVENT_RECORD* pEventRecord) {
ij->second.AppInputSample.second = ConvertIntelProviderInputTypes(props->InputType);
} else {
AppTimingData data;
- data.AppProcessId = processId;
- data.AppFrameId = props->FrameId;
+ data.ProcessId = processId;
+ data.FrameId = props->FrameId;
data.AppInputSample.first = timestamp;
data.AppInputSample.second = ConvertIntelProviderInputTypes(props->InputType);
mAppTimingDataByAppFrameId.emplace(key, data);
@@ -2979,6 +3013,211 @@ void PMTraceConsumer::HandleIntelPresentMonEvent(EVENT_RECORD* pEventRecord)
assert(!mFilteredEvents); // Assert that filtering is working if expected
}
+void PMTraceConsumer::HandleTraceLoggingEvent(EVENT_RECORD* pEventRecord)
+{
+ if (mTrackPcLatency) {
+ HandlePclEvent(pEventRecord);
+ }
+}
+
+void PMTraceConsumer::HandlePclEvent(EVENT_RECORD* pEventRecord)
+{
+ try {
+ if (!mTraceLoggingDecoder.DecodeTraceLoggingEventRecord(pEventRecord)) {
+ pmlog_dbg("Failed to decode trace logging event"); // too spammy?
+ return;
+ }
+
+ auto eventName = mTraceLoggingDecoder.GetEventName();
+ if (!eventName.has_value()) {
+ pmlog_warn("Could not get trace logging event name");
+ return;
+ }
+
+ if (eventName.has_value()) {
+ if (eventName.value() == L"PCLStatsInit" ||
+ eventName.value() == L"ReflexStatsInit") {
+ pmlog_info("Received init event: " + pmon::util::str::ToNarrow(*eventName));
+ }
+ else if (eventName.value() == L"PCLStatsEvent" ||
+ eventName.value() == L"ReflexStatsEvent") {
+ auto marker = (Nvidia_PCL::PCLMarker)mTraceLoggingDecoder.GetNumericPropertyValue(L"Marker");
+ auto frameId = (uint32_t)mTraceLoggingDecoder.GetNumericPropertyValue(L"FrameID");
+ switch (marker) {
+ case Nvidia_PCL::PCLMarker::SimulationStart: {
+ auto processId = pEventRecord->EventHeader.ProcessId;
+ auto timestamp = pEventRecord->EventHeader.TimeStamp.QuadPart;
+ auto key = std::make_pair(frameId, processId);
+ auto ij = mPclTimingDataByPclFrameId.find(key);
+ if (ij != mPclTimingDataByPclFrameId.end()) {
+ ij->second.PclSimStartTime = timestamp;
+ } else {
+ AppTimingData data;
+ data.PclSimStartTime = timestamp;
+ data.ProcessId = processId;
+ data.FrameId = frameId;
+ mPclTimingDataByPclFrameId.emplace(key, data);
+ }
+ }
+ break;
+ case Nvidia_PCL::PCLMarker::SimulationEnd: {
+ auto processId = pEventRecord->EventHeader.ProcessId;
+ auto timestamp = pEventRecord->EventHeader.TimeStamp.QuadPart;
+ auto key = std::make_pair(frameId, processId);
+ auto ij = mPclTimingDataByPclFrameId.find(key);
+ if (ij != mPclTimingDataByPclFrameId.end()) {
+ ij->second.PclSimEndTime = timestamp;
+ } else {
+ AppTimingData data;
+ data.PclSimEndTime = timestamp;
+ data.ProcessId = processId;
+ data.FrameId = frameId;
+ mPclTimingDataByPclFrameId.emplace(key, data);
+ }
+ }
+ break;
+ case Nvidia_PCL::PCLMarker::RenderSubmitStart: {
+ auto processId = pEventRecord->EventHeader.ProcessId;
+ auto timestamp = pEventRecord->EventHeader.TimeStamp.QuadPart;
+ auto key = std::make_pair(frameId, processId);
+ auto ij = mPclTimingDataByPclFrameId.find(key);
+ if (ij != mPclTimingDataByPclFrameId.end()) {
+ ij->second.PclRenderSubmitStartTime = timestamp;
+ } else {
+ AppTimingData data;
+ data.PclRenderSubmitStartTime = timestamp;
+ data.ProcessId = processId;
+ data.FrameId = frameId;
+ mPclTimingDataByPclFrameId.emplace(key, data);
+ }
+ }
+ break;
+ case Nvidia_PCL::PCLMarker::RenderSubmitEnd: {
+ auto processId = pEventRecord->EventHeader.ProcessId;
+ auto timestamp = pEventRecord->EventHeader.TimeStamp.QuadPart;
+ auto key = std::make_pair(frameId, processId);
+ auto ij = mPclTimingDataByPclFrameId.find(key);
+ if (ij != mPclTimingDataByPclFrameId.end()) {
+ ij->second.PclRenderSubmitEndTime = timestamp;
+ } else {
+ AppTimingData data;
+ data.PclRenderSubmitEndTime = timestamp;
+ data.ProcessId = processId;
+ data.FrameId = frameId;
+ mPclTimingDataByPclFrameId.emplace(key, data);
+ }
+ }
+ break;
+ case Nvidia_PCL::PCLMarker::PresentStart: {
+ auto processId = pEventRecord->EventHeader.ProcessId;
+ auto timestamp = pEventRecord->EventHeader.TimeStamp.QuadPart;
+ auto key = std::make_pair(frameId, processId);
+ auto ij = mPclTimingDataByPclFrameId.find(key);
+ if (ij != mPclTimingDataByPclFrameId.end()) {
+ ij->second.PclPresentStartTime = timestamp;
+ } else {
+ AppTimingData data;
+ data.PclPresentStartTime = timestamp;
+ data.ProcessId = processId;
+ data.FrameId = frameId;
+ mPclTimingDataByPclFrameId.emplace(key, data);
+ }
+ }
+ break;
+ case Nvidia_PCL::PCLMarker::PresentEnd: {
+ auto processId = pEventRecord->EventHeader.ProcessId;
+ auto timestamp = pEventRecord->EventHeader.TimeStamp.QuadPart;
+ auto key = std::make_pair(frameId, processId);
+ auto ij = mPclTimingDataByPclFrameId.find(key);
+ if (ij != mPclTimingDataByPclFrameId.end()) {
+ ij->second.PclPresentEndTime = timestamp;
+ } else {
+ AppTimingData data;
+ data.PclPresentEndTime = timestamp;
+ data.ProcessId = processId;
+ data.FrameId = frameId;
+ mPclTimingDataByPclFrameId.emplace(key, data);
+ }
+ }
+ break;
+ case Nvidia_PCL::PCLMarker::PCLLatencyPing: {
+ auto processId = pEventRecord->EventHeader.ProcessId;
+ auto timestamp = pEventRecord->EventHeader.TimeStamp.QuadPart;
+ auto key = std::make_pair(frameId, processId);
+ auto ij = mPclTimingDataByPclFrameId.find(key);
+ if (ij != mPclTimingDataByPclFrameId.end()) {
+ ij->second.PclInputReceivedTime = timestamp;
+ ij->second.PclInputPingTime = mLatestPingTimestampByProcessId[processId];
+ if (mLatestPingTimestampByProcessId[processId] != 0) {
+ ij->second.PclInputPingTime = mLatestPingTimestampByProcessId[processId];
+ mLatestPingTimestampByProcessId[processId] = 0;
+ }
+ } else {
+ AppTimingData data;
+ data.PclInputReceivedTime = timestamp;
+ if (mLatestPingTimestampByProcessId[processId] != 0) {
+ data.PclInputPingTime = mLatestPingTimestampByProcessId[processId];
+ mLatestPingTimestampByProcessId[processId] = 0;
+ }
+ data.ProcessId = processId;
+ mPclTimingDataByPclFrameId.emplace(key, data);
+ }
+ }
+ break;
+ case Nvidia_PCL::PCLMarker::OutOfBandPresentStart: {
+ auto processId = pEventRecord->EventHeader.ProcessId;
+ auto timestamp = pEventRecord->EventHeader.TimeStamp.QuadPart;
+ // If we receive an out of band present start, we will use it
+ // to attach the pcl timing data to the present
+ mUsingOutOfBoundPresentStart = true;
+ auto key = std::make_pair(frameId, processId);
+ // We do not track the out of band present in the same way as the other markers.
+ // We only use it in an attempt to attach the pcl timing data to the present
+ auto ij = mPclTimingDataByPclFrameId.find(key);
+ if (ij != mPclTimingDataByPclFrameId.end()) {
+ if (ij->second.PclOutOfBandPresentStartTime == 0) {
+ ij->second.PclOutOfBandPresentStartTime = timestamp;
+ }
+ }
+ else {
+ AppTimingData data;
+ data.PclOutOfBandPresentStartTime = timestamp;
+ data.ProcessId = processId;
+ data.FrameId = frameId;
+ mPclTimingDataByPclFrameId.emplace(key, data);
+ }
+
+ }
+ break;
+ }
+ } else if (eventName.value() == L"PCLStatsInput" ||
+ eventName.value() == L"ReflexStatsInput") {
+ auto processId = pEventRecord->EventHeader.ProcessId;
+ auto timestamp = pEventRecord->EventHeader.TimeStamp.QuadPart;
+ mLatestPingTimestampByProcessId[processId] = timestamp;
+
+ } else if (eventName.value() == L"PCLStatsShutdown" ||
+ eventName.value() == L"ReflexStatsShutdown") {
+ // PCL stats is shutting down for this process. Remove
+ // all PCL tracking structure for this process id.
+ pmlog_info("Shutting down PCL stats tracking");
+ auto processId = pEventRecord->EventHeader.ProcessId;
+ std::erase_if(mPclTimingDataByPclFrameId, [processId](const auto& p) {
+ return p.first.second == processId; });
+ std::erase_if(mLatestPingTimestampByProcessId, [processId](const auto& p) {
+ return p.first == processId; });
+
+ }
+ else {
+ // unhandled trace event => ignore
+ }
+ }
+ }
+ catch (...) {
+ pmlog_error(pmon::util::ReportException());
+ }
+}
+
void PMTraceConsumer::DeferFlipFrameType(
uint64_t vidPnLayerId,
uint64_t presentId,
@@ -3093,28 +3332,31 @@ void PMTraceConsumer::DequeuePresentEvents(std::vector, AppTimingData, PairHash>& timingDataByFrameId,
+ uint32_t processId, uint32_t appFrameId, uint64_t presentStartTime, std::function timingSelector) {
if (appFrameId != 0) {
// If the incoming app frame id is already assigned then we receiving
// the information from version 2 of the PresentFrameType event.
auto key = std::make_pair(appFrameId, processId);
- auto ii = mAppTimingDataByAppFrameId.find(key);
- if (ii != mAppTimingDataByAppFrameId.end()) {
+ auto ii = timingDataByFrameId.find(key);
+ if (ii != timingDataByFrameId.end()) {
ii->second.AssignedToPresent = true;
ii->second.PresentCompleted = false;
return &ii->second;
}
} else {
- auto itToReturn = mAppTimingDataByAppFrameId.end();
+ auto itToReturn = timingDataByFrameId.end();
uint32_t earlierFrameId = std::numeric_limits::max();
uint64_t smallestPresentStartDelta = std::numeric_limits::max();
- // Search for the app timing data with the closest AppPresentStartTime to the passed
+ // 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 = mAppTimingDataByAppFrameId.begin(); it != mAppTimingDataByAppFrameId.end(); ++it) {
+ for (auto it = timingDataByFrameId.begin(); it != timingDataByFrameId.end(); ++it) {
if (it->first.second == processId) {
if (it->second.AssignedToPresent == false) {
- if (it->second.AppPresentStartTime != 0 && it->second.AppPresentStartTime < presentStartTime) {
- auto tempPresentStartDelta = presentStartTime - it->second.AppPresentStartTime;
+ uint64_t timingValue = timingSelector(it->second);
+ if (timingValue != 0 && timingValue < presentStartTime) {
+ auto tempPresentStartDelta = presentStartTime - timingValue;
if (tempPresentStartDelta < smallestPresentStartDelta) {
smallestPresentStartDelta = tempPresentStartDelta;
earlierFrameId = it->first.first;
@@ -3127,7 +3369,7 @@ AppTimingData* PMTraceConsumer::ExtractAppTimingData(uint32_t processId, uint32_
// If we found the app timing data and if the Present it is attached is not completed return
// the data
- if (itToReturn != mAppTimingDataByAppFrameId.end() && itToReturn->second.PresentCompleted != true) {
+ if (itToReturn != timingDataByFrameId.end() && itToReturn->second.PresentCompleted != true) {
itToReturn->second.AssignedToPresent = true;
return &itToReturn->second;
}
@@ -3150,7 +3392,7 @@ void PMTraceConsumer::SetAppTimingDataAsComplete(uint32_t processId, uint32_t ap
auto key = std::make_pair(appFrameId, processId);
auto ii = mAppTimingDataByAppFrameId.find(key);
if (ii != mAppTimingDataByAppFrameId.end()) {
- DebugAssert(ii->second.AppProcessId == processId);
+ DebugAssert(ii->second.ProcessId == processId);
ii->second.PresentCompleted = true;
}
}
\ No newline at end of file
diff --git a/PresentData/PresentMonTraceConsumer.hpp b/PresentData/PresentMonTraceConsumer.hpp
index ac06e3c4..182cb181 100644
--- a/PresentData/PresentMonTraceConsumer.hpp
+++ b/PresentData/PresentMonTraceConsumer.hpp
@@ -21,6 +21,7 @@
#include
#include
#include // must include after windows.h
+#include
#include "Debug.hpp"
#include "GpuTrace.hpp"
@@ -158,9 +159,12 @@ struct FlipFrameTypeEvent {
FrameType FrameType;
};
+// Structure used to track application provided timing information
+// using ETW events provided by either the PresentMon provider or
+// PC Latency stats.
struct AppTimingData {
- uint32_t AppProcessId = 0;
- uint32_t AppFrameId = 0;
+ uint32_t ProcessId = 0;
+ uint32_t FrameId = 0;
uint64_t AppSleepStartTime = 0;
uint64_t AppSleepEndTime = 0;
uint64_t AppSimStartTime = 0;
@@ -170,6 +174,15 @@ struct AppTimingData {
uint64_t AppPresentStartTime = 0;
uint64_t AppPresentEndTime = 0;
std::pair AppInputSample = { 0, InputDeviceType::None };
+ uint64_t PclSimStartTime = 0;
+ uint64_t PclSimEndTime = 0;
+ uint64_t PclRenderSubmitStartTime = 0;
+ uint64_t PclRenderSubmitEndTime = 0;
+ uint64_t PclPresentStartTime = 0;
+ uint64_t PclPresentEndTime = 0;
+ uint64_t PclInputPingTime = 0;
+ uint64_t PclInputReceivedTime = 0;
+ uint64_t PclOutOfBandPresentStartTime = 0;
bool AssignedToPresent = false;
bool PresentCompleted = false;
};
@@ -215,6 +228,15 @@ struct PresentEvent {
uint64_t AppPresentStartTime; // QPC value of app present start time provided by Intel App Provider
uint64_t AppPresentEndTime; // QPC value of app present end time provided by Intel App Provider
std::pair AppInputSample; // QPC value of app input data provided by Intel App Provider
+ uint32_t PclFrameId = 0;
+ uint64_t PclSimStartTime = 0;
+ uint64_t PclSimEndTime = 0;
+ uint64_t PclRenderSubmitStartTime = 0;
+ uint64_t PclRenderSubmitEndTime = 0;
+ uint64_t PclPresentStartTime = 0;
+ uint64_t PclPresentEndTime = 0;
+ uint64_t PclInputPingTime = 0;
+ uint64_t PclInputReceivedTime = 0;
// Extra present parameters obtained through DXGI or D3D9 present
uint64_t SwapChainAddress;
@@ -317,6 +339,7 @@ struct PMTraceConsumer
bool mTrackPMMeasurements = false; // ... external measurements provided through the Intel-PresentMon provider
bool mTrackAppTiming = false; // ... app timing data communicated through the Intel-PresentMon provider.
bool mTrackHybridPresent = false; // ... hybrid presents.
+ bool mTrackPcLatency = false; // ... Nvidia PC Latency stats.
// When PresentEvents are missing data that may still arrive later, they get put into a deferred
// state until the data arrives. This time limit specifies how long a PresentEvent can be
@@ -376,6 +399,9 @@ struct PMTraceConsumer
// EventMetadata stores the structure of ETW events to optimize subsequent property retrieval.
EventMetadata mMetadata;
+ // TraceLoggingContext decodes trace logging events and allows for easy property retrieval.
+ TraceLoggingContext mTraceLoggingDecoder;
+
// Limit tracking to specified processes
std::set mTrackedProcessFilter;
std::shared_mutex mTrackedProcessFilterMutex;
@@ -482,6 +508,13 @@ struct PMTraceConsumer
uint32_t,
PairHash> mHybridPresentModeBySwapChainPid; // SwapChain and process id -> HybridPresentMode
+ // State used to track pcl events and their associated presents.
+ std::unordered_map,
+ AppTimingData,
+ PairHash> mPclTimingDataByPclFrameId; // PCL frame id -> PCLTimingData
+ std::unordered_map mLatestPingTimestampByProcessId; // ProcessId -> Latest Ping Timestamp
+ bool mUsingOutOfBoundPresentStart = false;
+
// mGpuTrace tracks work executed on the GPU.
GpuTrace mGpuTrace;
@@ -544,6 +577,8 @@ struct PMTraceConsumer
void HandleMetadataEvent(EVENT_RECORD* pEventRecord);
void HandleIntelPresentMonEvent(EVENT_RECORD* pEventRecord);
void HandleNvidiaDisplayDriverEvent(EVENT_RECORD* pEventRecord);
+ void HandleTraceLoggingEvent(EVENT_RECORD* pEventRecord);
+ void HandlePclEvent(EVENT_RECORD* pEventRecord);
void HandleWin7DxgkBlt(EVENT_RECORD* pEventRecord);
void HandleWin7DxgkFlip(EVENT_RECORD* pEventRecord);
@@ -578,7 +613,7 @@ struct PMTraceConsumer
// -------------------------------------------------------------------------------------------
// Function for managing app provided events
- AppTimingData* ExtractAppTimingData(uint32_t processId, uint32_t appFrameId, uint64_t presentStartTime);
+ AppTimingData* ExtractAppTimingData(std::unordered_map, AppTimingData, PairHash>& timingDataByFrameId, uint32_t processId, uint32_t appFrameId, uint64_t presentStartTime, std::function timingSelector);
bool IsApplicationPresent(std::shared_ptr const& present);
void SetAppTimingDataAsComplete(uint32_t processId, uint32_t appFrameId);
diff --git a/PresentData/PresentMonTraceSession.cpp b/PresentData/PresentMonTraceSession.cpp
index 8c65dc4a..e169b3d4 100644
--- a/PresentData/PresentMonTraceSession.cpp
+++ b/PresentData/PresentMonTraceSession.cpp
@@ -19,6 +19,7 @@
#include "ETW/NT_Process.h"
#include "ETW/Intel_PresentMon.h"
#include "ETW/NV_DD.h"
+#include "ETW/Nvidia_PCL.h"
namespace {
@@ -290,7 +291,8 @@ template<
bool IS_REALTIME_SESSION,
bool TRACK_DISPLAY,
bool TRACK_INPUT,
- bool TRACK_PRESENTMON>
+ bool TRACK_PRESENTMON,
+ bool TRACK_PCL>
void CALLBACK EventRecordCallback(EVENT_RECORD* pEventRecord)
{
auto session = (PMTraceSession*) pEventRecord->UserContext;
@@ -403,6 +405,13 @@ void CALLBACK EventRecordCallback(EVENT_RECORD* pEventRecord)
return;
}
}
+
+ if constexpr (TRACK_PCL) {
+ if (hdr.ProviderId == Nvidia_PCL::GUID) {
+ session->mPMConsumer->HandlePclEvent(pEventRecord);
+ return;
+ }
+ }
}
template
@@ -433,6 +442,13 @@ PEVENT_RECORD_CALLBACK GetEventRecordCallback(bool t1, bool t2, bool t3, bool t4
: GetEventRecordCallback(t2, t3, t4);
}
+template
+PEVENT_RECORD_CALLBACK GetEventRecordCallback(bool t1, bool t2, bool t3, bool t4, bool t5)
+{
+ return t1 ? GetEventRecordCallback(t2, t3, t4, t5)
+ : GetEventRecordCallback(t2, t3, t4, t5);
+}
+
ULONG CALLBACK BufferCallback(EVENT_TRACE_LOGFILE* pLogFile)
{
auto session = (PMTraceSession*) pLogFile->Context;
@@ -497,7 +513,8 @@ ULONG PMTraceSession::Start(
mIsRealtimeSession, // IS_REALTIME_SESSION
mPMConsumer->mTrackDisplay, // TRACK_DISPLAY
mPMConsumer->mTrackInput, // TRACK_INPUT
- mPMConsumer->mTrackFrameType || mPMConsumer->mTrackPMMeasurements || mPMConsumer->mTrackAppTiming); // TRACK_PRESENTMON
+ mPMConsumer->mTrackFrameType || mPMConsumer->mTrackPMMeasurements || mPMConsumer->mTrackAppTiming, // TRACK_PRESENTMON
+ mPMConsumer->mTrackPcLatency); // TRACK_PC_LATENCY
mTraceHandle = OpenTraceW(&traceProps);
if (mTraceHandle == INVALID_PROCESSTRACE_HANDLE) {
@@ -816,6 +833,12 @@ ULONG EnableProvidersListing(
status = provider.Enable(sessionHandle, NvidiaDisplayDriver_Events::GUID);
if (status != ERROR_SUCCESS) return status;
+ if (pmConsumer->mTrackPcLatency) {
+ provider.ClearFilter();
+ status = provider.EnableWithoutFiltering(sessionHandle, Nvidia_PCL::GUID, TRACE_LEVEL_VERBOSE);
+ if (status != ERROR_SUCCESS) return status;
+ }
+
return ERROR_SUCCESS;
}
diff --git a/PresentData/TraceConsumer.hpp b/PresentData/TraceConsumer.hpp
index 3206c602..e9755b01 100644
--- a/PresentData/TraceConsumer.hpp
+++ b/PresentData/TraceConsumer.hpp
@@ -10,6 +10,7 @@
#include
#include
#include // Must include after windows.h
+#include "TraceLogging.h"
struct EventMetadataKey {
GUID guid_;
diff --git a/PresentData/TraceLogging.cpp b/PresentData/TraceLogging.cpp
new file mode 100644
index 00000000..167870e2
--- /dev/null
+++ b/PresentData/TraceLogging.cpp
@@ -0,0 +1,138 @@
+#include "TraceLogging.h"
+#include "ETW\Nvidia_PCL.h"
+
+using pmon::util::Except;
+
+
+bool TraceLoggingContext::DecodeTraceLoggingEventRecord(EVENT_RECORD* pEventRecord)
+{
+ if (pEventRecord == nullptr) {
+ pmlog_warn("null event record pointer");
+ return false;
+ }
+
+ // We do not handle Windows Software Trace Preprocessor (WPP) events
+ if ((pEventRecord->EventHeader.Flags & EVENT_HEADER_FLAG_TRACE_MESSAGE) != 0)
+ {
+ return false;
+ }
+
+ if (pEventRecord->EventHeader.EventDescriptor.Opcode == EVENT_TRACE_TYPE_INFO &&
+ pEventRecord->EventHeader.ProviderId == EventTraceGuid)
+ {
+ // TODO: determine if this necessary. As mentioned in the sample code
+ // the first event in every ETL file contains the data from the file header.
+ // This is the same data as was returned in the EVENT_TRACE_LOGFILEW by
+ // OpenTrace. Since we've already seen this information, we'll skip this
+ // event.
+ // In PresentMon we process ETW events in both realtime and from ETL files.
+ // Check how this works!!
+ return false;
+ }
+
+ // Reset event state
+ mpEventRecord = pEventRecord;
+ mpEventData = static_cast(mpEventRecord->UserData);
+ mpEventDataEnd = mpEventData + mpEventRecord->UserDataLength;
+ if (mpEventRecord->EventHeader.Flags & EVENT_HEADER_FLAG_32_BIT_HEADER) {
+ mPointerSize = 4;
+ }
+ else if (mpEventRecord->EventHeader.Flags & EVENT_HEADER_FLAG_64_BIT_HEADER) {
+ mPointerSize = 8;
+ }
+ else {
+ // Ambiguous, assume size of the decoder's pointer.
+ mPointerSize = sizeof(void*);
+ }
+
+ return SetupTraceLoggingInfoBuffer();
+}
+
+bool TraceLoggingContext::SetupTraceLoggingInfoBuffer()
+{
+ ULONG status;
+ ULONG cb;
+
+ // Use TdhGetEventInformation to obtain information about this event.
+ // We do not process WPP or classic ETW events in this class so we set
+ // TdhContextCount to 0 and TdhContext to NULL in both calls to
+ // TdhGetEventInformation
+ cb = static_cast(mTraceEventInfoBuffer.size());
+ status = TdhGetEventInformation(
+ mpEventRecord,
+ 0,
+ nullptr,
+ reinterpret_cast(mTraceEventInfoBuffer.data()),
+ &cb);
+ if (status == ERROR_INSUFFICIENT_BUFFER) {
+ mTraceEventInfoBuffer.resize(cb);
+ status = TdhGetEventInformation(
+ mpEventRecord,
+ 0,
+ nullptr,
+ reinterpret_cast(mTraceEventInfoBuffer.data()),
+ &cb);
+ }
+
+ if (status != ERROR_SUCCESS)
+ {
+ pmlog_warn("Failure when calling TdhGetEventInformation").hr(status);
+ return false;
+ }
+
+ mpTraceEventInfo = reinterpret_cast(mTraceEventInfoBuffer.data());
+
+ // Check to see if either the event name or the task name are available. If
+ // not then we are unable to continue processing the event
+ if (mpTraceEventInfo->EventNameOffset == 0 && mpTraceEventInfo->TaskNameOffset == 0) {
+ pmlog_warn("Missing event or task name");
+ return false;
+ }
+
+ return true;
+}
+
+std::optional TraceLoggingContext::GetTraceEventInfoString(unsigned offset) const {
+ if (mTraceEventInfoBuffer.empty()) {
+ pmlog_warn("mTraceEventInfoBuffer is empty");
+ return std::nullopt;
+ }
+ return std::wstring(reinterpret_cast(mTraceEventInfoBuffer.data() + offset));
+}
+
+std::optional TraceLoggingContext::GetEventName()
+{
+ if (mpTraceEventInfo == nullptr) {
+ pmlog_warn("mTraceEventInfoBuffer not setup");
+ return std::nullopt;
+ }
+
+ return GetTraceEventInfoString(mpTraceEventInfo->EventNameOffset);
+}
+
+size_t TraceLoggingContext::GetSkipSize(unsigned tdhType) const
+{
+ switch (tdhType)
+ {
+ case TDH_INTYPE_INT8:
+ case TDH_INTYPE_UINT8:
+ return 1;
+ case TDH_INTYPE_INT16:
+ case TDH_INTYPE_UINT16:
+ return 2;
+ case TDH_INTYPE_INT32:
+ case TDH_INTYPE_UINT32:
+ case TDH_INTYPE_HEXINT32:
+ return 4;
+ case TDH_INTYPE_INT64:
+ case TDH_INTYPE_UINT64:
+ case TDH_INTYPE_HEXINT64:
+ return 8;
+ case TDH_INTYPE_FLOAT:
+ return sizeof(float);
+ case TDH_INTYPE_DOUBLE:
+ return sizeof(double);
+ default:
+ throw Except("Unknown TDH Type");
+ }
+}
\ No newline at end of file
diff --git a/PresentData/TraceLogging.h b/PresentData/TraceLogging.h
new file mode 100644
index 00000000..08afdba5
--- /dev/null
+++ b/PresentData/TraceLogging.h
@@ -0,0 +1,171 @@
+#pragma once
+#include "../IntelPresentMon/CommonUtilities/Exception.h"
+#include "../IntelPresentMon/CommonUtilities/Meta.h"
+#include "../IntelPresentMon/CommonUtilities/log/Log.h"
+#include
+#include
+
+#define INITGUID // Ensure that EventTraceGuid is defined.
+#include
+#undef INITGUID
+
+#include
+#include
+#include
+#include
+
+PM_DEFINE_EX(TraceLoggingError);
+
+class TraceLoggingContext
+{
+public:
+ explicit TraceLoggingContext() :
+ mpEventRecord(nullptr),
+ mpEventData(nullptr),
+ mpEventDataEnd(nullptr),
+ mPointerSize(0),
+ mCurrentEventValid(false),
+ mpTraceEventInfo(nullptr),
+ mEventTimeStamp{ 0 } {
+ }
+
+ bool DecodeTraceLoggingEventRecord(EVENT_RECORD* pEventRecord);
+ std::optional GetEventName();
+
+ // Templated member function to retrieve a property value of type T by name.
+ template
+ T GetNumericPropertyValue(const std::wstring& propertyName) const
+ {
+ using pmon::util::Except;
+ using pmon::util::dependent_false;
+
+ unsigned propertyCount = this->mpTraceEventInfo->PropertyCount;
+
+ // Start at the beginning of the raw data.
+ const BYTE* pb = this->mpEventData;
+
+ // Iterate over each property.
+ for (unsigned i = 0; i < propertyCount; ++i)
+ {
+ const EVENT_PROPERTY_INFO& epi = this->mpTraceEventInfo->EventPropertyInfoArray[i];
+
+ // Only support scalar properties: count must be 1 and not flagged as a struct or parameterized.
+ if (epi.count != 1 || (epi.Flags & (PropertyStruct | PropertyParamCount)) != 0)
+ {
+ pb += GetSkipSize(epi.nonStructType.InType);
+ continue;
+ }
+
+ // Obtain the property name.
+ auto currentName = epi.NameOffset ? this->GetTraceEventInfoString(epi.NameOffset) : std::nullopt;
+
+ // Get the size of the data for this property.
+ size_t skip = GetSkipSize(epi.nonStructType.InType);
+
+ // If this is not the property we are looking for, skip its data.
+ if ((currentName.has_value() == false) || (currentName.value() != propertyName))
+ {
+ pb += skip;
+ continue;
+ }
+
+ // Found the matching property.
+ if (pb + skip > mpEventDataEnd)
+ {
+ throw Except("Insufficient data for property");
+ }
+
+ // Check that the property's underlying type matches the expected type T.
+ if constexpr (std::is_same_v)
+ {
+ if (epi.nonStructType.InType != TDH_INTYPE_INT8)
+ throw Except("Type mismatch for property: expected int8_t");
+ return *reinterpret_cast(pb);
+ }
+ else if constexpr (std::is_same_v)
+ {
+ if (epi.nonStructType.InType != TDH_INTYPE_UINT8)
+ throw Except("Type mismatch for property: expected uint8_t");
+ return *reinterpret_cast(pb);
+ }
+ else if constexpr (std::is_same_v)
+ {
+ if (epi.nonStructType.InType != TDH_INTYPE_INT16)
+ throw Except("Type mismatch for property: expected int16_t");
+ return *reinterpret_cast(pb);
+ }
+ else if constexpr (std::is_same_v)
+ {
+ if (epi.nonStructType.InType != TDH_INTYPE_UINT16)
+ throw Except("Type mismatch for property: expected uint16_t");
+ return *reinterpret_cast(pb);
+ }
+ else if constexpr (std::is_same_v)
+ {
+ if (epi.nonStructType.InType != TDH_INTYPE_INT32)
+ throw Except("Type mismatch for property: expected int32_t");
+ return *reinterpret_cast(pb);
+ }
+ else if constexpr (std::is_same_v)
+ {
+ if (epi.nonStructType.InType != TDH_INTYPE_UINT32 &&
+ epi.nonStructType.InType != TDH_INTYPE_HEXINT32)
+ {
+ throw Except("Type mismatch for property: expected uint32_t");
+ }
+ return *reinterpret_cast(pb);
+ }
+ else if constexpr (std::is_same_v)
+ {
+ if (epi.nonStructType.InType != TDH_INTYPE_INT64)
+ throw Except("Type mismatch for property: expected int64_t");
+ return *reinterpret_cast(pb);
+ }
+ else if constexpr (std::is_same_v)
+ {
+ if (epi.nonStructType.InType != TDH_INTYPE_UINT64 &&
+ epi.nonStructType.InType != TDH_INTYPE_HEXINT64)
+ {
+ throw Except("Type mismatch for property: expected uint32_t");
+ }
+ return *reinterpret_cast(pb);
+ }
+ else if constexpr (std::is_same_v)
+ {
+ if (epi.nonStructType.InType != TDH_INTYPE_FLOAT)
+ throw Except("Type mismatch for property: expected float");
+ return *reinterpret_cast(pb);
+ }
+ else if constexpr (std::is_same_v)
+ {
+ if (epi.nonStructType.InType != TDH_INTYPE_DOUBLE)
+ throw Except("Type mismatch for property: expected double");
+ return *reinterpret_cast(pb);
+ }
+ else
+ {
+ static_assert(dependent_false::value, "Unsupported type in GetNumericPropertyValue");
+ }
+ }
+
+ // If we reach here, the property was not found.
+ throw Except("Property not found");
+ }
+private:
+
+ bool SetupTraceLoggingInfoBuffer();
+ std::optional GetTraceEventInfoString(unsigned offset) const;
+
+ size_t GetSkipSize(unsigned tdhType) const;
+
+ TDH_CONTEXT mTdhContext[1] = {};
+ EVENT_RECORD* mpEventRecord; // Event currently being processed
+ BYTE const* mpEventData; // Position of the next byte of event data to be consumed.
+ BYTE const* mpEventDataEnd; // Position of the end of the event data.
+ BYTE mPointerSize;
+ bool mCurrentEventValid;
+
+ LARGE_INTEGER mEventTimeStamp;
+ std::vector mTraceEventInfoBuffer; // Buffer for TRACE_EVENT_INFO data.
+ TRACE_EVENT_INFO const* mpTraceEventInfo;
+};
\ No newline at end of file
diff --git a/PresentMon/CommandLine.cpp b/PresentMon/CommandLine.cpp
index cc4cf04e..c0236ed7 100644
--- a/PresentMon/CommandLine.cpp
+++ b/PresentMon/CommandLine.cpp
@@ -299,6 +299,7 @@ void PrintUsage()
LR"(--track_hw_measurements)", LR"(Tracks HW-measured latency and/or power data coming from a LMT and/or PCAT device.)",
LR"(--track_app_timing)", LR"(Track app times for each displayed frame; requires application and/or driver instrumentation using Intel-PresentMon provider.)",
LR"(--track_hybrid_present)", LR"(Tracks if the present is a hybrid present and is performing a cross adapter copy.)",
+ LR"(--track_pc_latency)", LR"(Track app timines for each displayed frame; requires application instrumentation using PC Latency events.)",
LR"(--set_circular_buffer_size)", LR"(Overide the default present event circular buffer size of 2048. Must be a power of 2.)",
};
@@ -469,6 +470,7 @@ bool ParseCommandLine(int argc, wchar_t** argv)
else if (ParseArg(argv[i], L"track_hw_measurements")) { args->mTrackPMMeasurements = true; continue; }
else if (ParseArg(argv[i], L"track_app_timing")) { args->mTrackAppTiming = true; continue; }
else if (ParseArg(argv[i], L"track_hybrid_present")) { args->mTrackHybridPresent = true; continue; }
+ else if (ParseArg(argv[i], L"track_pc_latency")) { args->mTrackPcLatency = true; continue; }
// Hidden options:
#if PRESENTMON_ENABLE_DEBUG_TRACE
diff --git a/PresentMon/CsvOutput.cpp b/PresentMon/CsvOutput.cpp
index 50b06f5c..9a1767e0 100644
--- a/PresentMon/CsvOutput.cpp
+++ b/PresentMon/CsvOutput.cpp
@@ -306,8 +306,10 @@ void WriteCsvHeader(FILE* fp)
L",MsRenderPresentLatency");
if (args.mTrackDisplay) {
- fwprintf(fp, L",MsUntilDisplayed"
- L",MsPCLatency");
+ fwprintf(fp, L",MsUntilDisplayed");
+ if (args.mTrackPcLatency) {
+ fwprintf(fp, L",MsPCLatency");
+ }
}
}
@@ -387,6 +389,9 @@ void WriteCsvHeader(FILE* fp)
if (args.mTrackAppTiming) {
fwprintf(fp, L",AppFrameId");
}
+ if (args.mTrackPcLatency) {
+ fwprintf(fp, L",PCLFrameId");
+ }
}
fwprintf(fp, L"\n");
@@ -450,7 +455,12 @@ void WriteCsvRow(
}
// MsBetweenSimulationStart
- fwprintf(fp, L",NA");
+ if (metrics.mMsBetweenSimStarts == 0.0) {
+ fwprintf(fp, L",NA");
+ }
+ else {
+ fwprintf(fp, L",%.4lf", metrics.mMsBetweenSimStarts);
+ }
// MsBetweenPresents
fwprintf(fp, L",%.*lf", DBL_DIG - 1, metrics.mMsBetweenPresents);
@@ -479,9 +489,14 @@ void WriteCsvRow(
fwprintf(fp, L",%.4lf", metrics.mMsUntilDisplayed);
}
}
-
- // MsPCLatency
- fwprintf(fp, L",NA");
+ if (args.mTrackPcLatency) {
+ if (metrics.mMsPcLatency == 0.0) {
+ fwprintf(fp, L",NA");
+ }
+ else {
+ fwprintf(fp, L",%.4lf", metrics.mMsPcLatency);
+ }
+ }
}
// CPUStartTime
@@ -574,7 +589,6 @@ void WriteCsvRow(
fwprintf(fp, L",%.4lf", metrics.mMsInstrumentedLatency);
}
}
-
if (args.mWriteDisplayTime) {
if (metrics.mScreenTime == 0) {
fwprintf(fp, L",NA");
@@ -588,7 +602,9 @@ void WriteCsvRow(
if (args.mTrackAppTiming) {
fwprintf(fp, L",%u", p.AppFrameId);
}
-
+ if (args.mTrackPcLatency) {
+ fwprintf(fp, L",%u", p.PclFrameId);
+ }
}
fwprintf(fp, L"\n");
diff --git a/PresentMon/LogSetup.cpp b/PresentMon/LogSetup.cpp
index 54bf5c9c..aa61ec86 100644
--- a/PresentMon/LogSetup.cpp
+++ b/PresentMon/LogSetup.cpp
@@ -1,5 +1,4 @@
#include "../IntelPresentMon/CommonUtilities/log/Log.h"
-
namespace pmon::util::log
{
std::shared_ptr GetDefaultChannel() noexcept
diff --git a/PresentMon/MainThread.cpp b/PresentMon/MainThread.cpp
index fe09fc68..ca4bb719 100644
--- a/PresentMon/MainThread.cpp
+++ b/PresentMon/MainThread.cpp
@@ -292,6 +292,7 @@ int wmain(int argc, wchar_t** argv)
pmConsumer.mTrackAppTiming = args.mTrackAppTiming;
pmConsumer.mTrackHybridPresent = args.mTrackHybridPresent;
pmConsumer.mDisableOfflineBackpressure = args.mDisableOfflineBackpressure;
+ pmConsumer.mTrackPcLatency = args.mTrackPcLatency;
if (args.mTargetPid != 0) {
pmConsumer.mFilteredProcessIds = true;
pmConsumer.AddTrackedProcessForFiltering(args.mTargetPid);
diff --git a/PresentMon/OutputThread.cpp b/PresentMon/OutputThread.cpp
index 58ef0467..008bf4d0 100644
--- a/PresentMon/OutputThread.cpp
+++ b/PresentMon/OutputThread.cpp
@@ -3,6 +3,7 @@
// SPDX-License-Identifier: MIT
#include "PresentMon.hpp"
+#include "../IntelPresentMon/CommonUtilities/Math.h"
#include
#include
@@ -11,6 +12,10 @@
static std::thread gThread;
static bool gQuit = false;
+#include
+#include
+#include
+
// When we collect realtime ETW events, we don't receive the events in real
// time but rather sometime after they occur. Since the user might be toggling
// recording based on realtime cues (e.g., watching the target application) we
@@ -242,17 +247,55 @@ static void UpdateChain(
if (p->Displayed.empty() == false) {
if (p->Displayed.back().first == FrameType::NotSet ||
p->Displayed.back().first == FrameType::Application) {
- if (p->AppSimStartTime != 0) {
+
+ // If the chain animation error source has been set to either
+ // app provider or PCL latency then set the last displayed simulation start time and the
+ // first app simulation start time based on the animation error source type.
+ if (chain->mAnimationErrorSource == AnimationErrorSource::AppProvider) {
chain->mLastDisplayedSimStartTime = p->AppSimStartTime;
if (chain->mFirstAppSimStartTime == 0) {
// Received the first app sim start time.
chain->mFirstAppSimStartTime = p->AppSimStartTime;
}
- } else if (chain->mLastAppPresent != nullptr) {
- chain->mLastDisplayedSimStartTime = chain->mLastAppPresent->PresentStartTime +
- chain->mLastAppPresent->TimeInPresent;
+ chain->mLastDisplayedAppScreenTime = p->Displayed.back().second;
+ } else if (chain->mAnimationErrorSource == AnimationErrorSource::PCLatency) {
+ // In the case of PCLatency only set values if pcl sim start time is not zero.
+ if (p->PclSimStartTime != 0) {
+ chain->mLastDisplayedSimStartTime = p->PclSimStartTime;
+ if (chain->mFirstAppSimStartTime == 0) {
+ // Received the first app sim start time.
+ chain->mFirstAppSimStartTime = p->PclSimStartTime;
+ }
+ chain->mLastDisplayedAppScreenTime = p->Displayed.back().second;
+ }
+ } else {
+ // Currently sourcing animation error from CPU start time, however check
+ // to see if we have a valid app provider or PCL sim start time and set the
+ // new animation source and set the first app sim start time
+ if (p->AppSimStartTime != 0) {
+ chain->mAnimationErrorSource = AnimationErrorSource::AppProvider;
+ chain->mLastDisplayedSimStartTime = p->AppSimStartTime;
+ if (chain->mFirstAppSimStartTime == 0) {
+ // Received the first app sim start time.
+ chain->mFirstAppSimStartTime = p->AppSimStartTime;
+ }
+ chain->mLastDisplayedAppScreenTime = p->Displayed.back().second;
+ } else if (p->PclSimStartTime != 0) {
+ chain->mAnimationErrorSource = AnimationErrorSource::PCLatency;
+ chain->mLastDisplayedSimStartTime = p->PclSimStartTime;
+ if (chain->mFirstAppSimStartTime == 0) {
+ // Received the first app sim start time.
+ chain->mFirstAppSimStartTime = p->PclSimStartTime;
+ }
+ chain->mLastDisplayedAppScreenTime = p->Displayed.back().second;
+ } else {
+ if (chain->mLastAppPresent != nullptr) {
+ chain->mLastDisplayedSimStartTime = chain->mLastAppPresent->PresentStartTime +
+ chain->mLastAppPresent->TimeInPresent;
+ }
+ chain->mLastDisplayedAppScreenTime = p->Displayed.back().second;
+ }
}
- chain->mLastDisplayedAppScreenTime = p->Displayed.back().second;
}
}
// Want this to always be updated with the last displayed screen time regardless if the
@@ -273,6 +316,14 @@ static void UpdateChain(
chain->mLastAppPresent = p;
}
+ // Set chain->mLastSimStartTime to either p->PclSimStartTime or p->AppSimStartTime depending on
+ // if either are not zero. If both are zero, do not set.
+ if (p->PclSimStartTime != 0) {
+ chain->mLastSimStartTime = p->PclSimStartTime;
+ } else if (p->AppSimStartTime != 0) {
+ chain->mLastSimStartTime = p->AppSimStartTime;
+ }
+
// Want this to always be updated with the last present regardless if the
// frame was generated or not
chain->mLastPresent = p;
@@ -500,6 +551,13 @@ static void ReportMetricsHelper(
// way to calculate the Xell Gpu latency
metrics.mMsInstrumentedGpuLatency = InstrumentedStartTime == 0 ? 0 :
pmSession.TimestampDeltaToUnsignedMilliSeconds(InstrumentedStartTime, gpuStartTime);
+
+ // If we have both a valid pcl sim start time and a valid app sim start time, we use the pcl sim start time.
+ if (p->PclSimStartTime != 0) {
+ metrics.mMsBetweenSimStarts = pmSession.TimestampDeltaToUnsignedMilliSeconds(chain->mLastSimStartTime, p->PclSimStartTime);
+ } else if (p->AppSimStartTime != 0) {
+ metrics.mMsBetweenSimStarts = pmSession.TimestampDeltaToUnsignedMilliSeconds(chain->mLastSimStartTime, p->AppSimStartTime);
+ }
} else {
metrics.mMsCPUBusy = 0;
metrics.mMsCPUWait = 0;
@@ -509,8 +567,11 @@ static void ReportMetricsHelper(
metrics.mMsGPUWait = 0;
metrics.mMsInstrumentedSleep = 0;
metrics.mMsInstrumentedGpuLatency = 0;
+ metrics.mMsBetweenSimStarts = 0;
}
+ // If the frame was displayed regardless of how it was produced, calculate the following
+ // metrics
if (displayed) {
// Special handling for NV flipDelay
AdjustScreenTimeForCollapsedPresentNV(p, nextDisplayedPresent, screenTime, nextScreenTime);
@@ -534,6 +595,40 @@ static void ReportMetricsHelper(
// way to calculate the Xell Gpu latency
metrics.mMsInstrumentedLatency = InstrumentedStartTime == 0 ? 0 :
pmSession.TimestampDeltaToUnsignedMilliSeconds(InstrumentedStartTime, screenTime);
+
+ metrics.mMsPcLatency = 0.f;
+ // Check to see if we have a valid pc latency sim start time.
+ if (p->PclSimStartTime != 0) {
+ if (p->PclInputPingTime == 0) {
+ if (chain->mAccumulatedInput2FrameStartTime != 0) {
+ // This frame was displayed but we don't have a pc latency input time. However, there is accumulated time
+ // so there is a pending input that will now hit the screen. Add in the time from the last not
+ // displayed pc simulation start to this frame's pc simulation start.
+ chain->mAccumulatedInput2FrameStartTime +=
+ pmSession.TimestampDeltaToUnsignedMilliSeconds(chain->mLastReceivedNotDisplayedPclSimStart, p->PclSimStartTime);
+ // Add all of the accumlated time to the average input to frame start time.
+ chain->mEmaInput2FrameStartTime = pmon::util::CalculateEma(
+ chain->mEmaInput2FrameStartTime,
+ chain->mAccumulatedInput2FrameStartTime,
+ 0.1);
+ // Reset the tracking variables for when we have a dropped frame with a pc latency input
+ chain->mAccumulatedInput2FrameStartTime = 0.f;
+ chain->mLastReceivedNotDisplayedPclSimStart = 0;
+ }
+ } else {
+ chain->mEmaInput2FrameStartTime = pmon::util::CalculateEma(
+ chain->mEmaInput2FrameStartTime,
+ pmSession.TimestampDeltaToUnsignedMilliSeconds(p->PclInputPingTime, p->PclSimStartTime),
+ 0.1);
+ }
+ }
+ // If we have a non-zero average input to frame start time and a PC Latency simulation
+ // start time calculate the PC Latency
+ auto simStartTime = p->PclSimStartTime != 0 ? p->PclSimStartTime : chain->mLastSimStartTime;
+ if (chain->mEmaInput2FrameStartTime != 0.f && simStartTime != 0) {
+ metrics.mMsPcLatency = chain->mEmaInput2FrameStartTime +
+ pmSession.TimestampDeltaToMilliSeconds(simStartTime, screenTime);
+ }
} else {
metrics.mMsDisplayLatency = 0;
metrics.mMsDisplayedTime = 0;
@@ -543,10 +638,37 @@ static void ReportMetricsHelper(
metrics.mMsInstrumentedLatency = 0;
metrics.mMsInstrumentedRenderLatency = 0;
metrics.mMsReadyTimeToDisplayLatency = 0;
+ metrics.mMsPcLatency = 0;
+ if (p->PclSimStartTime != 0) {
+ if (p->PclInputPingTime != 0) {
+ // This frame was dropped but we have valid pc latency input and simulation start
+ // times. Calculate the initial input to sim start time.
+ chain->mAccumulatedInput2FrameStartTime =
+ pmSession.TimestampDeltaToUnsignedMilliSeconds(p->PclInputPingTime, p->PclSimStartTime);
+ } else if (chain->mAccumulatedInput2FrameStartTime != 0.f) {
+ // This frame was also dropped and there is no pc latency input time. However, since we have
+ // accumulated time this means we have a pending input that has had multiple dropped frames
+ // and has not yet hit the screen. Calculate the time between the last not displayed sim start and
+ // this sim start and add it to our accumulated total
+ chain->mAccumulatedInput2FrameStartTime +=
+ pmSession.TimestampDeltaToUnsignedMilliSeconds(chain->mLastReceivedNotDisplayedPclSimStart, p->PclSimStartTime);
+ }
+ chain->mLastReceivedNotDisplayedPclSimStart = p->PclSimStartTime;
+ }
}
+ // The following metrics use both the frame's displayed and origin information.
+ metrics.mMsClickToPhotonLatency = 0;
+ metrics.mMsAllInputPhotonLatency = 0;
+ metrics.mMsInstrumentedInputTime = 0;
+ metrics.mMsAnimationError = std::nullopt;
+ metrics.mAnimationTime = std::nullopt;
+
if (displayIndex == appIndex) {
if (displayed) {
+ // For all input device metrics check to see if there were any previous device input times
+ // that were attached to a dropped frame and if so use the last received times for the
+ // metric calculations
auto updatedInputTime = chain->mLastReceivedNotDisplayedAllInputTime == 0 ? 0 :
pmSession.TimestampDeltaToUnsignedMilliSeconds(chain->mLastReceivedNotDisplayedAllInputTime, screenTime);
metrics.mMsAllInputPhotonLatency = p->InputTime == 0 ? updatedInputTime :
@@ -562,13 +684,47 @@ static void ReportMetricsHelper(
metrics.mMsInstrumentedInputTime = p->AppInputSample.first == 0 ? updatedInputTime :
pmSession.TimestampDeltaToUnsignedMilliSeconds(p->AppInputSample.first, screenTime);
+ // Reset all last received device times
chain->mLastReceivedNotDisplayedAllInputTime = 0;
chain->mLastReceivedNotDisplayedMouseClickTime = 0;
chain->mLastReceivedNotDisplayedAppProviderInputTime = 0;
+
+ // Next calculate the animation error and animation time. First calculate the simulation
+ // start time. Simulation start can be either an app provided sim start time via the provider or
+ // PCL stats or, if not present,the cpu start.
+ uint64_t simStartTime = 0;
+ if (chain->mAnimationErrorSource == AnimationErrorSource::PCLatency) {
+ // If the pcl latency is the source of the animation error then use the pcl sim start time.
+ simStartTime = p->PclSimStartTime;
+ } else if (chain->mAnimationErrorSource == AnimationErrorSource::AppProvider) {
+ // If the app provider is the source of the animation error then use the app sim start time.
+ simStartTime = p->AppSimStartTime;
+ } else if (chain->mAnimationErrorSource == AnimationErrorSource::CpuStart) {
+ // If the cpu start time is the source of the animation error then use the cpu start time.
+ simStartTime = metrics.mCPUStart;
+ }
+
+ if (chain->mLastDisplayedSimStartTime != 0) {
+ // If the simulation start time is less than the last displayed simulation start time it means
+ // we are transitioning to app provider events.
+ if (simStartTime > chain->mLastDisplayedSimStartTime) {
+ metrics.mMsAnimationError = pmSession.TimestampDeltaToMilliSeconds(screenTime - chain->mLastDisplayedAppScreenTime,
+ simStartTime - chain->mLastDisplayedSimStartTime);
+ }
+ }
+ // If we have a value in app sim start or pcl sim start and we haven't set the first
+ // sim start time then we are transitioning from using cpu start to
+ // an application provided timestamp. Set the animation time to zero
+ // for the first frame.
+ if ((p->AppSimStartTime != 0 || p->PclSimStartTime != 0) && chain->mFirstAppSimStartTime == 0) {
+ metrics.mAnimationTime = 0.;
+ }
+ else {
+ double animationTime = 0.;
+ CalculateAnimationTime(pmSession, chain->mFirstAppSimStartTime, simStartTime, animationTime);
+ metrics.mAnimationTime = animationTime;
+ }
} else {
- metrics.mMsClickToPhotonLatency = 0;
- metrics.mMsAllInputPhotonLatency = 0;
- metrics.mMsInstrumentedInputTime = 0;
if (p->InputTime != 0) {
chain->mLastReceivedNotDisplayedAllInputTime = p->InputTime;
}
@@ -579,44 +735,6 @@ static void ReportMetricsHelper(
chain->mLastReceivedNotDisplayedAppProviderInputTime = p->AppInputSample.first;
}
}
- } else {
- metrics.mMsClickToPhotonLatency = 0;
- metrics.mMsAllInputPhotonLatency = 0;
- metrics.mMsInstrumentedInputTime = 0;
- }
-
- if (displayed && displayIndex == appIndex) {
- // Calculate the sim start time based on if AppSimStartTime is non-zero
- auto simStartTime = p->AppSimStartTime != 0 ? p->AppSimStartTime : metrics.mCPUStart;
-
- if (chain->mLastDisplayedSimStartTime != 0) {
- // If the simulation start time is less than the last displated simulation start time it means
- // we are transitioning to app provider events.
- if (simStartTime > chain->mLastDisplayedSimStartTime) {
- metrics.mMsAnimationError = pmSession.TimestampDeltaToMilliSeconds(screenTime - chain->mLastDisplayedAppScreenTime,
- simStartTime - chain->mLastDisplayedSimStartTime);
- }
- else {
- metrics.mMsAnimationError = 0;
- }
- } else {
- metrics.mMsAnimationError = 0;
- }
- // If we have a value in app sim start and we haven't set the first
- // sim start time then we are transitioning from using cpu start to
- // an application provided timestamp. Set the animation time to zero
- // for the first frame.
- if (p->AppSimStartTime != 0 && chain->mFirstAppSimStartTime == 0) {
- metrics.mAnimationTime = 0.;
- } else {
- double animationTime = 0.;
- CalculateAnimationTime(pmSession, chain->mFirstAppSimStartTime, simStartTime, animationTime);
- metrics.mAnimationTime = animationTime;
- }
-
- } else {
- metrics.mMsAnimationError = std::nullopt;
- metrics.mAnimationTime = std::nullopt;
}
diff --git a/PresentMon/PresentMon.hpp b/PresentMon/PresentMon.hpp
index 6be3b8cc..389855c2 100644
--- a/PresentMon/PresentMon.hpp
+++ b/PresentMon/PresentMon.hpp
@@ -56,6 +56,13 @@ enum class CSVOutput {
Stdout // To STDOUT in CSV format
};
+// What the animation error calculation is based on
+enum class AnimationErrorSource {
+ CpuStart,
+ AppProvider,
+ PCLatency,
+};
+
struct CommandLineArgs {
std::vector mTargetProcessNames;
std::vector mExcludeProcessNames;
@@ -79,6 +86,7 @@ struct CommandLineArgs {
bool mTrackPMMeasurements;
bool mTrackAppTiming;
bool mTrackHybridPresent;
+ bool mTrackPcLatency;
bool mScrollLockIndicator;
bool mExcludeDropped;
bool mTerminateExistingSession;
@@ -120,6 +128,8 @@ struct FrameMetrics {
uint64_t mScreenTime = 0;
FrameType mFrameType = FrameType::NotSet;
double mMsInstrumentedLatency = 0;
+ double mMsPcLatency = 0;
+ double mMsBetweenSimStarts = 0;
// Internal Intel Metrics
double mMsInstrumentedRenderLatency = 0;
@@ -183,6 +193,9 @@ struct SwapChainData {
// for frame statistics).
std::shared_ptr mLastAppPresent;
+ // QPC of the last simulation start time iregardless of whether it was displayed or not
+ uint64_t mLastSimStartTime = 0;
+
// The CPU start and screen time for the most recent frame that was displayed
uint64_t mLastDisplayedSimStartTime = 0;
uint64_t mLastDisplayedAppScreenTime = 0;
@@ -192,9 +205,15 @@ struct SwapChainData {
// QPC of last received input data that did not make it to the screen due
// to the Present() being dropped
- uint64_t mLastReceivedNotDisplayedAllInputTime;
- uint64_t mLastReceivedNotDisplayedMouseClickTime;
- uint64_t mLastReceivedNotDisplayedAppProviderInputTime;
+ uint64_t mLastReceivedNotDisplayedAllInputTime = 0;
+ uint64_t mLastReceivedNotDisplayedMouseClickTime = 0;
+ uint64_t mLastReceivedNotDisplayedAppProviderInputTime = 0;
+ // QPC of the last PC Latency simulation start
+ uint64_t mLastReceivedNotDisplayedPclSimStart = 0;
+
+ // Animation error source. Start with CPU start QPC and switch if
+ // we receive a valid PCL or App Provider simulation start time.
+ AnimationErrorSource mAnimationErrorSource = AnimationErrorSource::CpuStart;
// Frame statistics
float mAvgCPUDuration = 0.f;
@@ -203,6 +222,8 @@ struct SwapChainData {
float mAvgDisplayedTime = 0.f;
float mAvgMsUntilDisplayed = 0.f;
float mAvgMsBetweenDisplayChange = 0.f;
+ double mEmaInput2FrameStartTime = 0.f;
+ double mAccumulatedInput2FrameStartTime = 0.f;
// Internal NVIDIA Metrics
uint64_t mLastDisplayedFlipDelay = 0;
diff --git a/README-ConsoleApplication.md b/README-ConsoleApplication.md
index f6c1003f..e0b799bc 100644
--- a/README-ConsoleApplication.md
+++ b/README-ConsoleApplication.md
@@ -54,8 +54,9 @@ A binary of the console application is provided in the release, e.g.:
| ------------------------------ | --- |
| `--track_frame_type` | Track the type of each displayed frame; requires application and/or driver instrumentation using Intel-PresentMon provider. |
| `--track_hw_measurements` | Tracks HW-measured latency and/or power data coming from a LMT and/or PCAT device. |
-| `--track_app_timing` | Track app times for each displayed frame; requires application and/or driver instrumentation using Intel-PresentMon provider. |
+| `--track_app_timing` | Track app timines for each displayed frame; requires application and/or driver instrumentation using Intel-PresentMon provider. |
| `--track_hybrid_present` | Tracks if the present is a hybrid present and is performing a cross adapter copy. |
+| `--track_pc_latency` | Track app timines for each displayed frame; requires application instrumentation using PC Latency events. |
## Comma-separated value (CSV) file output
diff --git a/Tests/Gold/test_case_0.csv b/Tests/Gold/test_case_0.csv
index c2dea9bb..be942381 100644
--- a/Tests/Gold/test_case_0.csv
+++ b/Tests/Gold/test_case_0.csv
@@ -1,8 +1,8 @@
-Application,ProcessID,SwapChainAddress,PresentRuntime,SyncInterval,PresentFlags,AllowsTearing,PresentMode,FrameType,TimeInQPC,MsBetweenSimulationStart,MsBetweenPresents,MsBetweenDisplayChange,MsInPresentAPI,MsRenderPresentLatency,MsUntilDisplayed,MsPCLatency,CPUStartQPC,MsBetweenAppStart,MsCPUBusy,MsCPUWait,MsGPULatency,MsGPUTime,MsGPUBusy,MsGPUWait,MsVideoBusy,MsAnimationError,AnimationTime,MsAllInputToPhotonLatency,MsClickToPhotonLatency,MsInstrumentedLatency
-dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2076674276,NA,16.47540000000000,16.63730000000000,0.08930000000000,0.06730000000000,16.4296,NA,2076511276,16.3893,16.3000,0.0893,0.8529,15.5144,1.0752,14.4392,0.0000,0.0000,332.7030,NA,NA,NA
+Application,ProcessID,SwapChainAddress,PresentRuntime,SyncInterval,PresentFlags,AllowsTearing,PresentMode,FrameType,TimeInQPC,MsBetweenSimulationStart,MsBetweenPresents,MsBetweenDisplayChange,MsInPresentAPI,MsRenderPresentLatency,MsUntilDisplayed,MsPCLatency,CPUStartQPC,MsBetweenAppStart,MsCPUBusy,MsCPUWait,MsGPULatency,MsGPUTime,MsGPUBusy,MsGPUWait,MsVideoBusy,MsAnimationError,AnimationTime,MsAllInputToPhotonLatency,MsClickToPhotonLatency,MsInstrumentedLatency
+dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2076674276,NA,16.47540000000000,16.63730000000000,0.08930000000000,0.06730000000000,16.4296,NA,2076511276,16.3893,16.3000,0.0893,0.8529,15.5144,1.0752,14.4392,0.0000,NA,332.7030,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2077008319,NA,33.40430000000000,33.33230000000000,0.15240000000000,0.09120000000000,16.3576,NA,2076675169,33.4674,33.3150,0.1524,0.0000,33.4282,1.2105,32.2177,0.0000,-16.9430,349.0923,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2078012026,NA,100.37070000000000,100.06489999999999,0.12220000000000,0.12380000000000,16.0518,NA,2077009843,100.3405,100.2183,0.1222,0.0000,100.4033,1.1640,99.2393,0.0000,-66.5975,382.5597,NA,NA,NA
-Presenter.exe,10792,0x20979A6D5F8,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,2077944157,NA,2.35150000000000,16.67840000000000,7.48010000000000,7.47370000000000,39.5171,NA,2077942683,7.6275,0.1474,7.4801,0.0000,7.7858,0.1722,7.6136,0.0000,0.0000,475.8437,NA,NA,NA
+Presenter.exe,10792,0x20979A6D5F8,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,2077944157,NA,2.35150000000000,16.67840000000000,7.48010000000000,7.47370000000000,39.5171,NA,2077942683,7.6275,0.1474,7.4801,0.0000,7.7858,0.1722,7.6136,0.0000,NA,475.8437,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2078174981,NA,16.29550000000000,16.67840000000000,0.09070000000000,0.06720000000000,16.4347,NA,2078013248,16.2640,16.1733,0.0907,0.0016,16.2389,0.2928,15.9461,0.0000,83.6621,482.9002,NA,NA,NA
Presenter.exe,10792,0x20979A6D5F8,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,2078019292,NA,7.51350000000000,16.68050000000000,15.92220000000000,16.10160000000000,48.6841,NA,2078018958,15.9556,0.0334,15.9222,15.9223,0.2127,0.2127,0.0000,0.0000,-9.0530,483.4712,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2078341409,NA,16.64280000000000,16.68050000000000,0.07620000000000,0.07980000000000,16.4724,NA,2078175888,16.6283,16.5521,0.0762,0.0000,16.6554,0.2362,16.4192,0.0000,-0.4165,499.1642,NA,NA,NA
@@ -50,7 +50,7 @@ dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,20825192
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2082681588,NA,16.23790000000000,16.68300000000000,0.16980000000000,0.11410000000000,32.8403,NA,2082520490,16.2796,16.1098,0.1698,0.0000,16.2558,0.3022,15.9536,0.0000,0.5986,933.6244,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2082854819,NA,17.32310000000000,16.65980000000000,0.12620000000000,0.12240000000000,32.1770,NA,2082683286,17.2795,17.1533,0.1262,0.0000,17.3314,0.2556,17.0758,0.0000,-0.3802,949.9040,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2083035136,NA,18.03170000000000,16.67480000000000,0.07990000000000,-17.68110000000000,30.8201,NA,2082856081,17.9854,17.9055,0.0799,0.0000,0.2282,0.2282,0.0000,0.0000,0.6047,967.1835,NA,NA,NA
-Presenter.exe,8320,0x15EFD8424E0,DXGI,0,0,0,Composed: Flip,Application,2083154644,NA,15.60630000000000,16.68470000000000,0.42190000000000,0.52600000000000,35.5540,NA,2083006479,15.2384,14.8165,0.4219,1.1213,14.2212,0.3149,13.9063,0.0000,0.0000,982.2233,NA,NA,NA
+Presenter.exe,8320,0x15EFD8424E0,DXGI,0,0,0,Composed: Flip,Application,2083154644,NA,15.60630000000000,16.68470000000000,0.42190000000000,0.52600000000000,35.5540,NA,2083006479,15.2384,14.8165,0.4219,1.1213,14.2212,0.3149,13.9063,0.0000,NA,982.2233,NA,NA,NA
Presenter.exe,8320,0x15EFD8424E0,DXGI,0,0,0,Hardware: Independent Flip,Application,2083310385,NA,15.57410000000000,NA,0.25920000000000,0.28460000000000,NA,NA,2083158863,15.4114,15.1522,0.2592,0.5251,14.9117,0.2187,14.6930,0.0000,NA,NA,NA,NA,NA
Presenter.exe,8320,0x15EFD8424E0,DXGI,0,0,0,Hardware: Independent Flip,Application,2083467002,NA,15.66170000000000,16.67290000000000,1.43250000000000,4.58030000000000,20.9911,NA,2083312977,16.8350,15.4025,1.4325,19.8211,0.1617,0.1617,0.0000,0.0000,13.9769,1012.8731,NA,NA,NA
Presenter.exe,8320,0x15EFD8424E0,DXGI,0,0,0,Hardware: Independent Flip,Application,2083623264,NA,15.62620000000000,NA,0.57040000000000,5.48780000000000,NA,NA,2083481327,14.7641,14.1937,0.5704,19.5829,0.0986,0.0986,0.0000,0.0000,NA,NA,NA,NA,NA
@@ -79,7 +79,7 @@ dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,20873579
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2087517489,NA,15.95780000000000,16.67610000000000,0.11460000000000,0.08390000000000,16.2343,NA,2087375895,14.2740,14.1594,0.1146,0.0380,14.2053,0.0971,14.1082,0.0000,16.8174,1419.1649,NA,NA,NA
Presenter.exe,11648,0x1B95496E4B0,DXGI,0,0,0,Composed: Flip,Application,2087684621,NA,15.63250000000000,NA,0.16960000000000,0.28870000000000,NA,NA,2087533727,15.2590,15.0894,0.1696,0.2755,15.1026,0.2174,14.8852,0.0000,NA,NA,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2087690912,NA,17.34230000000000,16.70120000000000,0.12700000000000,0.07980000000000,15.5932,NA,2087518635,17.3547,17.2277,0.1270,0.0000,17.3382,0.2387,17.0995,0.0000,-2.4272,1433.4389,NA,NA,NA
-Presenter.exe,11648,0x1B95496E4B0,DXGI,0,0,0,Composed: Flip,Application,2087841111,NA,15.64900000000000,16.67920000000000,0.12630000000000,0.23030000000000,17.2525,NA,2087686317,15.6057,15.4794,0.1263,0.1699,15.5398,0.2293,15.3105,0.0000,0.0000,1450.2071,NA,NA,NA
+Presenter.exe,11648,0x1B95496E4B0,DXGI,0,0,0,Composed: Flip,Application,2087841111,NA,15.64900000000000,16.67920000000000,0.12630000000000,0.23030000000000,17.2525,NA,2087686317,15.6057,15.4794,0.1263,0.1699,15.5398,0.2293,15.3105,0.0000,NA,1450.2071,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2087863557,NA,17.26450000000000,16.67920000000000,0.06030000000000,-16.96550000000000,15.0079,NA,2087692182,17.1978,17.1375,0.0603,0.0000,0.2192,0.2192,0.0000,0.0000,0.6755,1450.7936,NA,NA,NA
Presenter.exe,11648,0x1B95496E4B0,DXGI,0,0,0,Composed: Flip,Application,2087997322,NA,15.62110000000000,16.69180000000000,0.14020000000000,0.25860000000000,18.3232,NA,2087842374,15.6350,15.4948,0.1402,0.1695,15.5839,0.2523,15.3316,0.0000,-1.0861,1465.8128,NA,NA,NA
Presenter.exe,11648,0x1B95496E4B0,DXGI,0,0,1,Hardware: Independent Flip,Application,2088153535,NA,15.62130000000000,0.09000000000000,0.11770000000000,0.20670000000000,2.7919,NA,2087998724,15.5988,15.4811,0.1177,0.2860,15.4018,0.2101,15.1917,0.0000,15.5450,1481.4478,NA,NA,NA
@@ -117,7 +117,7 @@ dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,20953644
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2095522411,NA,15.79990000000000,16.68970000000000,0.09220000000000,0.06670000000000,16.4124,NA,2095366257,15.7076,15.6154,0.0922,0.0000,15.7536,0.2051,15.5485,0.0000,1.0204,2218.2011,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2095694938,NA,17.25270000000000,16.67780000000000,0.11240000000000,0.24690000000000,15.8375,NA,2095523333,17.2729,17.1605,0.1124,0.0000,17.4329,0.1292,17.3037,0.0000,-0.9702,2233.9087,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2095857288,NA,16.23500000000000,16.70750000000000,0.07940000000000,0.06060000000000,16.3100,NA,2095696062,16.2020,16.1226,0.0794,0.1345,16.0487,0.2711,15.7776,0.0000,0.5654,2251.1816,NA,NA,NA
-Presenter.exe,3976,0x0,Other,-1,0,0,Composed: Copy with GPU GDI,Application,2095970262,NA,14.68890000000000,16.65220000000000,0.00000000000000,0.08630000000000,21.6648,NA,2095823373,14.6889,14.6889,0.0000,0.1348,14.6404,0.2958,14.3446,0.0000,0.0000,2263.9127,NA,NA,NA
+Presenter.exe,3976,0x0,Other,-1,0,0,Composed: Copy with GPU GDI,Application,2095970262,NA,14.68890000000000,16.65220000000000,0.00000000000000,0.08630000000000,21.6648,NA,2095823373,14.6889,14.6889,0.0000,0.1348,14.6404,0.2958,14.3446,0.0000,NA,2263.9127,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2096024031,NA,16.67430000000000,16.65220000000000,0.08350000000000,0.06580000000000,16.2879,NA,2095858082,16.6784,16.5949,0.0835,0.0000,16.6795,0.2758,16.4037,0.0000,-0.4502,2267.3836,NA,NA,NA
Presenter.exe,3976,0x0,Other,-1,0,0,Composed: Copy with GPU GDI,Application,2096121153,NA,15.08910000000000,16.67170000000000,0.00000000000000,0.14000000000000,23.2474,NA,2095970262,15.0891,15.0891,0.0000,0.5439,14.6852,0.2073,14.4779,0.0000,-1.9828,2278.6016,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2096190533,NA,16.65020000000000,16.67170000000000,0.07900000000000,0.05970000000000,16.3094,NA,2096024866,16.6457,16.5667,0.0790,0.0000,16.6441,0.2655,16.3786,0.0000,0.0067,2284.0620,NA,NA,NA
@@ -172,7 +172,7 @@ dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,21025284
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2102704267,NA,17.57940000000000,16.69940000000000,0.12450000000000,0.09960000000000,15.4578,NA,2102529891,17.5621,17.4376,0.1245,0.0000,17.5777,0.3118,17.2659,0.0000,66.8769,2934.5645,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2102861949,NA,15.76820000000000,16.67990000000000,0.13750000000000,0.13390000000000,16.3695,NA,2102705512,15.7812,15.6437,0.1375,0.0000,15.8025,0.2803,15.5222,0.0000,0.8822,2952.1266,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2103033100,NA,17.11510000000000,16.67140000000000,0.17130000000000,0.08920000000000,15.9258,NA,2102863324,17.1489,16.9776,0.1713,0.0000,17.0704,0.1975,16.8729,0.0000,-0.8902,2967.9078,NA,NA,NA
-Presenter.exe,11112,0x0,Other,1,0,0,Hardware: Legacy Flip,Application,2103880791,NA,71.87560000000001,83.41780000000000,0.00000000000000,-71.41889999999999,31.2617,NA,2103162035,71.8756,71.8756,0.0000,0.3592,0.0975,0.0975,0.0000,0.0000,0.0000,2997.7789,NA,NA,NA
+Presenter.exe,11112,0x0,Other,1,0,0,Hardware: Legacy Flip,Application,2103880791,NA,71.87560000000001,83.41780000000000,0.00000000000000,-71.41889999999999,31.2617,NA,2103162035,71.8756,71.8756,0.0000,0.3592,0.0975,0.0975,0.0000,0.0000,NA,2997.7789,NA,NA,NA
Presenter.exe,11112,0x0,Other,1,0,0,Hardware: Legacy Flip,Application,2104087609,NA,20.68180000000000,16.67150000000000,0.00000000000000,-17.69260000000000,27.2514,NA,2103880791,20.6818,20.6818,0.0000,0.1660,2.8232,0.2266,2.5966,0.0000,55.2041,3069.6545,NA,NA,NA
Presenter.exe,11112,0x0,Other,1,0,0,Hardware: Legacy Flip,Application,2104243447,NA,15.58380000000000,16.67930000000000,0.00000000000000,11.69900000000000,28.3469,NA,2104087609,15.5838,15.5838,0.0000,0.0363,27.2465,0.3605,26.8860,0.0000,4.0025,3090.3363,NA,NA,NA
Presenter.exe,11112,0x0,Other,1,0,0,Hardware: Legacy Flip,Application,2104399960,NA,15.65130000000000,16.68010000000000,0.00000000000000,12.73310000000000,29.3757,NA,2104243447,15.6513,15.6513,0.0000,11.6990,16.6854,0.3232,16.3622,0.0000,-1.0963,3105.9201,NA,NA,NA
@@ -201,7 +201,7 @@ dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,21093689
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2109551366,NA,18.24150000000000,15.07910000000000,0.13720000000000,0.10160000000000,14.6301,NA,2109370444,18.2294,18.0922,0.1372,0.0000,18.2363,0.2165,18.0198,0.0000,18.5614,3618.6198,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2109700589,NA,14.92230000000000,16.68090000000000,0.11290000000000,0.08370000000000,16.3887,NA,2109552738,14.8980,14.7851,0.1129,0.0000,14.9044,0.1987,14.7057,0.0000,1.5485,3636.8492,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2109875338,NA,17.47490000000000,16.68460000000000,0.10840000000000,0.08660000000000,15.5984,NA,2109701718,17.4704,17.3620,0.1084,0.0000,17.4778,0.1588,17.3190,0.0000,-1.7866,3651.7472,NA,NA,NA
-Presenter.exe,2032,0x29A5884FF18,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,2109834811,NA,0.88290000000000,16.67780000000000,4.48130000000000,4.60600000000000,36.3289,NA,2109834695,4.4929,0.0116,4.4813,0.0058,4.6118,0.2335,4.3783,0.0000,0.0000,3665.0449,NA,NA,NA
+Presenter.exe,2032,0x29A5884FF18,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,2109834811,NA,0.88290000000000,16.67780000000000,4.48130000000000,4.60600000000000,36.3289,NA,2109834695,4.4929,0.0116,4.4813,0.0058,4.6118,0.2335,4.3783,0.0000,NA,3665.0449,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2110034432,NA,15.90940000000000,16.67780000000000,0.10100000000000,0.06880000000000,16.3668,NA,2109876422,15.9020,15.8010,0.1010,0.0000,15.8916,0.2449,15.6467,0.0000,0.7926,3669.2176,NA,NA,NA
Presenter.exe,2032,0x29A5884FF18,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,2109885941,NA,5.11300000000000,16.68130000000000,15.15410000000000,15.37880000000000,47.8972,NA,2109879624,15.7858,0.6317,15.1541,15.8349,0.1756,0.1756,0.0000,0.0000,-12.1884,3669.5378,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2110206154,NA,17.17220000000000,16.68130000000000,0.08110000000000,0.22530000000000,15.8759,NA,2110035442,17.1523,17.0712,0.0811,0.0000,17.3287,0.2353,17.0934,0.0000,-0.7793,3685.1196,NA,NA,NA
@@ -242,7 +242,7 @@ dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,21132067
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2113372043,NA,16.52790000000000,16.67660000000000,0.13660000000000,0.10140000000000,16.1842,NA,2113209726,16.3683,16.2317,0.1366,0.0000,16.4005,0.2826,16.1179,0.0000,-0.6967,4002.5480,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2113538128,NA,16.60850000000000,16.69910000000000,0.11530000000000,0.08560000000000,16.2748,NA,2113373409,16.5872,16.4719,0.1153,0.0000,16.5927,0.2022,16.3905,0.0000,-0.3308,4018.9163,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2113708124,NA,16.99960000000000,16.69090000000000,0.17160000000000,0.16150000000000,15.9661,NA,2113539281,17.0559,16.8843,0.1716,0.0000,17.0755,0.3595,16.7160,0.0000,-0.1037,4035.5035,NA,NA,NA
-Presenter.exe,5988,0x224CBFFD9D8,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,2113641930,NA,1.51510000000000,16.67920000000000,7.19800000000000,7.16820000000000,39.2647,NA,2113638532,7.5378,0.3398,7.1980,0.0153,7.4927,0.2552,7.2375,0.0000,0.0000,4045.4286,NA,NA,NA
+Presenter.exe,5988,0x224CBFFD9D8,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,2113641930,NA,1.51510000000000,16.67920000000000,7.19800000000000,7.16820000000000,39.2647,NA,2113638532,7.5378,0.3398,7.1980,0.0153,7.4927,0.2552,7.2375,0.0000,NA,4045.4286,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2113871442,NA,16.33180000000000,16.67920000000000,0.13210000000000,0.11460000000000,16.3135,NA,2113709840,16.2923,16.1602,0.1321,0.0000,16.2849,0.1759,16.1090,0.0000,0.3767,4052.5594,NA,NA,NA
Presenter.exe,5988,0x224CBFFD9D8,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,2113714086,NA,7.21560000000000,16.67930000000000,16.26560000000000,16.27300000000000,48.7284,NA,2113713910,16.2832,0.0176,16.2656,0.0130,16.2776,0.2558,16.0218,0.0000,-9.1415,4052.9664,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2114038556,NA,16.71140000000000,16.67930000000000,0.13600000000000,0.12310000000000,16.2814,NA,2113872763,16.7153,16.5793,0.1360,0.0000,16.7199,0.2140,16.5059,0.0000,-0.3870,4068.8517,NA,NA,NA
@@ -284,7 +284,7 @@ dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,21172092
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2117540519,NA,33.13070000000000,33.37790000000000,0.13830000000000,0.12500000000000,16.3602,NA,2117210599,33.1303,32.9920,0.1383,0.0000,33.1726,0.2301,32.9425,0.0000,-16.4660,4402.6353,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2117715704,NA,17.51850000000000,16.67030000000000,0.11690000000000,0.09440000000000,15.5120,NA,2117541902,17.4971,17.3802,0.1169,0.0000,17.4879,0.1630,17.3249,0.0000,16.4600,4435.7656,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2117875954,NA,16.02500000000000,16.67960000000000,0.08560000000000,0.06420000000000,16.1666,NA,2117716873,15.9937,15.9081,0.0856,0.0000,15.9948,0.2586,15.7362,0.0000,0.8175,4453.2627,NA,NA,NA
-Presenter.exe,12268,0x20DBB4358B0,DXGI,0,0,0,Composed: Flip,Application,2117997030,NA,15.62470000000000,16.68800000000000,0.12740000000000,0.21640000000000,20.7470,NA,2117844370,15.3934,15.2660,0.1274,0.0894,15.3930,0.2120,15.1810,0.0000,0.0000,4466.0124,NA,NA,NA
+Presenter.exe,12268,0x20DBB4358B0,DXGI,0,0,0,Composed: Flip,Application,2117997030,NA,15.62470000000000,16.68800000000000,0.12740000000000,0.21640000000000,20.7470,NA,2117844370,15.3934,15.2660,0.1274,0.0894,15.3930,0.2120,15.1810,0.0000,NA,4466.0124,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2118044692,NA,16.87380000000000,16.68800000000000,0.08980000000000,0.20510000000000,15.9808,NA,2117876810,16.8780,16.7882,0.0898,0.0000,17.0147,0.2064,16.8083,0.0000,-0.6943,4469.2564,NA,NA,NA
Presenter.exe,12268,0x20DBB4358B0,DXGI,0,0,0,Composed: Flip,Application,2118153651,NA,15.66210000000000,16.67970000000000,0.11350000000000,0.23870000000000,21.7646,NA,2117998304,15.6482,15.5347,0.1135,0.4784,15.2950,0.2278,15.0672,0.0000,-1.2863,4481.4058,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2118208619,NA,16.39270000000000,16.67970000000000,0.08820000000000,0.12190000000000,16.2678,NA,2118045590,16.3911,16.3029,0.0882,0.1153,16.3095,0.2752,16.0343,0.0000,0.1983,4486.1344,NA,NA,NA
@@ -339,7 +339,7 @@ dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,21240470
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2124218883,NA,17.17950000000000,16.67850000000000,4.07220000000000,0.29080000000000,15.6983,NA,2124048354,21.1251,17.0529,4.0722,0.0000,17.3789,0.4213,16.9576,0.0000,0.2240,5086.4108,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2124378977,NA,16.00940000000000,16.67720000000000,0.11250000000000,0.07550000000000,16.3661,NA,2124259605,12.0497,11.9372,0.1125,0.0366,11.9761,0.0837,11.8924,0.0000,4.4479,5107.5359,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2124549841,NA,17.08640000000000,16.67390000000000,0.14270000000000,0.08140000000000,15.9536,NA,2124380102,17.1166,16.9739,0.1427,0.0000,17.0923,0.2720,16.8203,0.0000,-4.6242,5119.5856,NA,NA,NA
-Presenter.exe,11100,0x0,Other,1,0,0,Hardware: Legacy Flip,Application,2125524520,NA,80.51500000000000,NA,0.00000000000000,-79.97450000000001,18.6322,NA,2124719370,80.5150,80.5150,0.0000,0.4520,0.0885,0.0885,0.0000,0.0000,0.0000,5153.5124,NA,NA,NA
+Presenter.exe,11100,0x0,Other,1,0,0,Hardware: Legacy Flip,Application,2125524520,NA,80.51500000000000,NA,0.00000000000000,-79.97450000000001,18.6322,NA,2124719370,80.5150,80.5150,0.0000,0.4520,0.0885,0.0885,0.0000,0.0000,NA,5153.5124,NA,NA,NA
Presenter.exe,11100,0x0,Other,1,0,0,Hardware: Legacy Flip,Application,2125628438,NA,10.39180000000000,16.67270000000000,0.00000000000000,-9.51820000000000,24.9131,NA,2125524520,10.3918,10.3918,0.0000,0.1928,0.6808,0.2129,0.4679,0.0000,63.8423,5234.0274,NA,NA,NA
Presenter.exe,11100,0x0,Other,1,0,0,Hardware: Legacy Flip,Application,2125784666,NA,15.62280000000000,16.65350000000000,0.00000000000000,9.32260000000000,25.9438,NA,2125628438,15.6228,15.6228,0.0000,0.0451,24.9003,0.4760,24.4243,0.0000,-6.2617,5244.4192,NA,NA,NA
Presenter.exe,11100,0x0,Other,1,0,0,Hardware: Legacy Flip,Application,2125941064,NA,15.63980000000000,16.68060000000000,0.00000000000000,10.33520000000000,26.9846,NA,2125784666,15.6398,15.6398,0.0000,9.3226,16.6524,0.4381,16.2143,0.0000,-1.0578,5260.0420,NA,NA,NA
diff --git a/Tests/Gold/test_case_0_v2.csv b/Tests/Gold/test_case_0_v2.csv
index ddc27f54..325f1847 100644
--- a/Tests/Gold/test_case_0_v2.csv
+++ b/Tests/Gold/test_case_0_v2.csv
@@ -1,8 +1,8 @@
Application,ProcessID,SwapChainAddress,PresentRuntime,SyncInterval,PresentFlags,AllowsTearing,PresentMode,FrameType,CPUStartQPC,FrameTime,CPUBusy,CPUWait,GPULatency,GPUTime,GPUBusy,GPUWait,VideoBusy,DisplayLatency,DisplayedTime,AnimationError,AnimationTime,AllInputToPhotonLatency,ClickToPhotonLatency,InstrumentedLatency
-dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2076511276,16.3893,16.3000,0.0893,0.8529,15.5144,1.0752,14.4392,0.0000,32.7296,33.3323,0.0000,332.7030,NA,NA,NA
+dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2076511276,16.3893,16.3000,0.0893,0.8529,15.5144,1.0752,14.4392,0.0000,32.7296,33.3323,NA,332.7030,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2076675169,33.4674,33.3150,0.1524,0.0000,33.4282,1.2105,32.2177,0.0000,49.6726,100.0649,-16.9430,349.0923,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2077009843,100.3405,100.2183,0.1222,0.0000,100.4033,1.1640,99.2393,0.0000,116.2701,16.6784,-66.5975,382.5597,NA,NA,NA
-Presenter.exe,10792,0x20979A6D5F8,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,2077942683,7.6275,0.1474,7.4801,0.0000,7.7858,0.1722,7.6136,0.0000,39.6645,16.6805,0.0000,475.8437,NA,NA,NA
+Presenter.exe,10792,0x20979A6D5F8,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,2077942683,7.6275,0.1474,7.4801,0.0000,7.7858,0.1722,7.6136,0.0000,39.6645,16.6805,NA,475.8437,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2078013248,16.2640,16.1733,0.0907,0.0016,16.2389,0.2928,15.9461,0.0000,32.6080,16.6805,83.6621,482.9002,NA,NA,NA
Presenter.exe,10792,0x20979A6D5F8,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,2078018958,15.9556,0.0334,15.9222,15.9223,0.2127,0.2127,0.0000,0.0000,48.7175,16.6791,-9.0530,483.4712,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2078175888,16.6283,16.5521,0.0762,0.0000,16.6554,0.2362,16.4192,0.0000,33.0245,16.6791,-0.4165,499.1642,NA,NA,NA
@@ -50,7 +50,7 @@ dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,20823476
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2082520490,16.2796,16.1098,0.1698,0.0000,16.2558,0.3022,15.9536,0.0000,48.9501,16.6598,0.5986,933.6244,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2082683286,17.2795,17.1533,0.1262,0.0000,17.3314,0.2556,17.0758,0.0000,49.3303,16.6748,-0.3802,949.9040,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2082856081,17.9854,17.9055,0.0799,0.0000,0.2282,0.2282,0.0000,0.0000,48.7256,16.6847,0.6047,967.1835,NA,NA,NA
-Presenter.exe,8320,0x15EFD8424E0,DXGI,0,0,0,Composed: Flip,Application,2083006479,15.2384,14.8165,0.4219,1.1213,14.2212,0.3149,13.9063,0.0000,50.3705,16.6729,0.0000,982.2233,NA,NA,NA
+Presenter.exe,8320,0x15EFD8424E0,DXGI,0,0,0,Composed: Flip,Application,2083006479,15.2384,14.8165,0.4219,1.1213,14.2212,0.3149,13.9063,0.0000,50.3705,16.6729,NA,982.2233,NA,NA,NA
Presenter.exe,8320,0x15EFD8424E0,DXGI,0,0,0,Hardware: Independent Flip,Application,2083158863,15.4114,15.1522,0.2592,0.5251,14.9117,0.2187,14.6930,0.0000,NA,NA,NA,NA,NA,NA,NA
Presenter.exe,8320,0x15EFD8424E0,DXGI,0,0,0,Hardware: Independent Flip,Application,2083312977,16.8350,15.4025,1.4325,19.8211,0.1617,0.1617,0.0000,0.0000,36.3936,16.6855,13.9769,1012.8731,NA,NA,NA
Presenter.exe,8320,0x15EFD8424E0,DXGI,0,0,0,Hardware: Independent Flip,Application,2083481327,14.7641,14.1937,0.5704,19.5829,0.0986,0.0986,0.0000,0.0000,NA,NA,NA,NA,NA,NA,NA
@@ -79,7 +79,7 @@ dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,20870409
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2087375895,14.2740,14.1594,0.1146,0.0380,14.2053,0.0971,14.1082,0.0000,30.3937,16.7012,16.8174,1419.1649,NA,NA,NA
Presenter.exe,11648,0x1B95496E4B0,DXGI,0,0,0,Composed: Flip,Application,2087533727,15.2590,15.0894,0.1696,0.2755,15.1026,0.2174,14.8852,0.0000,NA,NA,NA,NA,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2087518635,17.3547,17.2277,0.1270,0.0000,17.3382,0.2387,17.0995,0.0000,32.8209,16.6792,-2.4272,1433.4389,NA,NA,NA
-Presenter.exe,11648,0x1B95496E4B0,DXGI,0,0,0,Composed: Flip,Application,2087686317,15.6057,15.4794,0.1263,0.1699,15.5398,0.2293,15.3105,0.0000,32.7319,16.6918,0.0000,1450.2071,NA,NA,NA
+Presenter.exe,11648,0x1B95496E4B0,DXGI,0,0,0,Composed: Flip,Application,2087686317,15.6057,15.4794,0.1263,0.1699,15.5398,0.2293,15.3105,0.0000,32.7319,16.6918,NA,1450.2071,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2087692182,17.1978,17.1375,0.0603,0.0000,0.2192,0.2192,0.0000,0.0000,32.1454,16.6918,0.6755,1450.7936,NA,NA,NA
Presenter.exe,11648,0x1B95496E4B0,DXGI,0,0,0,Composed: Flip,Application,2087842374,15.6350,15.4948,0.1402,0.1695,15.5839,0.2523,15.3316,0.0000,33.8180,0.0900,-1.0861,1465.8128,NA,NA,NA
Presenter.exe,11648,0x1B95496E4B0,DXGI,0,0,1,Hardware: Independent Flip,Application,2087998724,15.5988,15.4811,0.1177,0.2860,15.4018,0.2101,15.1917,0.0000,18.2730,13.0569,15.5450,1481.4478,NA,NA,NA
@@ -117,7 +117,7 @@ dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,20951891
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2095366257,15.7076,15.6154,0.0922,0.0000,15.7536,0.2051,15.5485,0.0000,32.0278,16.6778,1.0204,2218.2011,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2095523333,17.2729,17.1605,0.1124,0.0000,17.4329,0.1292,17.3037,0.0000,32.9980,16.7075,-0.9702,2233.9087,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2095696062,16.2020,16.1226,0.0794,0.1345,16.0487,0.2711,15.7776,0.0000,32.4326,16.6522,0.5654,2251.1816,NA,NA,NA
-Presenter.exe,3976,0x0,Other,-1,0,0,Composed: Copy with GPU GDI,Application,2095823373,14.6889,14.6889,0.0000,0.1348,14.6404,0.2958,14.3446,0.0000,36.3537,16.6717,0.0000,2263.9127,NA,NA,NA
+Presenter.exe,3976,0x0,Other,-1,0,0,Composed: Copy with GPU GDI,Application,2095823373,14.6889,14.6889,0.0000,0.1348,14.6404,0.2958,14.3446,0.0000,36.3537,16.6717,NA,2263.9127,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2095858082,16.6784,16.5949,0.0835,0.0000,16.6795,0.2758,16.4037,0.0000,32.8828,16.6717,-0.4502,2267.3836,NA,NA,NA
Presenter.exe,3976,0x0,Other,-1,0,0,Composed: Copy with GPU GDI,Application,2095970262,15.0891,15.0891,0.0000,0.5439,14.6852,0.2073,14.4779,0.0000,38.3365,16.6887,-1.9828,2278.6016,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2096024866,16.6457,16.5667,0.0790,0.0000,16.6441,0.2655,16.3786,0.0000,32.8761,16.6887,0.0067,2284.0620,NA,NA,NA
@@ -172,7 +172,7 @@ dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,21016941
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2102529891,17.5621,17.4376,0.1245,0.0000,17.5777,0.3118,17.2659,0.0000,32.8954,16.6799,66.8769,2934.5645,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2102705512,15.7812,15.6437,0.1375,0.0000,15.8025,0.2803,15.5222,0.0000,32.0132,16.6714,0.8822,2952.1266,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2102863324,17.1489,16.9776,0.1713,0.0000,17.0704,0.1975,16.8729,0.0000,32.9034,16.6872,-0.8902,2967.9078,NA,NA,NA
-Presenter.exe,11112,0x0,Other,1,0,0,Hardware: Legacy Flip,Application,2103162035,71.8756,71.8756,0.0000,0.3592,0.0975,0.0975,0.0000,0.0000,103.1373,16.6715,0.0000,2997.7789,NA,NA,NA
+Presenter.exe,11112,0x0,Other,1,0,0,Hardware: Legacy Flip,Application,2103162035,71.8756,71.8756,0.0000,0.3592,0.0975,0.0975,0.0000,0.0000,103.1373,16.6715,NA,2997.7789,NA,NA,NA
Presenter.exe,11112,0x0,Other,1,0,0,Hardware: Legacy Flip,Application,2103880791,20.6818,20.6818,0.0000,0.1660,2.8232,0.2266,2.5966,0.0000,47.9332,16.6793,55.2041,3069.6545,NA,NA,NA
Presenter.exe,11112,0x0,Other,1,0,0,Hardware: Legacy Flip,Application,2104087609,15.5838,15.5838,0.0000,0.0363,27.2465,0.3605,26.8860,0.0000,43.9307,16.6801,4.0025,3090.3363,NA,NA,NA
Presenter.exe,11112,0x0,Other,1,0,0,Hardware: Legacy Flip,Application,2104243447,15.6513,15.6513,0.0000,11.6990,16.6854,0.3232,16.3622,0.0000,45.0270,16.6802,-1.0963,3105.9201,NA,NA,NA
@@ -201,7 +201,7 @@ dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,21090340
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2109370444,18.2294,18.0922,0.1372,0.0000,18.2363,0.2165,18.0198,0.0000,32.7223,16.6809,18.5614,3618.6198,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2109552738,14.8980,14.7851,0.1129,0.0000,14.9044,0.1987,14.7057,0.0000,31.1738,16.6846,1.5485,3636.8492,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2109701718,17.4704,17.3620,0.1084,0.0000,17.4778,0.1588,17.3190,0.0000,32.9604,16.6778,-1.7866,3651.7472,NA,NA,NA
-Presenter.exe,2032,0x29A5884FF18,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,2109834695,4.4929,0.0116,4.4813,0.0058,4.6118,0.2335,4.3783,0.0000,36.3405,16.6813,0.0000,3665.0449,NA,NA,NA
+Presenter.exe,2032,0x29A5884FF18,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,2109834695,4.4929,0.0116,4.4813,0.0058,4.6118,0.2335,4.3783,0.0000,36.3405,16.6813,NA,3665.0449,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2109876422,15.9020,15.8010,0.1010,0.0000,15.8916,0.2449,15.6467,0.0000,32.1678,16.6813,0.7926,3669.2176,NA,NA,NA
Presenter.exe,2032,0x29A5884FF18,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,2109879624,15.7858,0.6317,15.1541,15.8349,0.1756,0.1756,0.0000,0.0000,48.5289,16.6797,-12.1884,3669.5378,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2110035442,17.1523,17.0712,0.0811,0.0000,17.3287,0.2353,17.0934,0.0000,32.9471,16.6797,-0.7793,3685.1196,NA,NA,NA
@@ -242,7 +242,7 @@ dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,21130499
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2113209726,16.3683,16.2317,0.1366,0.0000,16.4005,0.2826,16.1179,0.0000,32.4159,16.6991,-0.6967,4002.5480,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2113373409,16.5872,16.4719,0.1153,0.0000,16.5927,0.2022,16.3905,0.0000,32.7467,16.6909,-0.3308,4018.9163,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2113539281,17.0559,16.8843,0.1716,0.0000,17.0755,0.3595,16.7160,0.0000,32.8504,16.6792,-0.1037,4035.5035,NA,NA,NA
-Presenter.exe,5988,0x224CBFFD9D8,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,2113638532,7.5378,0.3398,7.1980,0.0153,7.4927,0.2552,7.2375,0.0000,39.6045,16.6793,0.0000,4045.4286,NA,NA,NA
+Presenter.exe,5988,0x224CBFFD9D8,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,2113638532,7.5378,0.3398,7.1980,0.0153,7.4927,0.2552,7.2375,0.0000,39.6045,16.6793,NA,4045.4286,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2113709840,16.2923,16.1602,0.1321,0.0000,16.2849,0.1759,16.1090,0.0000,32.4737,16.6793,0.3767,4052.5594,NA,NA,NA
Presenter.exe,5988,0x224CBFFD9D8,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,2113713910,16.2832,0.0176,16.2656,0.0130,16.2776,0.2558,16.0218,0.0000,48.7460,16.6886,-9.1415,4052.9664,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2113872763,16.7153,16.5793,0.1360,0.0000,16.7199,0.2140,16.5059,0.0000,32.8607,16.6886,-0.3870,4068.8517,NA,NA,NA
@@ -284,7 +284,7 @@ dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,21170414
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2117210599,33.1303,32.9920,0.1383,0.0000,33.1726,0.2301,32.9425,0.0000,49.3522,16.6703,-16.4660,4402.6353,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2117541902,17.4971,17.3802,0.1169,0.0000,17.4879,0.1630,17.3249,0.0000,32.8922,16.6796,16.4600,4435.7656,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2117716873,15.9937,15.9081,0.0856,0.0000,15.9948,0.2586,15.7362,0.0000,32.0747,16.6880,0.8175,4453.2627,NA,NA,NA
-Presenter.exe,12268,0x20DBB4358B0,DXGI,0,0,0,Composed: Flip,Application,2117844370,15.3934,15.2660,0.1274,0.0894,15.3930,0.2120,15.1810,0.0000,36.0130,16.6797,0.0000,4466.0124,NA,NA,NA
+Presenter.exe,12268,0x20DBB4358B0,DXGI,0,0,0,Composed: Flip,Application,2117844370,15.3934,15.2660,0.1274,0.0894,15.3930,0.2120,15.1810,0.0000,36.0130,16.6797,NA,4466.0124,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2117876810,16.8780,16.7882,0.0898,0.0000,17.0147,0.2064,16.8083,0.0000,32.7690,16.6797,-0.6943,4469.2564,NA,NA,NA
Presenter.exe,12268,0x20DBB4358B0,DXGI,0,0,0,Composed: Flip,Application,2117998304,15.6482,15.5347,0.1135,0.4784,15.2950,0.2278,15.0672,0.0000,37.2993,16.6803,-1.2863,4481.4058,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2118045590,16.3911,16.3029,0.0882,0.1153,16.3095,0.2752,16.0343,0.0000,32.5707,16.6803,0.1983,4486.1344,NA,NA,NA
@@ -339,7 +339,7 @@ dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,21238793
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2124048354,21.1251,17.0529,4.0722,0.0000,17.3789,0.4213,16.9576,0.0000,32.7512,16.6772,0.2240,5086.4108,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2124259605,12.0497,11.9372,0.1125,0.0366,11.9761,0.0837,11.8924,0.0000,28.3033,16.6739,4.4479,5107.5359,NA,NA,NA
dwm.exe,1268,0x224B280A1C0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2124380102,17.1166,16.9739,0.1427,0.0000,17.0923,0.2720,16.8203,0.0000,32.9275,16.7109,-4.6242,5119.5856,NA,NA,NA
-Presenter.exe,11100,0x0,Other,1,0,0,Hardware: Legacy Flip,Application,2124719370,80.5150,80.5150,0.0000,0.4520,0.0885,0.0885,0.0000,0.0000,99.1472,16.6727,0.0000,5153.5124,NA,NA,NA
+Presenter.exe,11100,0x0,Other,1,0,0,Hardware: Legacy Flip,Application,2124719370,80.5150,80.5150,0.0000,0.4520,0.0885,0.0885,0.0000,0.0000,99.1472,16.6727,NA,5153.5124,NA,NA,NA
Presenter.exe,11100,0x0,Other,1,0,0,Hardware: Legacy Flip,Application,2125524520,10.3918,10.3918,0.0000,0.1928,0.6808,0.2129,0.4679,0.0000,35.3049,16.6535,63.8423,5234.0274,NA,NA,NA
Presenter.exe,11100,0x0,Other,1,0,0,Hardware: Legacy Flip,Application,2125628438,15.6228,15.6228,0.0000,0.0451,24.9003,0.4760,24.4243,0.0000,41.5666,16.6806,-6.2617,5244.4192,NA,NA,NA
Presenter.exe,11100,0x0,Other,1,0,0,Hardware: Legacy Flip,Application,2125784666,15.6398,15.6398,0.0000,9.3226,16.6524,0.4381,16.2143,0.0000,42.6244,16.6870,-1.0578,5260.0420,NA,NA,NA
diff --git a/Tests/Gold/test_case_1.csv b/Tests/Gold/test_case_1.csv
index 92c960d1..6078f655 100644
--- a/Tests/Gold/test_case_1.csv
+++ b/Tests/Gold/test_case_1.csv
@@ -1,11 +1,11 @@
-Application,ProcessID,SwapChainAddress,PresentRuntime,SyncInterval,PresentFlags,AllowsTearing,PresentMode,FrameType,TimeInQPC,MsBetweenSimulationStart,MsBetweenPresents,MsBetweenDisplayChange,MsInPresentAPI,MsRenderPresentLatency,MsUntilDisplayed,MsPCLatency,CPUStartQPC,MsBetweenAppStart,MsCPUBusy,MsCPUWait,MsGPULatency,MsGPUTime,MsGPUBusy,MsGPUWait,MsVideoBusy,MsAnimationError,AnimationTime,MsAllInputToPhotonLatency,MsClickToPhotonLatency,MsInstrumentedLatency
-dwm.exe,1564,0x2408E0B7CA0,DXGI,1,2,0,Hardware: Legacy Flip,Application,1857900376640,NA,16.60830000000000,16.62160000000000,0.23360000000000,0.19390000000000,16.2114,NA,1857900212645,16.6331,16.3995,0.2336,0.0938,16.4996,0.6803,15.8193,0.0000,0.0000,589.9990,NA,NA,NA
+Application,ProcessID,SwapChainAddress,PresentRuntime,SyncInterval,PresentFlags,AllowsTearing,PresentMode,FrameType,TimeInQPC,MsBetweenSimulationStart,MsBetweenPresents,MsBetweenDisplayChange,MsInPresentAPI,MsRenderPresentLatency,MsUntilDisplayed,MsPCLatency,CPUStartQPC,MsBetweenAppStart,MsCPUBusy,MsCPUWait,MsGPULatency,MsGPUTime,MsGPUBusy,MsGPUWait,MsVideoBusy,MsAnimationError,AnimationTime,MsAllInputToPhotonLatency,MsClickToPhotonLatency,MsInstrumentedLatency
+dwm.exe,1564,0x2408E0B7CA0,DXGI,1,2,0,Hardware: Legacy Flip,Application,1857900376640,NA,16.60830000000000,16.62160000000000,0.23360000000000,0.19390000000000,16.2114,NA,1857900212645,16.6331,16.3995,0.2336,0.0938,16.4996,0.6803,15.8193,0.0000,NA,589.9990,NA,NA,NA
dwm.exe,1564,0x2408E0B7CA0,DXGI,1,2,0,Hardware: Legacy Flip,Application,1857900710190,NA,33.35500000000000,33.36470000000000,0.21790000000000,0.15990000000000,16.2211,NA,1857900378976,33.3393,33.1214,0.2179,0.0000,33.3210,0.6792,32.6418,0.0000,-16.7316,606.6321,NA,NA,NA
dwm.exe,1564,0x2408E0B7CA0,DXGI,1,0,0,Hardware: Legacy Flip,Application,1857901234475,NA,52.42850000000000,49.99050000000000,0.24810000000000,0.17490000000000,13.7831,NA,1857900712369,52.4587,52.2106,0.2481,0.0000,52.4435,0.2331,52.2104,0.0000,-16.6512,639.9714,NA,NA,NA
-dwm.exe,1564,0x240A8D570F0,DXGI,1,0,0,Hardware: Legacy Flip,Application,1857901237043,NA,102.43200000000000,116.77079999999999,0.12170000000000,0.10820000000000,16.7004,NA,1857900213626,102.4634,102.3417,0.1217,102.2598,0.1901,0.1901,0.0000,0.0000,0.0000,590.0971,NA,NA,NA
+dwm.exe,1564,0x240A8D570F0,DXGI,1,0,0,Hardware: Legacy Flip,Application,1857901237043,NA,102.43200000000000,116.77079999999999,0.12170000000000,0.10820000000000,16.7004,NA,1857900213626,102.4634,102.3417,0.1217,102.2598,0.1901,0.1901,0.0000,0.0000,NA,590.0971,NA,NA,NA
dwm.exe,1564,0x2408E0B7CA0,DXGI,1,2,0,Hardware: Legacy Flip,Application,1857901378625,NA,14.41500000000000,16.67730000000000,0.22500000000000,0.15110000000000,16.0454,NA,1857901236956,14.3919,14.1669,0.2250,0.1169,14.2011,0.5995,13.6016,0.0000,35.7814,692.4301,NA,NA,NA
dwm.exe,1564,0x240A8D570F0,DXGI,1,0,0,Hardware: Legacy Flip,Application,1857901381172,NA,14.41290000000000,16.65580000000000,0.14930000000000,0.09740000000000,18.9433,NA,1857901238260,14.4405,14.2912,0.1493,14.1876,0.2010,0.1323,0.0687,0.0000,85.8076,692.5605,NA,NA,NA
-Presenter.exe,24560,0x2019D7777C0,DXGI,0,0,0,Composed: Flip,Application,1857901506031,NA,12.00270000000000,NA,0.46790000000000,0.40010000000000,19.9784,NA,1857901396898,11.3812,10.9133,0.4679,2.1063,9.2071,0.1696,9.0375,0.0000,0.0000,708.4243,NA,NA,NA
+Presenter.exe,24560,0x2019D7777C0,DXGI,0,0,0,Composed: Flip,Application,1857901506031,NA,12.00270000000000,NA,0.46790000000000,0.40010000000000,19.9784,NA,1857901396898,11.3812,10.9133,0.4679,2.1063,9.2071,0.1696,9.0375,0.0000,NA,708.4243,NA,NA,NA
Presenter.exe,24560,0x2019D7777C0,DXGI,0,0,0,Composed: Flip,Application,1857901605971,NA,9.99400000000000,NA,0.31910000000000,0.39070000000000,NA,NA,1857901510710,9.8452,9.5261,0.3191,0.7618,9.1550,0.2181,8.9369,0.0000,NA,NA,NA,NA,NA
dwm.exe,1564,0x2408E0B7CA0,DXGI,1,0,0,Hardware: Legacy Flip,Application,1857901580785,NA,20.21600000000000,16.67360000000000,0.34050000000000,0.16570000000000,12.5030,NA,1857901380875,20.3315,19.9910,0.3405,0.1271,20.0296,0.1241,19.9055,0.0000,-2.2817,706.8220,NA,NA,NA
dwm.exe,1564,0x240A8D570F0,DXGI,1,0,0,Hardware: Legacy Flip,Application,1857901585511,NA,20.43390000000000,16.70160000000000,0.17620000000000,0.12980000000000,15.2110,NA,1857901382665,20.4608,20.2846,0.1762,19.9777,0.4367,0.2754,0.1613,0.0000,-2.2611,707.0010,NA,NA,NA
@@ -37,7 +37,7 @@ dwm.exe,1564,0x240A8D570F0,DXGI,1,0,0,Hardware: Legacy Flip,Application,18579035
dwm.exe,1564,0x2408E0B7CA0,DXGI,1,0,0,Hardware: Legacy Flip,Application,1857903547874,NA,14.28710000000000,16.66720000000000,0.22560000000000,0.14730000000000,15.8393,NA,1857903407305,14.2825,14.0569,0.2256,0.0000,14.2646,0.1113,14.1533,0.0000,-4.1189,909.4650,NA,NA,NA
dwm.exe,1564,0x2408E0B7CA0,DXGI,1,2,0,Hardware: Legacy Flip,Application,1857903711346,NA,16.34720000000000,16.66700000000000,0.20090000000000,0.14380000000000,16.1591,NA,1857903550130,16.3225,16.1216,0.2009,0.0868,16.1786,0.1893,15.9893,0.0000,-2.3845,923.7475,NA,NA,NA
dwm.exe,1564,0x2408E0B7CA0,DXGI,1,2,0,Hardware: Legacy Flip,Application,1857903877046,NA,16.57000000000000,16.70460000000000,0.25700000000000,0.18440000000000,16.2937,NA,1857903713355,16.6261,16.3691,0.2570,0.1542,16.3993,0.1142,16.2851,0.0000,-0.3821,940.0700,NA,NA,NA
-devenv.exe,24944,0x1E25CF20,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,1857903714902,NA,317.33760000000001,316.75819999999999,0.37190000000000,0.30840000000000,32.5081,NA,1857900544731,317.3890,317.0171,0.3719,0.4938,316.8317,0.1769,316.6548,0.0000,0.0000,623.2076,NA,NA,NA
+devenv.exe,24944,0x1E25CF20,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,1857903714902,NA,317.33760000000001,316.75819999999999,0.37190000000000,0.30840000000000,32.5081,NA,1857900544731,317.3890,317.0171,0.3719,0.4938,316.8317,0.1769,316.6548,0.0000,NA,623.2076,NA,NA,NA
dwm.exe,1564,0x2408E0B7CA0,DXGI,1,2,0,Hardware: Legacy Flip,Application,1857904711904,NA,83.48580000000000,83.35360000000000,0.21240000000000,0.15140000000000,16.1615,NA,1857903879616,83.4412,83.2288,0.2124,0.0000,83.4528,0.1118,83.3410,0.0000,-66.7275,956.6961,NA,NA,NA
dwm.exe,1564,0x240A8D570F0,DXGI,1,0,0,Hardware: Legacy Flip,Application,1857903713431,NA,16.32180000000000,16.68860000000000,0.09250000000000,0.08530000000000,2.5723,NA,1857903551091,16.3265,16.2340,0.0925,16.1693,0.1500,0.0738,0.0762,0.0000,32.1031,923.8436,NA,NA,NA
dwm.exe,1564,0x2408E0B7CA0,DXGI,1,2,0,Hardware: Legacy Flip,Application,1857907045821,NA,233.39169999999999,233.40039999999999,0.33580000000000,0.25010000000000,16.1702,NA,1857904714028,233.5151,233.1793,0.3358,0.0000,233.4904,0.2436,233.2468,0.0000,-149.9592,1040.1373,NA,NA,NA
diff --git a/Tests/Gold/test_case_1_v2.csv b/Tests/Gold/test_case_1_v2.csv
index 4d342540..0d500cc9 100644
--- a/Tests/Gold/test_case_1_v2.csv
+++ b/Tests/Gold/test_case_1_v2.csv
@@ -1,11 +1,11 @@
Application,ProcessID,SwapChainAddress,PresentRuntime,SyncInterval,PresentFlags,AllowsTearing,PresentMode,FrameType,CPUStartQPC,FrameTime,CPUBusy,CPUWait,GPULatency,GPUTime,GPUBusy,GPUWait,VideoBusy,DisplayLatency,DisplayedTime,AnimationError,AnimationTime,AllInputToPhotonLatency,ClickToPhotonLatency,InstrumentedLatency
-dwm.exe,1564,0x2408E0B7CA0,DXGI,1,2,0,Hardware: Legacy Flip,Application,1857900212645,16.6331,16.3995,0.2336,0.0938,16.4996,0.6803,15.8193,0.0000,32.6109,33.3647,0.0000,589.9990,NA,NA,NA
+dwm.exe,1564,0x2408E0B7CA0,DXGI,1,2,0,Hardware: Legacy Flip,Application,1857900212645,16.6331,16.3995,0.2336,0.0938,16.4996,0.6803,15.8193,0.0000,32.6109,33.3647,NA,589.9990,NA,NA,NA
dwm.exe,1564,0x2408E0B7CA0,DXGI,1,2,0,Hardware: Legacy Flip,Application,1857900378976,33.3393,33.1214,0.2179,0.0000,33.3210,0.6792,32.6418,0.0000,49.3425,49.9905,-16.7316,606.6321,NA,NA,NA
dwm.exe,1564,0x2408E0B7CA0,DXGI,1,0,0,Hardware: Legacy Flip,Application,1857900712369,52.4587,52.2106,0.2481,0.0000,52.4435,0.2331,52.2104,0.0000,65.9937,16.6773,-16.6512,639.9714,NA,NA,NA
-dwm.exe,1564,0x240A8D570F0,DXGI,1,0,0,Hardware: Legacy Flip,Application,1857900213626,102.4634,102.3417,0.1217,102.2598,0.1901,0.1901,0.0000,0.0000,119.0421,16.6558,0.0000,590.0971,NA,NA,NA
+dwm.exe,1564,0x240A8D570F0,DXGI,1,0,0,Hardware: Legacy Flip,Application,1857900213626,102.4634,102.3417,0.1217,102.2598,0.1901,0.1901,0.0000,0.0000,119.0421,16.6558,NA,590.0971,NA,NA,NA
dwm.exe,1564,0x2408E0B7CA0,DXGI,1,2,0,Hardware: Legacy Flip,Application,1857901236956,14.3919,14.1669,0.2250,0.1169,14.2011,0.5995,13.6016,0.0000,30.2123,16.6736,35.7814,692.4301,NA,NA,NA
dwm.exe,1564,0x240A8D570F0,DXGI,1,0,0,Hardware: Legacy Flip,Application,1857901238260,14.4405,14.2912,0.1493,14.1876,0.2010,0.1323,0.0687,0.0000,33.2345,16.7016,85.8076,692.5605,NA,NA,NA
-Presenter.exe,24560,0x2019D7777C0,DXGI,0,0,0,Composed: Flip,Application,1857901396898,11.3812,10.9133,0.4679,2.1063,9.2071,0.1696,9.0375,0.0000,30.8917,16.6654,0.0000,708.4243,NA,NA,NA
+Presenter.exe,24560,0x2019D7777C0,DXGI,0,0,0,Composed: Flip,Application,1857901396898,11.3812,10.9133,0.4679,2.1063,9.2071,0.1696,9.0375,0.0000,30.8917,16.6654,NA,708.4243,NA,NA,NA
Presenter.exe,24560,0x2019D7777C0,DXGI,0,0,0,Composed: Flip,Application,1857901510710,9.8452,9.5261,0.3191,0.7618,9.1550,0.2181,8.9369,0.0000,NA,NA,NA,NA,NA,NA,NA
dwm.exe,1564,0x2408E0B7CA0,DXGI,1,0,0,Hardware: Legacy Flip,Application,1857901380875,20.3315,19.9910,0.3405,0.1271,20.0296,0.1241,19.9055,0.0000,32.4940,16.6654,-2.2817,706.8220,NA,NA,NA
dwm.exe,1564,0x240A8D570F0,DXGI,1,0,0,Hardware: Legacy Flip,Application,1857901382665,20.4608,20.2846,0.1762,19.9777,0.4367,0.2754,0.1613,0.0000,35.4956,16.6604,-2.2611,707.0010,NA,NA,NA
@@ -37,7 +37,7 @@ dwm.exe,1564,0x240A8D570F0,DXGI,1,0,0,Hardware: Legacy Flip,Application,18579030
dwm.exe,1564,0x2408E0B7CA0,DXGI,1,0,0,Hardware: Legacy Flip,Application,1857903407305,14.2825,14.0569,0.2256,0.0000,14.2646,0.1113,14.1533,0.0000,29.8962,16.6670,-4.1189,909.4650,NA,NA,NA
dwm.exe,1564,0x2408E0B7CA0,DXGI,1,2,0,Hardware: Legacy Flip,Application,1857903550130,16.3225,16.1216,0.2009,0.0868,16.1786,0.1893,15.9893,0.0000,32.2807,16.7046,-2.3845,923.7475,NA,NA,NA
dwm.exe,1564,0x2408E0B7CA0,DXGI,1,2,0,Hardware: Legacy Flip,Application,1857903713355,16.6261,16.3691,0.2570,0.1542,16.3993,0.1142,16.2851,0.0000,32.6628,83.3536,-0.3821,940.0700,NA,NA,NA
-devenv.exe,24944,0x1E25CF20,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,1857900544731,317.3890,317.0171,0.3719,0.4938,316.8317,0.1769,316.6548,0.0000,349.5252,316.7540,0.0000,623.2076,NA,NA,NA
+devenv.exe,24944,0x1E25CF20,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,1857900544731,317.3890,317.0171,0.3719,0.4938,316.8317,0.1769,316.6548,0.0000,349.5252,316.7540,NA,623.2076,NA,NA,NA
dwm.exe,1564,0x2408E0B7CA0,DXGI,1,2,0,Hardware: Legacy Flip,Application,1857903879616,83.4412,83.2288,0.2124,0.0000,83.4528,0.1118,83.3410,0.0000,99.3903,233.4004,-66.7275,956.6961,NA,NA,NA
dwm.exe,1564,0x240A8D570F0,DXGI,1,0,0,Hardware: Legacy Flip,Application,1857903551091,16.3265,16.2340,0.0925,16.1693,0.1500,0.0738,0.0762,0.0000,18.8063,483.7742,32.1031,923.8436,NA,NA,NA
dwm.exe,1564,0x2408E0B7CA0,DXGI,1,2,0,Hardware: Legacy Flip,Application,1857904714028,233.5151,233.1793,0.3358,0.0000,233.4904,0.2436,233.2468,0.0000,249.3495,150.0195,-149.9592,1040.1373,NA,NA,NA
diff --git a/Tests/Gold/test_case_2.csv b/Tests/Gold/test_case_2.csv
index 833983eb..d595c14c 100644
--- a/Tests/Gold/test_case_2.csv
+++ b/Tests/Gold/test_case_2.csv
@@ -1,10 +1,10 @@
-Application,ProcessID,SwapChainAddress,PresentRuntime,SyncInterval,PresentFlags,AllowsTearing,PresentMode,FrameType,TimeInQPC,MsBetweenSimulationStart,MsBetweenPresents,MsBetweenDisplayChange,MsInPresentAPI,MsRenderPresentLatency,MsUntilDisplayed,MsPCLatency,CPUStartQPC,MsBetweenAppStart,MsCPUBusy,MsCPUWait,MsGPULatency,MsGPUTime,MsGPUBusy,MsGPUWait,MsVideoBusy,MsAnimationError,AnimationTime,MsAllInputToPhotonLatency,MsClickToPhotonLatency,MsInstrumentedLatency
-dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8086531034,NA,16.72210000000000,16.62600000000000,0.15220000000000,0.17940000000000,16.2531,NA,8086364705,16.7851,16.6329,0.1522,2.5541,14.2582,0.3531,13.9051,0.0000,0.0000,421.9730,NA,NA,NA
+Application,ProcessID,SwapChainAddress,PresentRuntime,SyncInterval,PresentFlags,AllowsTearing,PresentMode,FrameType,TimeInQPC,MsBetweenSimulationStart,MsBetweenPresents,MsBetweenDisplayChange,MsInPresentAPI,MsRenderPresentLatency,MsUntilDisplayed,MsPCLatency,CPUStartQPC,MsBetweenAppStart,MsCPUBusy,MsCPUWait,MsGPULatency,MsGPUTime,MsGPUBusy,MsGPUWait,MsVideoBusy,MsAnimationError,AnimationTime,MsAllInputToPhotonLatency,MsClickToPhotonLatency,MsInstrumentedLatency
+dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8086531034,NA,16.72210000000000,16.62600000000000,0.15220000000000,0.17940000000000,16.2531,NA,8086364705,16.7851,16.6329,0.1522,2.5541,14.2582,0.3531,13.9051,0.0000,NA,421.9730,NA,NA,NA
dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8086864256,NA,33.32220000000000,33.37830000000000,0.13630000000000,0.16780000000000,16.3092,NA,8086532556,33.3063,33.1700,0.1363,0.0272,33.3106,0.3341,32.9765,0.0000,-16.5932,438.7581,NA,NA,NA
dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8087197921,NA,33.36650000000000,33.34980000000000,0.08100000000000,0.07910000000000,16.2925,NA,8086865619,33.3112,33.2302,0.0810,0.0315,33.2778,0.3579,32.9199,0.0000,-0.0435,472.0644,NA,NA,NA
dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8087377067,NA,17.91460000000000,16.63160000000000,0.09670000000000,0.13130000000000,15.0095,NA,8087198731,17.9303,17.8336,0.0967,0.0000,17.9668,0.3061,17.6607,0.0000,16.6796,505.3756,NA,NA,NA
dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8087532152,NA,15.50850000000000,17.01750000000000,0.10340000000000,0.74610000000000,16.5185,NA,8087378034,15.5152,15.4118,0.1034,0.0346,16.1233,1.1187,15.0046,0.0000,0.9128,523.3059,NA,NA,NA
-Presenter.exe,10016,0x1BA6DC82C58,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,8087517434,NA,7.02520000000000,16.59000000000000,1.84770000000000,5.03430000000000,34.5803,NA,8087515642,2.0269,0.1792,1.8477,4.5334,0.6801,0.6801,0.0000,0.0000,0.0000,537.0667,NA,NA,NA
+Presenter.exe,10016,0x1BA6DC82C58,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,8087517434,NA,7.02520000000000,16.59000000000000,1.84770000000000,5.03430000000000,34.5803,NA,8087515642,2.0269,0.1792,1.8477,4.5334,0.6801,0.6801,0.0000,0.0000,NA,537.0667,NA,NA,NA
dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8087702601,NA,17.04490000000000,16.59000000000000,0.10820000000000,0.12890000000000,16.0636,NA,8087533186,17.0497,16.9415,0.1082,0.6427,16.4277,0.4585,15.9692,0.0000,-1.0748,538.8211,NA,NA,NA
Presenter.exe,10016,0x1BA6DC82C58,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,8087536372,NA,1.89380000000000,16.70460000000000,17.21260000000000,21.57300000000000,49.3911,NA,8087535911,17.2587,0.0461,17.2126,3.1866,18.4325,0.8600,17.5725,0.0000,-14.6777,539.0936,NA,NA,NA
dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8087870996,NA,16.83950000000000,16.70460000000000,0.17660000000000,0.24250000000000,15.9287,NA,8087703683,16.9079,16.7313,0.1766,0.0207,16.9531,0.6088,16.3443,0.0000,0.3451,555.8708,NA,NA,NA
@@ -56,7 +56,7 @@ dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,80930366
dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8093215505,NA,17.88490000000000,16.70130000000000,0.08890000000000,0.12460000000000,15.0585,NA,8093037612,17.8782,17.7893,0.0889,0.5104,17.4035,0.5756,16.8279,0.0000,-0.4100,1089.2637,NA,NA,NA
dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8093376298,NA,16.07930000000000,16.71390000000000,0.09640000000000,0.10460000000000,15.6931,NA,8093216394,16.0868,15.9904,0.0964,0.0357,16.0593,0.7770,15.2823,0.0000,1.1643,1107.1419,NA,NA,NA
dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8093610178,NA,23.38800000000000,100.10110000000000,0.13880000000000,0.20840000000000,92.4062,NA,8093377262,23.4304,23.2916,0.1388,0.0082,23.4918,1.5215,21.9703,0.0000,-84.0143,1123.2287,NA,NA,NA
-Presenter.exe,5348,0x28F99FCFD50,DXGI,0,0,0,Composed: Flip,Application,8093549040,NA,15.60610000000000,16.65630000000000,1.33410000000000,0.28650000000000,115.1763,NA,8093420326,14.2055,12.8714,1.3341,0.7979,12.3600,0.6429,11.7171,0.0000,0.0000,1127.5351,NA,NA,NA
+Presenter.exe,5348,0x28F99FCFD50,DXGI,0,0,0,Composed: Flip,Application,8093549040,NA,15.60610000000000,16.65630000000000,1.33410000000000,0.28650000000000,115.1763,NA,8093420326,14.2055,12.8714,1.3341,0.7979,12.3600,0.6429,11.7171,0.0000,NA,1127.5351,NA,NA,NA
dwm.exe,1300,0x296989CD030,DXGI,0,0,0,Hardware: Legacy Flip,Application,8093703685,NA,9.35070000000000,16.65630000000000,0.07150000000000,-9.06870000000000,99.7118,NA,8093611566,9.2834,9.2119,0.0715,0.0696,0.0736,0.0736,0.0000,0.0000,6.7741,1146.6591,NA,NA,NA
Presenter.exe,5348,0x28F99FCFD50,DXGI,0,0,0,Composed: Flip,Application,8093705796,NA,15.67560000000000,16.67030000000000,0.21760000000000,75.92380000000000,116.1710,NA,8093562381,14.5591,14.3415,0.2176,0.1619,90.1034,0.6611,89.4423,0.0000,-2.4648,1141.7406,NA,NA,NA
Presenter.exe,5348,0x28F99FCFD50,DXGI,0,0,0,Hardware: Independent Flip,Application,8094643159,NA,93.73630000000000,16.69620000000000,0.15920000000000,6.31560000000000,39.1309,NA,8093707972,93.6779,93.5187,0.1592,99.3280,0.5063,0.5063,0.0000,0.0000,-2.1371,1156.2997,NA,NA,NA
@@ -90,5 +90,5 @@ dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,81005500
dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8100710663,NA,16.05920000000000,16.56160000000000,0.07910000000000,0.06730000000000,33.0513,NA,8100551510,15.9944,15.9153,0.0791,0.4297,15.5529,0.7723,14.7806,0.0000,-0.5025,1840.6535,NA,NA,NA
dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8100895800,NA,18.51370000000000,16.66470000000000,0.14610000000000,0.21400000000000,31.2023,NA,8100711454,18.5807,18.4346,0.1461,0.0000,18.6604,0.6825,17.9779,0.0000,-0.6703,1856.6479,NA,NA,NA
dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8101119007,NA,22.32070000000000,NA,0.10150000000000,0.14530000000000,NA,NA,8100897261,22.2761,22.1746,0.1015,0.0679,22.2520,1.4524,20.7996,0.0000,NA,NA,NA,NA,NA
-Presenter.exe,5220,0x13B8AF7D830,DXGI,0,0,0,Composed: Flip,Application,8101064643,NA,16.98790000000000,NA,4.47630000000000,0.81750000000000,114.4600,NA,8100926266,18.3140,13.8377,4.4763,1.1974,13.4578,0.6943,12.7635,0.0000,0.0000,1878.1291,NA,NA,NA
+Presenter.exe,5220,0x13B8AF7D830,DXGI,0,0,0,Composed: Flip,Application,8101064643,NA,16.98790000000000,NA,4.47630000000000,0.81750000000000,114.4600,NA,8100926266,18.3140,13.8377,4.4763,1.1974,13.4578,0.6943,12.7635,0.0000,NA,1878.1291,NA,NA,NA
dwm.exe,1300,0x296989CD030,DXGI,0,512,1,Hardware: Legacy Flip,Application,8101212659,NA,9.36520000000000,100.14200000000000,0.07210000000000,-9.15380000000000,99.6584,NA,8101120022,9.3358,9.2637,0.0721,0.0438,0.0661,0.0661,0.0000,0.0000,-59.2852,1897.5047,NA,NA,NA
diff --git a/Tests/Gold/test_case_2_v2.csv b/Tests/Gold/test_case_2_v2.csv
index 3e46b2d9..6b6da131 100644
--- a/Tests/Gold/test_case_2_v2.csv
+++ b/Tests/Gold/test_case_2_v2.csv
@@ -1,10 +1,10 @@
Application,ProcessID,SwapChainAddress,PresentRuntime,SyncInterval,PresentFlags,AllowsTearing,PresentMode,FrameType,CPUStartQPC,FrameTime,CPUBusy,CPUWait,GPULatency,GPUTime,GPUBusy,GPUWait,VideoBusy,DisplayLatency,DisplayedTime,AnimationError,AnimationTime,AllInputToPhotonLatency,ClickToPhotonLatency,InstrumentedLatency
-dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8086364705,16.7851,16.6329,0.1522,2.5541,14.2582,0.3531,13.9051,0.0000,32.8860,33.3783,0.0000,421.9730,NA,NA,NA
+dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8086364705,16.7851,16.6329,0.1522,2.5541,14.2582,0.3531,13.9051,0.0000,32.8860,33.3783,NA,421.9730,NA,NA,NA
dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8086532556,33.3063,33.1700,0.1363,0.0272,33.3106,0.3341,32.9765,0.0000,49.4792,33.3498,-16.5932,438.7581,NA,NA,NA
dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8086865619,33.3112,33.2302,0.0810,0.0315,33.2778,0.3579,32.9199,0.0000,49.5227,16.6316,-0.0435,472.0644,NA,NA,NA
dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8087198731,17.9303,17.8336,0.0967,0.0000,17.9668,0.3061,17.6607,0.0000,32.8431,17.0175,16.6796,505.3756,NA,NA,NA
dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8087378034,15.5152,15.4118,0.1034,0.0346,16.1233,1.1187,15.0046,0.0000,31.9303,16.5900,0.9128,523.3059,NA,NA,NA
-Presenter.exe,10016,0x1BA6DC82C58,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,8087515642,2.0269,0.1792,1.8477,4.5334,0.6801,0.6801,0.0000,0.0000,34.7595,16.7046,0.0000,537.0667,NA,NA,NA
+Presenter.exe,10016,0x1BA6DC82C58,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,8087515642,2.0269,0.1792,1.8477,4.5334,0.6801,0.6801,0.0000,0.0000,34.7595,16.7046,NA,537.0667,NA,NA,NA
dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8087533186,17.0497,16.9415,0.1082,0.6427,16.4277,0.4585,15.9692,0.0000,33.0051,16.7046,-1.0748,538.8211,NA,NA,NA
Presenter.exe,10016,0x1BA6DC82C58,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,8087535911,17.2587,0.0461,17.2126,3.1866,18.4325,0.8600,17.5725,0.0000,49.4372,16.6609,-14.6777,539.0936,NA,NA,NA
dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8087703683,16.9079,16.7313,0.1766,0.0207,16.9531,0.6088,16.3443,0.0000,32.6600,16.6609,0.3451,555.8708,NA,NA,NA
@@ -56,7 +56,7 @@ dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,80928746
dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8093037612,17.8782,17.7893,0.0889,0.5104,17.4035,0.5756,16.8279,0.0000,32.8478,16.7139,-0.4100,1089.2637,NA,NA,NA
dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8093216394,16.0868,15.9904,0.0964,0.0357,16.0593,0.7770,15.2823,0.0000,31.6835,100.1011,1.1643,1107.1419,NA,NA,NA
dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8093377262,23.4304,23.2916,0.1388,0.0082,23.4918,1.5215,21.9703,0.0000,115.6978,16.6563,-84.0143,1123.2287,NA,NA,NA
-Presenter.exe,5348,0x28F99FCFD50,DXGI,0,0,0,Composed: Flip,Application,8093420326,14.2055,12.8714,1.3341,0.7979,12.3600,0.6429,11.7171,0.0000,128.0477,16.6703,0.0000,1127.5351,NA,NA,NA
+Presenter.exe,5348,0x28F99FCFD50,DXGI,0,0,0,Composed: Flip,Application,8093420326,14.2055,12.8714,1.3341,0.7979,12.3600,0.6429,11.7171,0.0000,128.0477,16.6703,NA,1127.5351,NA,NA,NA
dwm.exe,1300,0x296989CD030,DXGI,0,0,0,Hardware: Legacy Flip,Application,8093611566,9.2834,9.2119,0.0715,0.0696,0.0736,0.0736,0.0000,0.0000,108.9237,16.6703,6.7741,1146.6591,NA,NA,NA
Presenter.exe,5348,0x28F99FCFD50,DXGI,0,0,0,Composed: Flip,Application,8093562381,14.5591,14.3415,0.2176,0.1619,90.1034,0.6611,89.4423,0.0000,130.5125,16.6962,-2.4648,1141.7406,NA,NA,NA
Presenter.exe,5348,0x28F99FCFD50,DXGI,0,0,0,Hardware: Independent Flip,Application,8093707972,93.6779,93.5187,0.1592,99.3280,0.5063,0.5063,0.0000,0.0000,132.6496,16.6771,-2.1371,1156.2997,NA,NA,NA
@@ -90,5 +90,5 @@ dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,81003909
dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8100551510,15.9944,15.9153,0.0791,0.4297,15.5529,0.7723,14.7806,0.0000,48.9666,16.6647,-0.5025,1840.6535,NA,NA,NA
dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8100711454,18.5807,18.4346,0.1461,0.0000,18.6604,0.6825,17.9779,0.0000,49.6369,100.1420,-0.6703,1856.6479,NA,NA,NA
dwm.exe,1300,0x296989CD030,DXGI,1,0,0,Hardware: Legacy Flip,Application,8100897261,22.2761,22.1746,0.1015,0.0679,22.2520,1.4524,20.7996,0.0000,NA,NA,NA,NA,NA,NA,NA
-Presenter.exe,5220,0x13B8AF7D830,DXGI,0,0,0,Composed: Flip,Application,8100926266,18.3140,13.8377,4.4763,1.1974,13.4578,0.6943,12.7635,0.0000,128.2977,0.4528,0.0000,1878.1291,NA,NA,NA
+Presenter.exe,5220,0x13B8AF7D830,DXGI,0,0,0,Composed: Flip,Application,8100926266,18.3140,13.8377,4.4763,1.1974,13.4578,0.6943,12.7635,0.0000,128.2977,0.4528,NA,1878.1291,NA,NA,NA
dwm.exe,1300,0x296989CD030,DXGI,0,512,1,Hardware: Legacy Flip,Application,8101120022,9.3358,9.2637,0.0721,0.0438,0.0661,0.0661,0.0000,0.0000,108.9221,0.4528,-59.2852,1897.5047,NA,NA,NA
diff --git a/Tests/Gold/test_case_3.csv b/Tests/Gold/test_case_3.csv
index d64e55f2..719878b0 100644
--- a/Tests/Gold/test_case_3.csv
+++ b/Tests/Gold/test_case_3.csv
@@ -1,9 +1,9 @@
-Application,ProcessID,SwapChainAddress,PresentRuntime,SyncInterval,PresentFlags,AllowsTearing,PresentMode,FrameType,TimeInQPC,MsBetweenSimulationStart,MsBetweenPresents,MsBetweenDisplayChange,MsInPresentAPI,MsRenderPresentLatency,MsUntilDisplayed,MsPCLatency,CPUStartQPC,MsBetweenAppStart,MsCPUBusy,MsCPUWait,MsGPULatency,MsGPUTime,MsGPUBusy,MsGPUWait,MsVideoBusy,MsAnimationError,AnimationTime,MsAllInputToPhotonLatency,MsClickToPhotonLatency,MsInstrumentedLatency
-dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,1402651522,NA,16.58480000000000,16.67960000000000,0.04140000000000,0.06330000000000,16.4926,NA,1402486237,16.5699,16.5285,0.0414,0.0153,16.5765,0.5018,16.0747,0.0000,0.0000,374.7902,NA,NA,NA
+Application,ProcessID,SwapChainAddress,PresentRuntime,SyncInterval,PresentFlags,AllowsTearing,PresentMode,FrameType,TimeInQPC,MsBetweenSimulationStart,MsBetweenPresents,MsBetweenDisplayChange,MsInPresentAPI,MsRenderPresentLatency,MsUntilDisplayed,MsPCLatency,CPUStartQPC,MsBetweenAppStart,MsCPUBusy,MsCPUWait,MsGPULatency,MsGPUTime,MsGPUBusy,MsGPUWait,MsVideoBusy,MsAnimationError,AnimationTime,MsAllInputToPhotonLatency,MsClickToPhotonLatency,MsInstrumentedLatency
+dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,1402651522,NA,16.58480000000000,16.67960000000000,0.04140000000000,0.06330000000000,16.4926,NA,1402486237,16.5699,16.5285,0.0414,0.0153,16.5765,0.5018,16.0747,0.0000,NA,374.7902,NA,NA,NA
dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,1408324027,NA,567.25049999999999,567.16409999999996,0.15770000000000,0.16910000000000,16.4062,NA,1402651936,567.3668,567.2091,0.1577,0.0219,567.3563,0.6674,566.6889,0.0000,-550.5942,391.3601,NA,NA,NA
dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,1408525664,NA,20.16370000000000,16.65680000000000,0.18200000000000,0.32430000000000,12.8993,NA,1408325604,20.1880,20.0060,0.1820,0.0114,20.3189,1.0313,19.2876,0.0000,550.7100,958.7269,NA,NA,NA
dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,1408659114,NA,13.34500000000000,16.68930000000000,0.10570000000000,0.13320000000000,16.2436,NA,1408527484,13.2687,13.1630,0.1057,0.1423,13.1539,3.4062,9.7477,0.0000,3.4987,978.9149,NA,NA,NA
-Presenter.exe,5892,0x1F0FF310E98,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,1408518740,NA,4.18030000000000,16.68590000000000,15.34280000000000,18.41680000000000,46.9669,NA,1408514918,15.7250,0.3822,15.3428,16.2005,2.5985,2.5581,0.0404,0.0000,0.0000,977.6583,NA,NA,NA
+Presenter.exe,5892,0x1F0FF310E98,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,1408518740,NA,4.18030000000000,16.68590000000000,15.34280000000000,18.41680000000000,46.9669,NA,1408514918,15.7250,0.3822,15.3428,16.2005,2.5985,2.5581,0.0404,0.0000,NA,977.6583,NA,NA,NA
dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,1408826845,NA,16.77310000000000,16.68590000000000,0.09570000000000,0.08960000000000,16.1564,NA,1408660171,16.7631,16.6674,0.0957,0.0275,16.7295,1.6659,15.0636,0.0000,-3.4172,992.1836,NA,NA,NA
Presenter.exe,5892,0x1F0FF310E98,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,1408673291,NA,15.45510000000000,16.68810000000000,16.18580000000000,19.97720000000000,48.1999,NA,1408672168,16.2981,0.1123,16.1858,17.5180,2.5715,2.5715,0.0000,0.0000,-0.9631,993.3833,NA,NA,NA
dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,1408991980,NA,16.51350000000000,16.68810000000000,0.10880000000000,0.13430000000000,16.3310,NA,1408827802,16.5266,16.4178,0.1088,0.0000,16.5582,2.0061,14.5521,0.0000,0.0750,1008.9467,NA,NA,NA
@@ -48,7 +48,7 @@ dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,14150115
dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,1415164746,NA,15.32030000000000,16.66730000000000,0.06550000000000,0.06500000000000,16.2119,NA,1415012210,15.3191,15.2536,0.0655,0.0000,15.3248,2.8797,12.4451,0.0000,1.4320,1627.3875,NA,NA,NA
Presenter.exe,10112,0x1ED7B93C580,DXGI,0,0,0,Composed: Flip,Application,1415331279,NA,15.59960000000000,NA,1.02620000000000,-12.54210000000000,NA,NA,1415190018,15.1523,14.1261,1.0262,0.6077,0.9763,0.9763,0.0000,0.0000,NA,NA,NA,NA,NA
dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,1415340905,NA,17.61590000000000,16.68240000000000,0.06110000000000,0.05580000000000,15.2784,NA,1415165401,17.6115,17.5504,0.0611,0.0000,17.6067,1.9963,15.6104,0.0000,-1.3633,1642.7066,NA,NA,NA
-Presenter.exe,10112,0x1ED7B93C580,DXGI,0,0,0,Composed: Flip,Application,1415487098,NA,15.58190000000000,16.66970000000000,0.09160000000000,-11.54470000000000,17.3288,NA,1415341541,14.6473,14.5557,0.0916,2.2110,0.8000,0.8000,0.0000,0.0000,0.0000,1660.3206,NA,NA,NA
+Presenter.exe,10112,0x1ED7B93C580,DXGI,0,0,0,Composed: Flip,Application,1415487098,NA,15.58190000000000,16.66970000000000,0.09160000000000,-11.54470000000000,17.3288,NA,1415341541,14.6473,14.5557,0.0916,2.2110,0.8000,0.8000,0.0000,0.0000,NA,1660.3206,NA,NA,NA
dwm.exe,1252,0x22E6AFA2560,DXGI,1,2,0,Hardware: Legacy Flip,Application,1415496014,NA,15.51090000000000,16.66970000000000,0.04130000000000,-13.23630000000000,16.4372,NA,1415341516,15.4911,15.4498,0.0413,0.0000,2.2188,2.2188,0.0000,0.0000,0.9418,1660.3181,NA,NA,NA
Presenter.exe,10112,0x1ED7B93C580,DXGI,0,0,0,Composed: Flip,Application,1415643687,NA,15.65890000000000,33.46460000000000,0.05400000000000,2.70160000000000,35.1345,NA,1415488014,15.6213,15.5673,0.0540,17.2666,1.0023,1.0023,0.0000,0.0000,-18.8173,1674.9679,NA,NA,NA
Presenter.exe,10112,0x1ED7B93C580,DXGI,0,0,0,Hardware Composed: Independent Flip,Application,1415799653,NA,15.59660000000000,16.67980000000000,0.04540000000000,-11.59410000000000,36.2177,NA,1415644227,15.5880,15.5426,0.0454,2.9424,1.0061,1.0061,0.0000,0.0000,-1.0585,1690.5892,NA,NA,NA
@@ -75,7 +75,7 @@ dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,14195072
dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,1419667727,NA,16.04680000000000,16.71090000000000,0.05760000000000,0.05310000000000,16.2863,NA,1419507863,16.0440,15.9864,0.0576,0.0000,16.0417,2.5971,13.4446,0.0000,0.6209,2076.9528,NA,NA,NA
dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,1419839503,NA,17.17760000000000,16.68400000000000,0.05300000000000,0.05920000000000,15.7927,NA,1419668303,17.1730,17.1200,0.0530,0.0000,17.1837,2.1016,15.0821,0.0000,-0.6400,2092.9968,NA,NA,NA
dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,1420033534,NA,19.40310000000000,16.67030000000000,0.05360000000000,0.37010000000000,13.0599,NA,1419840033,19.4037,19.3501,0.0536,0.0062,19.7140,3.2188,16.4952,0.0000,0.5027,2110.1698,NA,NA,NA
-Presenter.exe,12980,0x2C6BEB300A0,DXGI,0,0,0,Composed: Flip,Application,1420017266,NA,15.55450000000000,16.69890000000000,1.58870000000000,-12.92350000000000,31.3856,NA,1419875294,15.7859,14.1972,1.5887,0.3109,0.9628,0.9628,0.0000,0.0000,0.0000,2113.6959,NA,NA,NA
+Presenter.exe,12980,0x2C6BEB300A0,DXGI,0,0,0,Composed: Flip,Application,1420017266,NA,15.55450000000000,16.69890000000000,1.58870000000000,-12.92350000000000,31.3856,NA,1419875294,15.7859,14.1972,1.5887,0.3109,0.9628,0.9628,0.0000,0.0000,NA,2113.6959,NA,NA,NA
dwm.exe,1252,0x22E6AFA2560,DXGI,1,2,0,Hardware: Legacy Flip,Application,1420166075,NA,13.25410000000000,16.69890000000000,0.03340000000000,-10.73410000000000,16.5047,NA,1420034070,13.2339,13.2005,0.0334,0.3165,2.1499,2.1499,0.0000,0.0000,2.7048,2129.5735,NA,NA,NA
Presenter.exe,12980,0x2C6BEB300A0,DXGI,0,0,0,Composed: Flip,Application,1420173751,NA,15.64850000000000,16.80620000000000,0.36330000000000,-10.56410000000000,32.5433,NA,1420033153,14.4231,14.0598,0.3633,0.0582,3.4375,1.2580,2.1795,0.0000,-1.0203,2129.4818,NA,NA,NA
Presenter.exe,12980,0x2C6BEB300A0,DXGI,0,0,1,Hardware Composed: Independent Flip,Application,1420330064,NA,15.63130000000000,0.50980000000000,0.29390000000000,1.13630000000000,17.4218,NA,1420177384,15.5619,15.2680,0.2939,15.3891,1.0152,1.0152,0.0000,0.0000,13.9133,2143.9049,NA,NA,NA
diff --git a/Tests/Gold/test_case_3_v2.csv b/Tests/Gold/test_case_3_v2.csv
index 62fc40b1..b4a52cea 100644
--- a/Tests/Gold/test_case_3_v2.csv
+++ b/Tests/Gold/test_case_3_v2.csv
@@ -1,9 +1,9 @@
Application,ProcessID,SwapChainAddress,PresentRuntime,SyncInterval,PresentFlags,AllowsTearing,PresentMode,FrameType,CPUStartQPC,FrameTime,CPUBusy,CPUWait,GPULatency,GPUTime,GPUBusy,GPUWait,VideoBusy,DisplayLatency,DisplayedTime,AnimationError,AnimationTime,AllInputToPhotonLatency,ClickToPhotonLatency,InstrumentedLatency
-dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,1402486237,16.5699,16.5285,0.0414,0.0153,16.5765,0.5018,16.0747,0.0000,33.0211,567.1641,0.0000,374.7902,NA,NA,NA
+dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,1402486237,16.5699,16.5285,0.0414,0.0153,16.5765,0.5018,16.0747,0.0000,33.0211,567.1641,NA,374.7902,NA,NA,NA
dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,1402651936,567.3668,567.2091,0.1577,0.0219,567.3563,0.6674,566.6889,0.0000,583.6153,16.6568,-550.5942,391.3601,NA,NA,NA
dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,1408325604,20.1880,20.0060,0.1820,0.0114,20.3189,1.0313,19.2876,0.0000,32.9053,16.6893,550.7100,958.7269,NA,NA,NA
dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,1408527484,13.2687,13.1630,0.1057,0.1423,13.1539,3.4062,9.7477,0.0000,29.4066,16.6859,3.4987,978.9149,NA,NA,NA
-Presenter.exe,5892,0x1F0FF310E98,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,1408514918,15.7250,0.3822,15.3428,16.2005,2.5985,2.5581,0.0404,0.0000,47.3491,16.6881,0.0000,977.6583,NA,NA,NA
+Presenter.exe,5892,0x1F0FF310E98,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,1408514918,15.7250,0.3822,15.3428,16.2005,2.5985,2.5581,0.0404,0.0000,47.3491,16.6881,NA,977.6583,NA,NA,NA
dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,1408660171,16.7631,16.6674,0.0957,0.0275,16.7295,1.6659,15.0636,0.0000,32.8238,16.6881,-3.4172,992.1836,NA,NA,NA
Presenter.exe,5892,0x1F0FF310E98,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,1408672168,16.2981,0.1123,16.1858,17.5180,2.5715,2.5715,0.0000,0.0000,48.3122,16.6857,-0.9631,993.3833,NA,NA,NA
dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,1408827802,16.5266,16.4178,0.1088,0.0000,16.5582,2.0061,14.5521,0.0000,32.7488,16.6857,0.0750,1008.9467,NA,NA,NA
@@ -48,7 +48,7 @@ dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,14148312
dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,1415012210,15.3191,15.2536,0.0655,0.0000,15.3248,2.8797,12.4451,0.0000,31.4655,16.6824,1.4320,1627.3875,NA,NA,NA
Presenter.exe,10112,0x1ED7B93C580,DXGI,0,0,0,Composed: Flip,Application,1415190018,15.1523,14.1261,1.0262,0.6077,0.9763,0.9763,0.0000,0.0000,NA,NA,NA,NA,NA,NA,NA
dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,1415165401,17.6115,17.5504,0.0611,0.0000,17.6067,1.9963,15.6104,0.0000,32.8288,16.6697,-1.3633,1642.7066,NA,NA,NA
-Presenter.exe,10112,0x1ED7B93C580,DXGI,0,0,0,Composed: Flip,Application,1415341541,14.6473,14.5557,0.0916,2.2110,0.8000,0.8000,0.0000,0.0000,31.8845,33.4646,0.0000,1660.3206,NA,NA,NA
+Presenter.exe,10112,0x1ED7B93C580,DXGI,0,0,0,Composed: Flip,Application,1415341541,14.6473,14.5557,0.0916,2.2110,0.8000,0.8000,0.0000,0.0000,31.8845,33.4646,NA,1660.3206,NA,NA,NA
dwm.exe,1252,0x22E6AFA2560,DXGI,1,2,0,Hardware: Legacy Flip,Application,1415341516,15.4911,15.4498,0.0413,0.0000,2.2188,2.2188,0.0000,0.0000,31.8870,33.4646,0.9418,1660.3181,NA,NA,NA
Presenter.exe,10112,0x1ED7B93C580,DXGI,0,0,0,Composed: Flip,Application,1415488014,15.6213,15.5673,0.0540,17.2666,1.0023,1.0023,0.0000,0.0000,50.7018,16.6798,-18.8173,1674.9679,NA,NA,NA
Presenter.exe,10112,0x1ED7B93C580,DXGI,0,0,0,Hardware Composed: Independent Flip,Application,1415644227,15.5880,15.5426,0.0454,2.9424,1.0061,1.0061,0.0000,0.0000,51.7603,16.6769,-1.0585,1690.5892,NA,NA,NA
@@ -75,7 +75,7 @@ dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,14193345
dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,1419507863,16.0440,15.9864,0.0576,0.0000,16.0417,2.5971,13.4446,0.0000,32.2727,16.6840,0.6209,2076.9528,NA,NA,NA
dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,1419668303,17.1730,17.1200,0.0530,0.0000,17.1837,2.1016,15.0821,0.0000,32.9127,16.6703,-0.6400,2092.9968,NA,NA,NA
dwm.exe,1252,0x22E6AFA2560,DXGI,1,0,0,Hardware: Legacy Flip,Application,1419840033,19.4037,19.3501,0.0536,0.0062,19.7140,3.2188,16.4952,0.0000,32.4100,16.6989,0.5027,2110.1698,NA,NA,NA
-Presenter.exe,12980,0x2C6BEB300A0,DXGI,0,0,0,Composed: Flip,Application,1419875294,15.7859,14.1972,1.5887,0.3109,0.9628,0.9628,0.0000,0.0000,45.5828,16.8062,0.0000,2113.6959,NA,NA,NA
+Presenter.exe,12980,0x2C6BEB300A0,DXGI,0,0,0,Composed: Flip,Application,1419875294,15.7859,14.1972,1.5887,0.3109,0.9628,0.9628,0.0000,0.0000,45.5828,16.8062,NA,2113.6959,NA,NA,NA
dwm.exe,1252,0x22E6AFA2560,DXGI,1,2,0,Hardware: Legacy Flip,Application,1420034070,13.2339,13.2005,0.0334,0.3165,2.1499,2.1499,0.0000,0.0000,29.7052,16.8062,2.7048,2129.5735,NA,NA,NA
Presenter.exe,12980,0x2C6BEB300A0,DXGI,0,0,0,Composed: Flip,Application,1420033153,14.4231,14.0598,0.3633,0.0582,3.4375,1.2580,2.1795,0.0000,46.6031,0.5098,-1.0203,2129.4818,NA,NA,NA
Presenter.exe,12980,0x2C6BEB300A0,DXGI,0,0,1,Hardware Composed: Independent Flip,Application,1420177384,15.5619,15.2680,0.2939,15.3891,1.0152,1.0152,0.0000,0.0000,32.6898,0.6904,13.9133,2143.9049,NA,NA,NA
diff --git a/Tests/Gold/test_case_4.csv b/Tests/Gold/test_case_4.csv
index c0b11986..1f1f2c1e 100644
--- a/Tests/Gold/test_case_4.csv
+++ b/Tests/Gold/test_case_4.csv
@@ -1,10 +1,10 @@
-Application,ProcessID,SwapChainAddress,PresentRuntime,SyncInterval,PresentFlags,AllowsTearing,PresentMode,FrameType,TimeInQPC,MsBetweenSimulationStart,MsBetweenPresents,MsBetweenDisplayChange,MsInPresentAPI,MsRenderPresentLatency,MsUntilDisplayed,MsPCLatency,CPUStartQPC,MsBetweenAppStart,MsCPUBusy,MsCPUWait,MsGPULatency,MsGPUTime,MsGPUBusy,MsGPUWait,MsVideoBusy,MsAnimationError,AnimationTime,MsAllInputToPhotonLatency,MsClickToPhotonLatency,MsInstrumentedLatency
-dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55437001610,NA,50.14450000000000,49.99660000000000,0.10030000000000,0.66430000000000,16.1080,NA,55436501505,50.1108,50.0105,0.1003,0.0339,50.6409,0.7695,49.8714,0.0000,0.0000,501.5764,NA,NA,NA
+Application,ProcessID,SwapChainAddress,PresentRuntime,SyncInterval,PresentFlags,AllowsTearing,PresentMode,FrameType,TimeInQPC,MsBetweenSimulationStart,MsBetweenPresents,MsBetweenDisplayChange,MsInPresentAPI,MsRenderPresentLatency,MsUntilDisplayed,MsPCLatency,CPUStartQPC,MsBetweenAppStart,MsCPUBusy,MsCPUWait,MsGPULatency,MsGPUTime,MsGPUBusy,MsGPUWait,MsVideoBusy,MsAnimationError,AnimationTime,MsAllInputToPhotonLatency,MsClickToPhotonLatency,MsInstrumentedLatency
+dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55437001610,NA,50.14450000000000,49.99660000000000,0.10030000000000,0.66430000000000,16.1080,NA,55436501505,50.1108,50.0105,0.1003,0.0339,50.6409,0.7695,49.8714,0.0000,NA,501.5764,NA,NA,NA
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55437166836,NA,16.52260000000000,16.71670000000000,0.11780000000000,0.67910000000000,16.3021,NA,55437002613,16.5401,16.4223,0.1178,0.0078,17.0936,0.6222,16.4714,0.0000,33.3941,551.6872,NA,NA,NA
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55437693123,NA,52.62870000000000,50.03070000000000,0.10770000000000,2.10770000000000,13.7041,NA,55437168014,52.6186,52.5109,0.1077,0.0404,54.5782,0.7861,53.7921,0.0000,-33.4906,568.2273,NA,NA,NA
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55437839509,NA,14.63860000000000,16.75120000000000,0.23040000000000,1.54550000000000,15.8167,NA,55437694200,14.7613,14.5309,0.2304,0.0090,16.0674,1.9944,14.0730,0.0000,35.8674,620.8459,NA,NA,NA
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55438003632,NA,16.41230000000000,16.70080000000000,0.07120000000000,1.14400000000000,16.1052,NA,55437841813,16.2531,16.1819,0.0712,0.0000,17.4374,1.4483,15.9891,0.0000,-1.9395,635.6072,NA,NA,NA
-Presenter.exe,9620,0x19E52815138,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,55437841575,NA,5.49970000000000,16.68160000000000,16.96820000000000,18.27340000000000,48.9925,NA,55437838580,17.2677,0.2995,16.9682,17.7236,0.8493,0.8493,0.0000,0.0000,0.0000,635.2839,NA,NA,NA
+Presenter.exe,9620,0x19E52815138,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,55437841575,NA,5.49970000000000,16.68160000000000,16.96820000000000,18.27340000000000,48.9925,NA,55437838580,17.2677,0.2995,16.9682,17.7236,0.8493,0.8493,0.0000,0.0000,NA,635.2839,NA,NA,NA
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55438170667,NA,16.70350000000000,16.68160000000000,0.06530000000000,1.19210000000000,16.0833,NA,55438004344,16.6976,16.6323,0.0653,0.1150,17.7094,0.9650,16.7444,0.0000,-0.4285,651.8603,NA,NA,NA
Presenter.exe,9620,0x19E52815138,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,55438011805,NA,17.02300000000000,16.68020000000000,16.53970000000000,18.08770000000000,48.6497,NA,55438011257,16.5945,0.0548,16.5397,17.2197,0.9228,0.9228,0.0000,0.0000,0.5875,652.5516,NA,NA,NA
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55438335806,NA,16.51390000000000,16.68020000000000,0.11110000000000,1.39100000000000,16.2496,NA,55438171320,16.5597,16.4486,0.1111,0.0219,17.8177,1.1749,16.6428,0.0000,0.0174,668.5579,NA,NA,NA
@@ -62,7 +62,7 @@ dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,5544852
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55448683141,NA,15.91730000000000,16.60680000000000,0.06350000000000,2.17780000000000,15.6194,NA,55448524991,15.8785,15.8150,0.0635,0.0000,18.0022,1.6131,16.3891,0.0000,18.0341,1703.9250,NA,NA,NA
Presenter.exe,8536,0x197B10BAB70,DXGI,0,0,0,Composed: Flip,Application,55448832884,NA,15.75720000000000,NA,1.56970000000000,-10.38950000000000,NA,NA,55448709072,13.9509,12.3812,1.5697,1.1699,0.8218,0.8218,0.0000,0.0000,NA,NA,NA,NA,NA
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55448870415,NA,18.72740000000000,16.70390000000000,0.11130000000000,0.42560000000000,13.5959,NA,55448683776,18.7752,18.6639,0.1113,0.0695,19.0200,2.0580,16.9620,0.0000,-0.8254,1719.8035,NA,NA,NA
-Presenter.exe,8536,0x197B10BAB70,DXGI,0,0,0,Composed: Flip,Application,55448989124,NA,15.62400000000000,16.66130000000000,0.19480000000000,-13.08290000000000,18.3863,NA,55448848581,14.2491,14.0543,0.1948,0.1171,0.8543,0.8543,0.0000,0.0000,0.0000,1736.2840,NA,NA,NA
+Presenter.exe,8536,0x197B10BAB70,DXGI,0,0,0,Composed: Flip,Application,55448989124,NA,15.62400000000000,16.66130000000000,0.19480000000000,-13.08290000000000,18.3863,NA,55448848581,14.2491,14.0543,0.1948,0.1171,0.8543,0.8543,0.0000,0.0000,NA,1736.2840,NA,NA,NA
Presenter.exe,8536,0x197B10BAB70,DXGI,0,0,0,Hardware: Independent Flip,Application,55449145292,NA,15.61680000000000,16.77070000000000,0.15680000000000,3.79860000000000,19.5402,NA,55448991072,15.5788,15.4220,0.1568,18.2978,0.9228,0.9228,0.0000,0.0000,-2.5216,1750.5331,NA,NA,NA
Presenter.exe,8536,0x197B10BAB70,DXGI,0,0,0,Hardware: Independent Flip,Application,55449302276,NA,15.69840000000000,16.68370000000000,0.29950000000000,3.79660000000000,20.5255,NA,55449146860,15.8411,15.5416,0.2995,4.4137,14.9245,0.9202,14.0043,0.0000,-1.1049,1766.1119,NA,NA,NA
Presenter.exe,8536,0x197B10BAB70,DXGI,0,0,0,Hardware: Independent Flip,Application,55449457907,NA,15.56310000000000,16.70430000000000,0.27530000000000,4.93940000000000,21.6667,NA,55449305271,15.5389,15.2636,0.2753,3.6232,16.5798,0.7561,15.8237,0.0000,-0.8632,1781.9530,NA,NA,NA
@@ -90,7 +90,7 @@ dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,5545368
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55453856415,NA,17.08340000000000,16.67880000000000,0.15250000000000,2.71800000000000,15.4116,NA,55453687026,17.0914,16.9389,0.1525,0.0167,19.6402,2.8172,16.8230,0.0000,33.7876,2220.1285,NA,NA,NA
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55454017095,NA,16.06800000000000,16.66520000000000,0.10630000000000,1.91440000000000,16.0088,NA,55453857940,16.0218,15.9155,0.1063,0.0000,17.8749,2.6085,15.2664,0.0000,0.4262,2237.2199,NA,NA,NA
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55454220315,NA,20.32200000000000,16.67040000000000,0.07480000000000,0.45110000000000,12.3572,NA,55454018158,20.2905,20.2157,0.0748,0.0000,20.6730,1.8226,18.8504,0.0000,-0.6486,2253.2417,NA,NA,NA
-Presenter.exe,5236,0x285B4C0D1B0,DXGI,0,0,0,Composed: Flip,Application,55454299820,NA,15.65140000000000,18.03750000000000,2.45370000000000,-11.33040000000000,22.4442,NA,55454168764,15.5593,13.1056,2.4537,0.8807,0.8945,0.8945,0.0000,0.0000,0.0000,2268.3023,NA,NA,NA
+Presenter.exe,5236,0x285B4C0D1B0,DXGI,0,0,0,Composed: Flip,Application,55454299820,NA,15.65140000000000,18.03750000000000,2.45370000000000,-11.33040000000000,22.4442,NA,55454168764,15.5593,13.1056,2.4537,0.8807,0.8945,0.8945,0.0000,0.0000,NA,2268.3023,NA,NA,NA
Presenter.exe,5236,0x285B4C0D1B0,DXGI,0,0,1,Hardware: Independent Flip,Application,55454457377,NA,15.75570000000000,NA,0.24110000000000,5.50070000000000,5.5007,NA,55454324357,13.5431,13.3020,0.2411,0.1296,18.6731,0.9864,17.6867,0.0000,-1844674407370938.5000,2283.8616,NA,NA,NA
Presenter.exe,5236,0x285B4C0D1B0,DXGI,0,0,1,Hardware: Independent Flip,Application,55454612236,NA,15.48590000000000,10.29460000000000,0.30560000000000,-7.97160000000000,0.3094,NA,55454459788,15.5504,15.2448,0.3056,6.5527,0.7205,0.7205,0.0000,0.0000,3.2485,2297.4047,NA,NA,NA
Presenter.exe,5236,0x285B4C0D1B0,DXGI,0,0,1,Hardware: Independent Flip,Application,55454769193,NA,15.69570000000000,15.62230000000000,0.20100000000000,-13.73470000000000,0.2360,NA,55454615292,15.5911,15.3901,0.2010,0.8622,0.7932,0.7932,0.0000,0.0000,-0.0719,2312.9551,NA,NA,NA
@@ -135,7 +135,7 @@ dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,5546352
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55463692378,NA,16.77020000000000,16.69050000000000,0.06330000000000,1.71370000000000,16.0261,NA,55463525474,16.7537,16.6904,0.0633,0.0028,18.4013,1.6356,16.7657,0.0000,-0.0308,3203.9733,NA,NA,NA
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55463860907,NA,16.85290000000000,16.68210000000000,0.06380000000000,1.95130000000000,15.8553,NA,55463693011,16.8534,16.7896,0.0638,0.0216,18.7193,1.6371,17.0822,0.0000,0.0716,3220.7270,NA,NA,NA
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55464025851,NA,16.49440000000000,16.69120000000000,0.08790000000000,3.02170000000000,16.0521,NA,55463861545,16.5185,16.4306,0.0879,0.0257,19.4266,1.8746,17.5520,0.0000,0.1622,3237.5804,NA,NA,NA
-Presenter.exe,5192,0x0,Other,-1,0,0,Composed: Copy with GPU GDI,Application,55464040731,NA,29.01960000000000,33.32130000000000,0.00000000000000,2.39770000000000,31.1942,NA,55463750535,29.0196,29.0196,0.0000,13.7598,17.6575,1.1375,16.5200,0.0000,0.0000,3226.4794,NA,NA,NA
+Presenter.exe,5192,0x0,Other,-1,0,0,Composed: Copy with GPU GDI,Application,55464040731,NA,29.01960000000000,33.32130000000000,0.00000000000000,2.39770000000000,31.1942,NA,55463750535,29.0196,29.0196,0.0000,13.7598,17.6575,1.1375,16.5200,0.0000,NA,3226.4794,NA,NA,NA
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55464200956,NA,17.51050000000000,16.63010000000000,0.13940000000000,3.46860000000000,15.1717,NA,55464026730,17.5620,17.4226,0.1394,0.0132,20.8780,2.9338,17.9442,0.0000,-0.1116,3254.0989,NA,NA,NA
Presenter.exe,5192,0x0,Other,-1,0,0,Composed: Copy with GPU GDI,Application,55464233068,NA,19.23370000000000,16.69380000000000,0.00000000000000,0.75290000000000,28.6543,NA,55464040731,19.2337,19.2337,0.0000,15.4732,4.5134,0.9042,3.6092,0.0000,12.3258,3255.4990,NA,NA,NA
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55464362303,NA,16.13470000000000,16.69380000000000,0.11610000000000,3.02440000000000,15.7308,NA,55464202350,16.1114,15.9953,0.1161,0.0000,19.0199,3.3394,15.6805,0.0000,0.8682,3271.6609,NA,NA,NA
diff --git a/Tests/Gold/test_case_4_v2.csv b/Tests/Gold/test_case_4_v2.csv
index db373bcb..3d851aac 100644
--- a/Tests/Gold/test_case_4_v2.csv
+++ b/Tests/Gold/test_case_4_v2.csv
@@ -1,10 +1,10 @@
Application,ProcessID,SwapChainAddress,PresentRuntime,SyncInterval,PresentFlags,AllowsTearing,PresentMode,FrameType,CPUStartQPC,FrameTime,CPUBusy,CPUWait,GPULatency,GPUTime,GPUBusy,GPUWait,VideoBusy,DisplayLatency,DisplayedTime,AnimationError,AnimationTime,AllInputToPhotonLatency,ClickToPhotonLatency,InstrumentedLatency
-dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55436501505,50.1108,50.0105,0.1003,0.0339,50.6409,0.7695,49.8714,0.0000,66.1185,16.7167,0.0000,501.5764,NA,NA,NA
+dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55436501505,50.1108,50.0105,0.1003,0.0339,50.6409,0.7695,49.8714,0.0000,66.1185,16.7167,NA,501.5764,NA,NA,NA
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55437002613,16.5401,16.4223,0.1178,0.0078,17.0936,0.6222,16.4714,0.0000,32.7244,50.0307,33.3941,551.6872,NA,NA,NA
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55437168014,52.6186,52.5109,0.1077,0.0404,54.5782,0.7861,53.7921,0.0000,66.2150,16.7512,-33.4906,568.2273,NA,NA,NA
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55437694200,14.7613,14.5309,0.2304,0.0090,16.0674,1.9944,14.0730,0.0000,30.3476,16.7008,35.8674,620.8459,NA,NA,NA
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55437841813,16.2531,16.1819,0.0712,0.0000,17.4374,1.4483,15.9891,0.0000,32.2871,16.6816,-1.9395,635.6072,NA,NA,NA
-Presenter.exe,9620,0x19E52815138,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,55437838580,17.2677,0.2995,16.9682,17.7236,0.8493,0.8493,0.0000,0.0000,49.2920,16.6802,0.0000,635.2839,NA,NA,NA
+Presenter.exe,9620,0x19E52815138,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,55437838580,17.2677,0.2995,16.9682,17.7236,0.8493,0.8493,0.0000,0.0000,49.2920,16.6802,NA,635.2839,NA,NA,NA
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55438004344,16.6976,16.6323,0.0653,0.1150,17.7094,0.9650,16.7444,0.0000,32.7156,16.6802,-0.4285,651.8603,NA,NA,NA
Presenter.exe,9620,0x19E52815138,D3D9,-1,0,0,Composed: Copy with GPU GDI,Application,55438011257,16.5945,0.0548,16.5397,17.2197,0.9228,0.9228,0.0000,0.0000,48.7045,16.6784,0.5875,652.5516,NA,NA,NA
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55438171320,16.5597,16.4486,0.1111,0.0219,17.8177,1.1749,16.6428,0.0000,32.6982,16.6784,0.0174,668.5579,NA,NA,NA
@@ -62,7 +62,7 @@ dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,5544817
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55448524991,15.8785,15.8150,0.0635,0.0000,18.0022,1.6131,16.3891,0.0000,31.4344,16.7039,18.0341,1703.9250,NA,NA,NA
Presenter.exe,8536,0x197B10BAB70,DXGI,0,0,0,Composed: Flip,Application,55448709072,13.9509,12.3812,1.5697,1.1699,0.8218,0.8218,0.0000,0.0000,NA,NA,NA,NA,NA,NA,NA
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55448683776,18.7752,18.6639,0.1113,0.0695,19.0200,2.0580,16.9620,0.0000,32.2598,16.6613,-0.8254,1719.8035,NA,NA,NA
-Presenter.exe,8536,0x197B10BAB70,DXGI,0,0,0,Composed: Flip,Application,55448848581,14.2491,14.0543,0.1948,0.1171,0.8543,0.8543,0.0000,0.0000,32.4406,16.7707,0.0000,1736.2840,NA,NA,NA
+Presenter.exe,8536,0x197B10BAB70,DXGI,0,0,0,Composed: Flip,Application,55448848581,14.2491,14.0543,0.1948,0.1171,0.8543,0.8543,0.0000,0.0000,32.4406,16.7707,NA,1736.2840,NA,NA,NA
Presenter.exe,8536,0x197B10BAB70,DXGI,0,0,0,Hardware: Independent Flip,Application,55448991072,15.5788,15.4220,0.1568,18.2978,0.9228,0.9228,0.0000,0.0000,34.9622,16.6837,-2.5216,1750.5331,NA,NA,NA
Presenter.exe,8536,0x197B10BAB70,DXGI,0,0,0,Hardware: Independent Flip,Application,55449146860,15.8411,15.5416,0.2995,4.4137,14.9245,0.9202,14.0043,0.0000,36.0671,16.7043,-1.1049,1766.1119,NA,NA,NA
Presenter.exe,8536,0x197B10BAB70,DXGI,0,0,0,Hardware: Independent Flip,Application,55449305271,15.5389,15.2636,0.2753,3.6232,16.5798,0.7561,15.8237,0.0000,36.9303,16.6633,-0.8632,1781.9530,NA,NA,NA
@@ -90,7 +90,7 @@ dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,5545318
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55453687026,17.0914,16.9389,0.1525,0.0167,19.6402,2.8172,16.8230,0.0000,32.3505,16.6652,33.7876,2220.1285,NA,NA,NA
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55453857940,16.0218,15.9155,0.1063,0.0000,17.8749,2.6085,15.2664,0.0000,31.9243,16.6704,0.4262,2237.2199,NA,NA,NA
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55454018158,20.2905,20.2157,0.0748,0.0000,20.6730,1.8226,18.8504,0.0000,32.5729,18.0375,-0.6486,2253.2417,NA,NA,NA
-Presenter.exe,5236,0x285B4C0D1B0,DXGI,0,0,0,Composed: Flip,Application,55454168764,15.5593,13.1056,2.4537,0.8807,0.8945,0.8945,0.0000,0.0000,NA,NA,0.0000,2268.3023,NA,NA,NA
+Presenter.exe,5236,0x285B4C0D1B0,DXGI,0,0,0,Composed: Flip,Application,55454168764,15.5593,13.1056,2.4537,0.8807,0.8945,0.8945,0.0000,0.0000,NA,NA,NA,2268.3023,NA,NA,NA
Presenter.exe,5236,0x285B4C0D1B0,DXGI,0,0,1,Hardware: Independent Flip,Application,55454324357,13.5431,13.3020,0.2411,0.1296,18.6731,0.9864,17.6867,0.0000,18.8027,10.2946,-1844674407370938.5000,2283.8616,NA,NA,NA
Presenter.exe,5236,0x285B4C0D1B0,DXGI,0,0,1,Hardware: Independent Flip,Application,55454459788,15.5504,15.2448,0.3056,6.5527,0.7205,0.7205,0.0000,0.0000,15.5542,15.6223,3.2485,2297.4047,NA,NA,NA
Presenter.exe,5236,0x285B4C0D1B0,DXGI,0,0,1,Hardware: Independent Flip,Application,55454615292,15.5911,15.3901,0.2010,0.8622,0.7932,0.7932,0.0000,0.0000,15.6261,15.8218,-0.0719,2312.9551,NA,NA,NA
@@ -135,7 +135,7 @@ dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,5546335
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55463525474,16.7537,16.6904,0.0633,0.0028,18.4013,1.6356,16.7657,0.0000,32.7165,16.6821,-0.0308,3203.9733,NA,NA,NA
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55463693011,16.8534,16.7896,0.0638,0.0216,18.7193,1.6371,17.0822,0.0000,32.6449,16.6912,0.0716,3220.7270,NA,NA,NA
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55463861545,16.5185,16.4306,0.0879,0.0257,19.4266,1.8746,17.5520,0.0000,32.4827,16.6301,0.1622,3237.5804,NA,NA,NA
-Presenter.exe,5192,0x0,Other,-1,0,0,Composed: Copy with GPU GDI,Application,55463750535,29.0196,29.0196,0.0000,13.7598,17.6575,1.1375,16.5200,0.0000,60.2138,16.6938,0.0000,3226.4794,NA,NA,NA
+Presenter.exe,5192,0x0,Other,-1,0,0,Composed: Copy with GPU GDI,Application,55463750535,29.0196,29.0196,0.0000,13.7598,17.6575,1.1375,16.5200,0.0000,60.2138,16.6938,NA,3226.4794,NA,NA,NA
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55464026730,17.5620,17.4226,0.1394,0.0132,20.8780,2.9338,17.9442,0.0000,32.5943,16.6938,-0.1116,3254.0989,NA,NA,NA
Presenter.exe,5192,0x0,Other,-1,0,0,Composed: Copy with GPU GDI,Application,55464040731,19.2337,19.2337,0.0000,15.4732,4.5134,0.9042,3.6092,0.0000,47.8880,16.6218,12.3258,3255.4990,NA,NA,NA
dwm.exe,10376,0x1BF098B1ED0,DXGI,1,0,0,Hardware: Legacy Flip,Application,55464202350,16.1114,15.9953,0.1161,0.0000,19.0199,3.3394,15.6805,0.0000,31.7261,16.6218,0.8682,3271.6609,NA,NA,NA
diff --git a/Tests/Gold/test_case_5.csv b/Tests/Gold/test_case_5.csv
index 37dad6a2..34582bcf 100644
--- a/Tests/Gold/test_case_5.csv
+++ b/Tests/Gold/test_case_5.csv
@@ -1,9 +1,9 @@
-Application,ProcessID,SwapChainAddress,PresentRuntime,SyncInterval,PresentFlags,AllowsTearing,PresentMode,FrameType,TimeInQPC,MsBetweenSimulationStart,MsBetweenPresents,MsBetweenDisplayChange,MsInPresentAPI,MsRenderPresentLatency,MsUntilDisplayed,MsPCLatency,CPUStartQPC,MsBetweenAppStart,MsCPUBusy,MsCPUWait,MsGPULatency,MsGPUTime,MsGPUBusy,MsGPUWait,MsVideoBusy,MsAnimationError,AnimationTime,MsAllInputToPhotonLatency,MsClickToPhotonLatency,MsInstrumentedLatency
-dwm.exe,2656,0x19D7EF5E390,DXGI,1,0,0,Hardware: Legacy Flip,Application,2466961604351,NA,17.59230000000000,16.59930000000000,0.37230000000000,0.32520000000000,14.1630,NA,2466961432001,17.6073,17.2350,0.3723,17.0327,0.5275,0.5275,0.0000,0.0000,0.0000,1939.5329,NA,NA,NA
+Application,ProcessID,SwapChainAddress,PresentRuntime,SyncInterval,PresentFlags,AllowsTearing,PresentMode,FrameType,TimeInQPC,MsBetweenSimulationStart,MsBetweenPresents,MsBetweenDisplayChange,MsInPresentAPI,MsRenderPresentLatency,MsUntilDisplayed,MsPCLatency,CPUStartQPC,MsBetweenAppStart,MsCPUBusy,MsCPUWait,MsGPULatency,MsGPUTime,MsGPUBusy,MsGPUWait,MsVideoBusy,MsAnimationError,AnimationTime,MsAllInputToPhotonLatency,MsClickToPhotonLatency,MsInstrumentedLatency
+dwm.exe,2656,0x19D7EF5E390,DXGI,1,0,0,Hardware: Legacy Flip,Application,2466961604351,NA,17.59230000000000,16.59930000000000,0.37230000000000,0.32520000000000,14.1630,NA,2466961432001,17.6073,17.2350,0.3723,17.0327,0.5275,0.5275,0.0000,0.0000,NA,1939.5329,NA,NA,NA
PresentBench.exe,24892,0x2A70D2CAC00,DXGI,0,0,0,Composed: Flip,Application,2466961626795,NA,11.06220000000000,NA,0.52690000000000,0.78810000000000,NA,NA,2466961521260,11.0804,10.5535,0.5269,1.1731,10.1685,1.5667,8.6018,0.0000,NA,NA,NA,NA,NA
-dwm.exe,2656,0x19D7F1BA8F0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2466961596409,NA,17.32320000000000,16.59680000000000,0.75120000000000,0.59190000000000,14.9755,NA,2466961428054,17.5867,16.8355,0.7512,0.3386,17.0888,0.6061,16.4827,0.0000,0.0000,1939.1382,NA,NA,NA
+dwm.exe,2656,0x19D7F1BA8F0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2466961596409,NA,17.32320000000000,16.59680000000000,0.75120000000000,0.59190000000000,14.9755,NA,2466961428054,17.5867,16.8355,0.7512,0.3386,17.0888,0.6061,16.4827,0.0000,NA,1939.1382,NA,NA,NA
dwm.exe,2656,0x19D7EF5E390,DXGI,1,0,0,Hardware: Legacy Flip,Application,2466961769023,NA,16.46720000000000,16.75860000000000,0.47210000000000,0.37150000000000,14.4544,NA,2466961608074,16.5670,16.0949,0.4721,15.8758,0.5906,0.5906,0.0000,0.0000,0.8487,1957.1402,NA,NA,NA
-PresentBench.exe,24892,0x2A70D2CAC00,DXGI,0,0,0,Composed: Flip,Application,2466961736878,NA,11.00830000000000,16.76180000000000,0.56230000000000,0.69260000000000,17.6904,NA,2466961632064,11.0437,10.4814,0.5623,0.2612,10.9128,0.5496,10.3632,0.0000,0.0000,1959.5392,NA,NA,NA
+PresentBench.exe,24892,0x2A70D2CAC00,DXGI,0,0,0,Composed: Flip,Application,2466961736878,NA,11.00830000000000,16.76180000000000,0.56230000000000,0.69260000000000,17.6904,NA,2466961632064,11.0437,10.4814,0.5623,0.2612,10.9128,0.5496,10.3632,0.0000,NA,1959.5392,NA,NA,NA
dwm.exe,2656,0x19D7F1BA8F0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2466961762174,NA,16.57650000000000,16.76180000000000,0.61900000000000,0.46580000000000,15.1608,NA,2466961603921,16.4443,15.8253,0.6190,0.3682,15.9229,1.5724,14.3505,0.0000,0.8249,1956.7249,NA,NA,NA
dwm.exe,2656,0x19D7EF5E390,DXGI,1,0,0,Hardware: Legacy Flip,Application,2466961930951,NA,16.19280000000000,16.62660000000000,0.44410000000000,0.33800000000000,14.8882,NA,2466961773744,16.1648,15.7207,0.4441,15.5395,0.5192,0.5192,0.0000,0.0000,-0.0596,1973.7072,NA,NA,NA
PresentBench.exe,24892,0x2A70D2CAC00,DXGI,0,0,0,Composed: Flip,Application,2466961846796,NA,10.99180000000000,16.62670000000000,0.54730000000000,0.86620000000000,23.3253,NA,2466961742501,10.9768,10.4295,0.5473,0.1897,11.1060,0.8736,10.2324,0.0000,-5.5830,1970.5829,NA,NA,NA
@@ -164,7 +164,7 @@ dwm.exe,2656,0x19D7F1BA8F0,DXGI,1,2,0,Hardware: Legacy Flip,Application,24669692
dwm.exe,2656,0x19D7EF5E390,DXGI,1,0,0,Hardware: Legacy Flip,Application,2466969432991,NA,16.54080000000000,16.61390000000000,0.55540000000000,0.48880000000000,14.6451,NA,2466969271948,16.6597,16.1043,0.5554,15.9365,0.6566,0.6566,0.0000,0.0000,0.2804,2723.5276,NA,NA,NA
PresentBench.exe,24892,0x2A70D2CAC00,DXGI,0,0,0,Composed: Flip,Application,2466969342791,NA,10.99490000000000,16.61310000000000,0.62410000000000,1.00210000000000,23.6756,NA,2466969239022,11.0010,10.3769,0.6241,0.3860,10.9930,0.7641,10.2289,0.0000,-4.5987,2720.2350,NA,NA,NA
PresentBench.exe,24892,0x2A70D2CAC00,DXGI,0,0,0,Composed: Flip,Application,2466969453335,NA,11.05440000000000,NA,0.57480000000000,0.86270000000000,NA,NA,2466969349032,11.0051,10.4303,0.5748,0.3780,10.9150,0.6826,10.2324,0.0000,NA,NA,NA,NA,NA
-steamwebhelper.exe,3980,0x21C48E8A710,DXGI,1,0,0,Composed: Flip,Application,2466969280539,NA,12.76920000000000,16.61310000000000,0.21300000000000,1.51910000000000,29.9008,NA,2466969154898,12.7771,12.5641,0.2130,12.8255,1.2577,1.2493,0.0084,0.0000,0.0000,2711.8226,NA,NA,NA
+steamwebhelper.exe,3980,0x21C48E8A710,DXGI,1,0,0,Composed: Flip,Application,2466969280539,NA,12.76920000000000,16.61310000000000,0.21300000000000,1.51910000000000,29.9008,NA,2466969154898,12.7771,12.5641,0.2130,12.8255,1.2577,1.2493,0.0084,0.0000,NA,2711.8226,NA,NA,NA
dwm.exe,2656,0x19D7F1BA8F0,DXGI,1,2,0,Hardware: Legacy Flip,Application,2466969426606,NA,16.63230000000000,16.61310000000000,0.58830000000000,0.47070000000000,15.2941,NA,2466969267137,16.5352,15.9469,0.5883,0.4137,16.0039,0.5486,15.4553,0.0000,0.3147,2723.0465,NA,NA,NA
dwm.exe,2656,0x19D7EF5E390,DXGI,1,0,0,Hardware: Legacy Flip,Application,2466969600203,NA,16.72120000000000,16.70190000000000,0.86530000000000,0.79710000000000,14.6258,NA,2466969438545,17.0311,16.1658,0.8653,15.9792,0.9837,0.8327,0.1510,0.0000,-0.0422,2740.1873,NA,NA,NA
PresentBench.exe,24892,0x2A70D2CAC00,DXGI,0,0,0,Composed: Flip,Application,2466969564450,NA,11.11150000000000,16.70250000000000,0.55530000000000,0.71380000000000,18.2122,NA,2466969459083,11.0920,10.5367,0.5553,0.2879,10.9626,0.6811,10.2815,0.0000,5.3036,2742.2411,NA,NA,NA
@@ -629,9 +629,9 @@ PresentBench.exe,24892,0x2A70D2CAC00,DXGI,0,0,0,Composed: Flip,Application,24669
PresentBench.exe,24892,0x2A70D2CAC00,DXGI,0,0,0,Composed: Flip,Application,2466990431593,NA,10.91660000000000,NA,0.52900000000000,0.97950000000000,NA,NA,2466990327593,10.9290,10.4000,0.5290,0.4415,10.9380,0.7138,10.2242,0.0000,NA,NA,NA,NA,NA
dwm.exe,2656,0x19D7F1BA8F0,DXGI,1,2,0,Hardware: Legacy Flip,Application,2466990425728,NA,16.70070000000000,16.68000000000000,0.54290000000000,0.40330000000000,15.5041,NA,2466990264244,16.6913,16.1484,0.5429,0.3428,16.2089,0.5687,15.6402,0.0000,-0.0397,4822.7572,NA,NA,NA
PresentBench.exe,24892,0x2A70D2CAC00,DXGI,0,0,0,Composed: Flip,Application,2466990542147,NA,11.05540000000000,16.60270000000000,0.50170000000000,0.61330000000000,20.4649,NA,2466990436883,11.0281,10.5264,0.5017,0.4505,10.6892,0.6655,10.0237,0.0000,5.3560,4840.0211,NA,NA,NA
-dwm.exe,2656,0x0,Other,-1,0,0,Hardware: Legacy Flip,Application,2466990934481,NA,16.79000000000000,16.65060000000000,0.00000000000000,0.03110000000000,14.5956,NA,2466990766581,16.7900,16.7900,0.0000,16.2638,0.5573,0.5573,0.0000,0.0000,0.0000,4872.9909,NA,NA,NA
-PresentBench.exe,24892,0x0,Other,-1,0,0,Composed: Flip,Application,2466990877183,NA,11.17160000000000,NA,0.00000000000000,0.19210000000000,20.3352,NA,2466990765467,11.1716,11.1716,0.0000,0.6719,10.6918,0.9088,9.7830,0.0000,0.0000,4872.8795,NA,NA,NA
-dwm.exe,2656,0x100000000,Other,-1,0,0,Hardware: Legacy Flip,Application,2466990928880,NA,16.67440000000000,16.64970000000000,0.00000000000000,0.03390000000000,15.1655,NA,2466990762136,16.6744,16.6744,0.0000,0.4752,16.2331,1.1912,15.0419,0.0000,0.0000,4872.5464,NA,NA,NA
+dwm.exe,2656,0x0,Other,-1,0,0,Hardware: Legacy Flip,Application,2466990934481,NA,16.79000000000000,16.65060000000000,0.00000000000000,0.03110000000000,14.5956,NA,2466990766581,16.7900,16.7900,0.0000,16.2638,0.5573,0.5573,0.0000,0.0000,NA,4872.9909,NA,NA,NA
+PresentBench.exe,24892,0x0,Other,-1,0,0,Composed: Flip,Application,2466990877183,NA,11.17160000000000,NA,0.00000000000000,0.19210000000000,20.3352,NA,2466990765467,11.1716,11.1716,0.0000,0.6719,10.6918,0.9088,9.7830,0.0000,NA,4872.8795,NA,NA,NA
+dwm.exe,2656,0x100000000,Other,-1,0,0,Hardware: Legacy Flip,Application,2466990928880,NA,16.67440000000000,16.64970000000000,0.00000000000000,0.03390000000000,15.1655,NA,2466990762136,16.6744,16.6744,0.0000,0.4752,16.2331,1.1912,15.0419,0.0000,NA,4872.5464,NA,NA,NA
dwm.exe,2656,0x0,Other,-1,0,0,Hardware: Legacy Flip,Application,2466991097588,NA,16.31070000000000,16.66170000000000,0.00000000000000,0.02920000000000,14.9466,NA,2466990934481,16.3107,16.3107,0.0000,15.9599,0.3800,0.3800,0.0000,0.0000,0.1283,4889.7809,NA,NA,NA
PresentBench.exe,24892,0x0,Other,-1,0,0,Composed: Flip,Application,2466990985962,NA,10.87790000000000,16.66200000000000,0.00000000000000,0.43810000000000,26.1193,NA,2466990877183,10.8779,10.8779,0.0000,0.2428,11.0732,1.0574,10.0158,0.0000,-5.4904,4884.0511,NA,NA,NA
PresentBench.exe,24892,0x0,Other,-1,0,0,Composed: Flip,Application,2466991094843,NA,10.88810000000000,NA,0.00000000000000,1.23830000000000,NA,NA,2466990985962,10.8881,10.8881,0.0000,0.4381,11.6883,1.4385,10.2498,0.0000,NA,NA,NA,NA,NA
diff --git a/Tests/Gold/test_case_5_v2.csv b/Tests/Gold/test_case_5_v2.csv
index 96cdcda9..67d57dcd 100644
--- a/Tests/Gold/test_case_5_v2.csv
+++ b/Tests/Gold/test_case_5_v2.csv
@@ -1,9 +1,9 @@
Application,ProcessID,SwapChainAddress,PresentRuntime,SyncInterval,PresentFlags,AllowsTearing,PresentMode,FrameType,CPUStartQPC,FrameTime,CPUBusy,CPUWait,GPULatency,GPUTime,GPUBusy,GPUWait,VideoBusy,DisplayLatency,DisplayedTime,AnimationError,AnimationTime,AllInputToPhotonLatency,ClickToPhotonLatency,InstrumentedLatency
-dwm.exe,2656,0x19D7EF5E390,DXGI,1,0,0,Hardware: Legacy Flip,Application,2466961432001,17.6073,17.2350,0.3723,17.0327,0.5275,0.5275,0.0000,0.0000,31.3980,16.7586,0.0000,1939.5329,NA,NA,NA
+dwm.exe,2656,0x19D7EF5E390,DXGI,1,0,0,Hardware: Legacy Flip,Application,2466961432001,17.6073,17.2350,0.3723,17.0327,0.5275,0.5275,0.0000,0.0000,31.3980,16.7586,NA,1939.5329,NA,NA,NA
PresentBench.exe,24892,0x2A70D2CAC00,DXGI,0,0,0,Composed: Flip,Application,2466961521260,11.0804,10.5535,0.5269,1.1731,10.1685,1.5667,8.6018,0.0000,NA,NA,NA,NA,NA,NA,NA
-dwm.exe,2656,0x19D7F1BA8F0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2466961428054,17.5867,16.8355,0.7512,0.3386,17.0888,0.6061,16.4827,0.0000,31.8110,16.7618,0.0000,1939.1382,NA,NA,NA
+dwm.exe,2656,0x19D7F1BA8F0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2466961428054,17.5867,16.8355,0.7512,0.3386,17.0888,0.6061,16.4827,0.0000,31.8110,16.7618,NA,1939.1382,NA,NA,NA
dwm.exe,2656,0x19D7EF5E390,DXGI,1,0,0,Hardware: Legacy Flip,Application,2466961608074,16.5670,16.0949,0.4721,15.8758,0.5906,0.5906,0.0000,0.0000,30.5493,16.6266,0.8487,1957.1402,NA,NA,NA
-PresentBench.exe,24892,0x2A70D2CAC00,DXGI,0,0,0,Composed: Flip,Application,2466961632064,11.0437,10.4814,0.5623,0.2612,10.9128,0.5496,10.3632,0.0000,28.1718,16.6267,0.0000,1959.5392,NA,NA,NA
+PresentBench.exe,24892,0x2A70D2CAC00,DXGI,0,0,0,Composed: Flip,Application,2466961632064,11.0437,10.4814,0.5623,0.2612,10.9128,0.5496,10.3632,0.0000,28.1718,16.6267,NA,1959.5392,NA,NA,NA
dwm.exe,2656,0x19D7F1BA8F0,DXGI,1,0,0,Hardware: Legacy Flip,Application,2466961603921,16.4443,15.8253,0.6190,0.3682,15.9229,1.5724,14.3505,0.0000,30.9861,16.6267,0.8249,1956.7249,NA,NA,NA
dwm.exe,2656,0x19D7EF5E390,DXGI,1,0,0,Hardware: Legacy Flip,Application,2466961773744,16.1648,15.7207,0.4441,15.5395,0.5192,0.5192,0.0000,0.0000,30.6089,16.7140,-0.0596,1973.7072,NA,NA,NA
PresentBench.exe,24892,0x2A70D2CAC00,DXGI,0,0,0,Composed: Flip,Application,2466961742501,10.9768,10.4295,0.5473,0.1897,11.1060,0.8736,10.2324,0.0000,33.7548,16.7167,-5.5830,1970.5829,NA,NA,NA
@@ -164,7 +164,7 @@ dwm.exe,2656,0x19D7F1BA8F0,DXGI,1,2,0,Hardware: Legacy Flip,Application,24669690
dwm.exe,2656,0x19D7EF5E390,DXGI,1,0,0,Hardware: Legacy Flip,Application,2466969271948,16.6597,16.1043,0.5554,15.9365,0.6566,0.6566,0.0000,0.0000,30.7494,16.7019,0.2804,2723.5276,NA,NA,NA
PresentBench.exe,24892,0x2A70D2CAC00,DXGI,0,0,0,Composed: Flip,Application,2466969239022,11.0010,10.3769,0.6241,0.3860,10.9930,0.7641,10.2289,0.0000,34.0525,16.7025,-4.5987,2720.2350,NA,NA,NA
PresentBench.exe,24892,0x2A70D2CAC00,DXGI,0,0,0,Composed: Flip,Application,2466969349032,11.0051,10.4303,0.5748,0.3780,10.9150,0.6826,10.2324,0.0000,NA,NA,NA,NA,NA,NA,NA
-steamwebhelper.exe,3980,0x21C48E8A710,DXGI,1,0,0,Composed: Flip,Application,2466969154898,12.7771,12.5641,0.2130,12.8255,1.2577,1.2493,0.0084,0.0000,42.4649,16.7025,0.0000,2711.8226,NA,NA,NA
+steamwebhelper.exe,3980,0x21C48E8A710,DXGI,1,0,0,Composed: Flip,Application,2466969154898,12.7771,12.5641,0.2130,12.8255,1.2577,1.2493,0.0084,0.0000,42.4649,16.7025,NA,2711.8226,NA,NA,NA
dwm.exe,2656,0x19D7F1BA8F0,DXGI,1,2,0,Hardware: Legacy Flip,Application,2466969267137,16.5352,15.9469,0.5883,0.4137,16.0039,0.5486,15.4553,0.0000,31.2410,16.7025,0.3147,2723.0465,NA,NA,NA
dwm.exe,2656,0x19D7EF5E390,DXGI,1,0,0,Hardware: Legacy Flip,Application,2466969438545,17.0311,16.1658,0.8653,15.9792,0.9837,0.8327,0.1510,0.0000,30.7916,16.7498,-0.0422,2740.1873,NA,NA,NA
PresentBench.exe,24892,0x2A70D2CAC00,DXGI,0,0,0,Composed: Flip,Application,2466969459083,11.0920,10.5367,0.5553,0.2879,10.9626,0.6811,10.2815,0.0000,28.7489,16.7503,5.3036,2742.2411,NA,NA,NA
@@ -629,9 +629,9 @@ PresentBench.exe,24892,0x2A70D2CAC00,DXGI,0,0,0,Composed: Flip,Application,24669
PresentBench.exe,24892,0x2A70D2CAC00,DXGI,0,0,0,Composed: Flip,Application,2466990327593,10.9290,10.4000,0.5290,0.4415,10.9380,0.7138,10.2242,0.0000,NA,NA,NA,NA,NA,NA,NA
dwm.exe,2656,0x19D7F1BA8F0,DXGI,1,2,0,Hardware: Legacy Flip,Application,2466990264244,16.6913,16.1484,0.5429,0.3428,16.2089,0.5687,15.6402,0.0000,31.6525,16.6027,-0.0397,4822.7572,NA,NA,NA
PresentBench.exe,24892,0x2A70D2CAC00,DXGI,0,0,0,Composed: Flip,Application,2466990436883,11.0281,10.5264,0.5017,0.4505,10.6892,0.6655,10.0237,0.0000,30.9913,16.7242,5.3560,4840.0211,NA,NA,NA
-dwm.exe,2656,0x0,Other,-1,0,0,Hardware: Legacy Flip,Application,2466990766581,16.7900,16.7900,0.0000,16.2638,0.5573,0.5573,0.0000,0.0000,31.3856,16.6617,0.0000,4872.9909,NA,NA,NA
-PresentBench.exe,24892,0x0,Other,-1,0,0,Composed: Flip,Application,2466990765467,11.1716,11.1716,0.0000,0.6719,10.6918,0.9088,9.7830,0.0000,31.5068,16.6620,0.0000,4872.8795,NA,NA,NA
-dwm.exe,2656,0x100000000,Other,-1,0,0,Hardware: Legacy Flip,Application,2466990762136,16.6744,16.6744,0.0000,0.4752,16.2331,1.1912,15.0419,0.0000,31.8399,16.6620,0.0000,4872.5464,NA,NA,NA
+dwm.exe,2656,0x0,Other,-1,0,0,Hardware: Legacy Flip,Application,2466990766581,16.7900,16.7900,0.0000,16.2638,0.5573,0.5573,0.0000,0.0000,31.3856,16.6617,NA,4872.9909,NA,NA,NA
+PresentBench.exe,24892,0x0,Other,-1,0,0,Composed: Flip,Application,2466990765467,11.1716,11.1716,0.0000,0.6719,10.6918,0.9088,9.7830,0.0000,31.5068,16.6620,NA,4872.8795,NA,NA,NA
+dwm.exe,2656,0x100000000,Other,-1,0,0,Hardware: Legacy Flip,Application,2466990762136,16.6744,16.6744,0.0000,0.4752,16.2331,1.1912,15.0419,0.0000,31.8399,16.6620,NA,4872.5464,NA,NA,NA
dwm.exe,2656,0x0,Other,-1,0,0,Hardware: Legacy Flip,Application,2466990934481,16.3107,16.3107,0.0000,15.9599,0.3800,0.3800,0.0000,0.0000,31.2573,16.6960,0.1283,4889.7809,NA,NA,NA
PresentBench.exe,24892,0x0,Other,-1,0,0,Composed: Flip,Application,2466990877183,10.8779,10.8779,0.0000,0.2428,11.0732,1.0574,10.0158,0.0000,36.9972,16.6957,-5.4904,4884.0511,NA,NA,NA
PresentBench.exe,24892,0x0,Other,-1,0,0,Composed: Flip,Application,2466990985962,10.8881,10.8881,0.0000,0.4381,11.6883,1.4385,10.2498,0.0000,NA,NA,NA,NA,NA,NA,NA
diff --git a/Tests/PresentMon.cpp b/Tests/PresentMon.cpp
index ce30ff5b..66266519 100644
--- a/Tests/PresentMon.cpp
+++ b/Tests/PresentMon.cpp
@@ -261,6 +261,7 @@ bool PresentMonCsv::Open(char const* file, int line, std::wstring const& path)
Header_MsAllInputToPhotonLatency });
auto track_frame_type = CheckAllIfAny(headerColumnIndex_, &columnsOK, { Header_FrameType });
auto track_app_timing = CheckAllIfAny(headerColumnIndex_, &columnsOK, { Header_MsInstrumentedLatency});
+ auto track_pc_latency = CheckAllIfAny(headerColumnIndex_, &columnsOK, { Header_MsPCLatency });
switch (time) {
case 1: params_.emplace_back(L"--qpc_time"); break;
@@ -273,6 +274,7 @@ bool PresentMonCsv::Open(char const* file, int line, std::wstring const& path)
if (!track_input) params_.emplace_back(L"--no_track_input");
if (track_frame_type) params_.emplace_back(L"--track_frame_type");
if (track_app_timing) params_.emplace_back(L"--track_app_timing");
+ if (track_pc_latency) params_.emplace_back(L"--track_pc_latency");
}
if (!columnsOK) {
diff --git a/Tools/create_gold_csvs.cmd b/Tools/create_gold_csvs.cmd
index 9e3a0943..c48889a2 100644
--- a/Tools/create_gold_csvs.cmd
+++ b/Tools/create_gold_csvs.cmd
@@ -40,6 +40,6 @@ exit /b 0
exit /b 0
)
- echo %presentmon% --no_console_stats --stop_existing_session --qpc_time --track_frame_type --track_app_timing --track_gpu_video %~3 --etl_file %1 --output_file %2
- %presentmon% --no_console_stats --stop_existing_session --qpc_time --track_frame_type --track_app_timing --track_gpu_video %~3 --etl_file %1 --output_file %2 >NUL 2>&1
+ echo %presentmon% --no_console_stats --stop_existing_session --qpc_time --track_frame_type --track_app_timing --track_gpu_video --track_pc_latency %~3 --etl_file %1 --output_file %2
+ %presentmon% --no_console_stats --stop_existing_session --qpc_time --track_frame_type --track_app_timing --track_gpu_video --track_pc_latency %~3 --etl_file %1 --output_file %2 >NUL 2>&1
exit /b 0
diff --git a/Tools/start_etl_collection.cmd b/Tools/start_etl_collection.cmd
index 1a36f748..39095c45 100644
--- a/Tools/start_etl_collection.cmd
+++ b/Tools/start_etl_collection.cmd
@@ -27,11 +27,12 @@ if errorlevel 1 (
:: ProviderGUID[:Flags[:Level]]
set d3d9=783ACA0A-790E-4d7f-8451-AA850511C6B9:0xf:6
set dxgi=ca11c036-0102-4a2d-a6ad-f03cfed5d3c9:0xf:6
-set dxgkrnl=802ec45a-1e99-4b83-9920-87c98277ba9d
-set dwm=9e9bba3c-2e38-40cb-99f4-9e8281425164:0xffff:6
-set dwm_win7=8c9dd1ad-e6e5-4b07-b455-684a9d879900:0xffff:6
-set win32k=8c416c79-d49b-4f01-a467-e56d3aa8234c:0x8400000440c01000:4
-set pmp=ecaa4712-4644-442f-b94c-a32f6cf8a499
+set dxgkrnl=802ec45a-1e99-4b83-9920-87c98277ba9d
+set dwm=9e9bba3c-2e38-40cb-99f4-9e8281425164:0xffff:6
+set dwm_win7=8c9dd1ad-e6e5-4b07-b455-684a9d879900:0xffff:6
+set win32k=8c416c79-d49b-4f01-a467-e56d3aa8234c:0x8400000440c01000:4
+set pmp=ecaa4712-4644-442f-b94c-a32f6cf8a499
+set pcl=0D216F06-82A6-4D49-BC4F-8F38AE56EFAB
set providers=LOADER
set providers=%providers%+PROC_THREAD
@@ -63,6 +64,7 @@ set providers=%providers%+%dwm%
set providers=%providers%+%dwm_win7%
set providers=%providers%+%pmp%
set providers=%providers%+%win32k%
+set providers=%providers%+%pcl%
%xperf% -start NoCaptureState -on %providers% -BufferSize 1024 -MinBuffers 30 -MaxBuffers 120 -f NoCaptureState.etl
if %errorlevel% neq 0 goto error