Skip to content

Commit 8514150

Browse files
Added in AnimationTime
2 parents 1166cc1 + f18b9e8 commit 8514150

File tree

24 files changed

+1661
-1481
lines changed

24 files changed

+1661
-1481
lines changed

IntelPresentMon/Core/source/pmon/RawFrameDataMetricList.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ namespace p2c::pmon
4141
Element{.metricId = PM_METRIC_DISPLAY_LATENCY, .deviceId = 0 },
4242
Element{.metricId = PM_METRIC_DISPLAYED_TIME, .deviceId = 0 },
4343
Element{.metricId = PM_METRIC_ANIMATION_ERROR, .deviceId = 0 },
44+
Element{.metricId = PM_METRIC_ANIMATION_TIME, .deviceId = 0 },
4445
Element{.metricId = PM_METRIC_ALL_INPUT_TO_PHOTON_LATENCY, .deviceId = 0 },
4546
Element{.metricId = PM_METRIC_CLICK_TO_PHOTON_LATENCY, .deviceId = 0 },
4647
Element{.metricId = PM_METRIC_INSTRUMENTED_LATENCY, .deviceId = 0 },

IntelPresentMon/Core/source/pmon/RawFrameDataWriter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ namespace p2c::pmon
136136
if (metricId == PM_METRIC_DISPLAYED_TIME ||
137137
metricId == PM_METRIC_DISPLAY_LATENCY ||
138138
metricId == PM_METRIC_ANIMATION_ERROR ||
139+
metricId == PM_METRIC_ANIMATION_TIME ||
139140
metricId == PM_METRIC_CLICK_TO_PHOTON_LATENCY ||
140141
metricId == PM_METRIC_ALL_INPUT_TO_PHOTON_LATENCY) {
141142
flags |= Annotation_::FLAG_NAN_MEANS_NOT_AVAILABLE;

IntelPresentMon/Interprocess/source/metadata/MetricList.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
\
3232
X_(PM_METRIC_DISPLAYED_TIME, PM_METRIC_TYPE_DYNAMIC_FRAME, PM_UNIT_MILLISECONDS, PM_DATA_TYPE_DOUBLE, PM_DATA_TYPE_DOUBLE, 0, PM_DEVICE_TYPE_INDEPENDENT, FULL_STATS) \
3333
X_(PM_METRIC_ANIMATION_ERROR, PM_METRIC_TYPE_DYNAMIC_FRAME, PM_UNIT_MILLISECONDS, PM_DATA_TYPE_DOUBLE, PM_DATA_TYPE_DOUBLE, 0, PM_DEVICE_TYPE_INDEPENDENT, FULL_STATS) \
34+
X_(PM_METRIC_ANIMATION_TIME, PM_METRIC_TYPE_FRAME_EVENT, PM_UNIT_MILLISECONDS, PM_DATA_TYPE_DOUBLE, PM_DATA_TYPE_DOUBLE, 0, PM_DEVICE_TYPE_INDEPENDENT, PM_STAT_NONE) \
3435
\
3536
X_(PM_METRIC_SYNC_INTERVAL, PM_METRIC_TYPE_DYNAMIC_FRAME, PM_UNIT_VERTICAL_BLANKS, PM_DATA_TYPE_INT32, PM_DATA_TYPE_INT32, 0, PM_DEVICE_TYPE_INDEPENDENT, PM_STAT_MID_POINT) \
3637
X_(PM_METRIC_PRESENT_FLAGS, PM_METRIC_TYPE_DYNAMIC_FRAME, PM_UNIT_DIMENSIONLESS, PM_DATA_TYPE_UINT32, PM_DATA_TYPE_UINT32, 0, PM_DEVICE_TYPE_INDEPENDENT, PM_STAT_MID_POINT) \

IntelPresentMon/PresentMonAPI2/PresentMonAPI.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ extern "C" {
116116

117117
PM_METRIC_ALL_INPUT_TO_PHOTON_LATENCY,
118118
PM_METRIC_INSTRUMENTED_LATENCY,
119+
PM_METRIC_ANIMATION_TIME,
120+
119121
};
120122

121123
enum PM_METRIC_TYPE

IntelPresentMon/PresentMonAPI2Tests/CsvHelper.h

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ enum Header {
4040
Header_DisplayLatency,
4141
Header_DisplayedTime,
4242
Header_AnimationError,
43+
Header_AnimationTime,
4344
Header_ClickToPhotonLatency,
4445
Header_AllInputToPhotonLatency,
4546

@@ -92,6 +93,7 @@ struct v2Metrics {
9293
std::optional<double> displayLatency;
9394
std::optional<double> displayedTime;
9495
std::optional<double> animationError;
96+
std::optional<double> animationTime;
9597
std::optional<double> clickToPhotonLatency;
9698
std::optional<double> AllInputToPhotonLatency;
9799
std::optional<double> InstrumentedLatency;
@@ -124,6 +126,7 @@ constexpr char const* GetHeaderString(Header h)
124126
case Header_DisplayLatency: return "DisplayLatency";
125127
case Header_DisplayedTime: return "DisplayedTime";
126128
case Header_AnimationError: return "AnimationError";
129+
case Header_AnimationTime: return "AnimationTime";
127130
case Header_ClickToPhotonLatency: return "ClickToPhotonLatency";
128131
case Header_AllInputToPhotonLatency: return "AllInputToPhotonLatency";
129132

@@ -328,7 +331,7 @@ class CsvParser {
328331
bool Open(std::wstring const& path, uint32_t processId);
329332
void Close();
330333
bool VerifyBlobAgainstCsv(const std::string& processName, const unsigned int& processId,
331-
PM_QUERY_ELEMENT(&queryElements)[21], pmapi::BlobContainer& blobs);
334+
PM_QUERY_ELEMENT(&queryElements)[22], pmapi::BlobContainer& blobs);
332335
bool ResetCsv();
333336

334337
private:
@@ -357,7 +360,7 @@ CsvParser::CsvParser()
357360
{}
358361

359362
bool CsvParser::VerifyBlobAgainstCsv(const std::string& processName, const unsigned int& processId,
360-
PM_QUERY_ELEMENT(&queryElements)[21], pmapi::BlobContainer& blobs)
363+
PM_QUERY_ELEMENT(&queryElements)[22], pmapi::BlobContainer& blobs)
361364
{
362365

363366
for (auto pBlob : blobs) {
@@ -381,9 +384,12 @@ bool CsvParser::VerifyBlobAgainstCsv(const std::string& processName, const unsig
381384
const auto displayLatency = *reinterpret_cast<const double*>(&pBlob[queryElements[15].dataOffset]);
382385
const auto displayedTime = *reinterpret_cast<const double*>(&pBlob[queryElements[16].dataOffset]);
383386
const auto animationError = *reinterpret_cast<const double*>(&pBlob[queryElements[17].dataOffset]);
384-
const auto allInputToPhotonLatency = *reinterpret_cast<const double*>(&pBlob[queryElements[18].dataOffset]);
385-
const auto clickToPhotonLatency = *reinterpret_cast<const double*>(&pBlob[queryElements[19].dataOffset]);
386-
const auto instrumentedLatency = *reinterpret_cast<const double*>(&pBlob[queryElements[20].dataOffset]);
387+
const auto animationTime = *reinterpret_cast<const double*>(&pBlob[queryElements[18].dataOffset]);
388+
const auto allInputToPhotonLatency = *reinterpret_cast<const double*>(&pBlob[queryElements[19].dataOffset]);
389+
const auto clickToPhotonLatency = *reinterpret_cast<const double*>(&pBlob[queryElements[20].dataOffset]);
390+
const auto instrumentedLatency = *reinterpret_cast<const double*>(&pBlob[queryElements[21].dataOffset]);
391+
392+
387393

388394
// Read rows until we find one with the process we are interested in
389395
// or we are out of data.
@@ -504,6 +510,21 @@ bool CsvParser::VerifyBlobAgainstCsv(const std::string& processName, const unsig
504510
}
505511
}
506512
break;
513+
case Header_AnimationTime:
514+
if (v2MetricRow_.animationTime.has_value()) {
515+
columnsMatch = Validate(v2MetricRow_.animationTime.value(), animationTime);
516+
}
517+
else
518+
{
519+
if (std::isnan(animationTime)) {
520+
columnsMatch = true;
521+
}
522+
else
523+
{
524+
columnsMatch = false;
525+
}
526+
}
527+
break;
507528
case Header_ClickToPhotonLatency:
508529
if (v2MetricRow_.clickToPhotonLatency.has_value()) {
509530
columnsMatch = Validate(v2MetricRow_.clickToPhotonLatency.value(), clickToPhotonLatency);
@@ -661,6 +682,7 @@ bool CsvParser::Open(std::wstring const& path, uint32_t processId) {
661682
Header_DisplayLatency,
662683
Header_DisplayedTime,
663684
Header_AnimationError,
685+
Header_AnimationTime,
664686
Header_ClickToPhotonLatency,
665687
Header_AllInputToPhotonLatency,
666688
Header_InstrumentedLatency });
@@ -850,6 +872,19 @@ void CsvParser::ConvertToMetricDataType(const char* data, Header columnId)
850872
}
851873
}
852874
break;
875+
case Header_AnimationTime:
876+
{
877+
if (strncmp(data, "NA", 2) != 0) {
878+
double convertedData = 0.;
879+
CharConvert<double> converter;
880+
converter.Convert(data, convertedData, columnId, line_);
881+
v2MetricRow_.animationTime = convertedData;
882+
}
883+
else {
884+
v2MetricRow_.animationTime.reset();
885+
}
886+
}
887+
break;
853888
case Header_ClickToPhotonLatency:
854889
{
855890
if (strncmp(data, "NA", 2) != 0) {

IntelPresentMon/PresentMonAPI2Tests/EtlTests.cpp

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ namespace EtlTests
159159
{ PM_METRIC_DISPLAY_LATENCY, PM_STAT_NONE, 0, 0 },
160160
{ PM_METRIC_DISPLAYED_TIME, PM_STAT_NONE, 0, 0 },
161161
{ PM_METRIC_ANIMATION_ERROR, PM_STAT_NONE, 0, 0 },
162+
{ PM_METRIC_ANIMATION_TIME, PM_STAT_NONE, 0, 0 },
162163
{ PM_METRIC_ALL_INPUT_TO_PHOTON_LATENCY, PM_STAT_NONE, 0, 0},
163164
{ PM_METRIC_CLICK_TO_PHOTON_LATENCY, PM_STAT_NONE, 0, 0},
164165
{ PM_METRIC_INSTRUMENTED_LATENCY, PM_STAT_NONE, 0, 0 }
@@ -1680,7 +1681,55 @@ namespace EtlTests
16801681
}
16811682

16821683
oChild.emplace("PresentMonService.exe"s,
1683-
"--timed-stop"s, "20000"s,
1684+
"--timed-stop"s, "60000"s,
1685+
"--control-pipe"s, pipeName,
1686+
"--nsm-prefix"s, "pmon_nsm_utest_"s,
1687+
"--intro-nsm"s, introName,
1688+
"--etl-test-file"s, etlName,
1689+
bp::std_out > out, bp::std_in < in);
1690+
1691+
std::this_thread::sleep_for(1000ms);
1692+
1693+
std::unique_ptr<pmapi::Session> pSession;
1694+
{
1695+
try
1696+
{
1697+
pSession = std::make_unique<pmapi::Session>(pipeName.c_str(), introName.c_str());
1698+
}
1699+
catch (const std::exception& e) {
1700+
std::cout << "Error: " << e.what() << std::endl;
1701+
Assert::AreEqual(false, true, L"*** Connecting to service via named pipe");
1702+
return;
1703+
}
1704+
}
1705+
1706+
RunTestCaseV2(std::move(pSession), processId, processName, goldCsvFile);
1707+
goldCsvFile.Close();
1708+
}
1709+
TEST_METHOD(Tc7v2CPXellOnFgOn11320Ext)
1710+
{
1711+
namespace bp = boost::process;
1712+
using namespace std::string_literals;
1713+
using namespace std::chrono_literals;
1714+
1715+
const uint32_t processId = 11320;
1716+
const std::string processName = "cpLauncher.exe";
1717+
1718+
bp::ipstream out; // Stream for reading the process's output
1719+
bp::opstream in; // Stream for writing to the process's input
1720+
1721+
const auto pipeName = R"(\\.\pipe\test-pipe-pmsvc-2)"s;
1722+
const auto introName = "PM_intro_test_nsm_2"s;
1723+
const auto etlName = "F:\\EtlTesting\\test_case_7.etl";
1724+
const auto goldCsvName = L"F:\\EtlTesting\\test_case_7.csv";
1725+
1726+
CsvParser goldCsvFile;
1727+
if (!goldCsvFile.Open(goldCsvName, processId)) {
1728+
return;
1729+
}
1730+
1731+
oChild.emplace("PresentMonService.exe"s,
1732+
"--timed-stop"s, "60000"s,
16841733
"--control-pipe"s, pipeName,
16851734
"--nsm-prefix"s, "pmon_nsm_utest_"s,
16861735
"--intro-nsm"s, introName,

IntelPresentMon/PresentMonMiddleware/ConcreteMiddleware.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1052,8 +1052,14 @@ static void ReportMetrics(
10521052
SetActiveGraphicsAdapter(*devId);
10531053
}
10541054

1055+
uint64_t simStartTime = 0;
1056+
auto iter = appSimStartTime.find(processId);
1057+
if (iter != appSimStartTime.end()) {
1058+
simStartTime = iter->second;
1059+
}
1060+
10551061
// context transmits various data that applies to each gather command in the query
1056-
PM_FRAME_QUERY::Context ctx{ nsm_hdr->start_qpc, pShmClient->GetQpcFrequency().QuadPart };
1062+
PM_FRAME_QUERY::Context ctx{ nsm_hdr->start_qpc, pShmClient->GetQpcFrequency().QuadPart, simStartTime };
10571063

10581064
while (frames_copied < frames_to_copy) {
10591065
const PmNsmFrameData* pCurrentFrameData = nullptr;
@@ -1078,6 +1084,10 @@ static void ReportMetrics(
10781084
pFrameDataOfLastDisplayed,
10791085
pPreviousFrameDataOfLastDisplayed);
10801086

1087+
if (simStartTime == 0 && ctx.firstAppSimStartTime != 0) {
1088+
simStartTime = ctx.firstAppSimStartTime;
1089+
}
1090+
10811091
if (ctx.dropped) {
10821092
pQuery->GatherToBlob(ctx, pBlob);
10831093
pBlob += pQuery->GetBlobSize();
@@ -1099,6 +1109,9 @@ static void ReportMetrics(
10991109
}
11001110
// Set to the actual number of frames copied
11011111
numFrames = frames_copied;
1112+
if (simStartTime != 0) {
1113+
appSimStartTime[processId] = simStartTime;
1114+
}
11021115
}
11031116

11041117
void ConcreteMiddleware::CalculateFpsMetric(fpsSwapChainData& swapChain, const PM_QUERY_ELEMENT& element, uint8_t* pBlob, LARGE_INTEGER qpcFrequency)

IntelPresentMon/PresentMonMiddleware/ConcreteMiddleware.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ namespace pmon::mid
138138
uint32_t clientProcessId = 0;
139139
// Stream clients mapping to process id
140140
std::map<uint32_t, std::unique_ptr<StreamClient>> presentMonStreamClients;
141+
// App sim start time for each process id
142+
std::map<uint32_t, uint64_t> appSimStartTime;
141143
std::unique_ptr<ipc::MiddlewareComms> pComms;
142144
// Dynamic query handle to frame data delta
143145
std::unordered_map<std::pair<const PM_DYNAMIC_QUERY*, uint32_t>, uint64_t> queryFrameDataDeltas;

IntelPresentMon/PresentMonMiddleware/FrameEventQuery.cpp

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ namespace
344344
private:
345345
uint32_t outputOffset_;
346346
};
347-
template<uint64_t PmNsmPresentEvent::* pEnd>
347+
template<uint64_t PmNsmPresentEvent::* pEnd, bool doDroppedCheck, bool calcAnimationTime>
348348
class StartDifferenceGatherCommand_ : public pmon::mid::GatherCommand_
349349
{
350350
public:
@@ -355,9 +355,29 @@ namespace
355355
}
356356
void Gather(Context& ctx, uint8_t* pDestBlob) const override
357357
{
358-
const auto qpcDuration = ctx.pSourceFrameData->present_event.*pEnd - ctx.qpcStart;
359-
const auto val = ctx.performanceCounterPeriodMs * double(qpcDuration);
360-
reinterpret_cast<double&>(pDestBlob[outputOffset_]) = val;
358+
if constexpr (calcAnimationTime) {
359+
if constexpr (doDroppedCheck) {
360+
if (ctx.dropped) {
361+
reinterpret_cast<double&>(pDestBlob[outputOffset_]) =
362+
std::numeric_limits<double>::quiet_NaN();
363+
return;
364+
}
365+
}
366+
if (ctx.sourceFrameDisplayIndex != ctx.appIndex) {
367+
reinterpret_cast<double&>(pDestBlob[outputOffset_]) = 0.;
368+
return;
369+
}
370+
const auto firstSimStartTime = ctx.firstAppSimStartTime != 0 ? ctx.firstAppSimStartTime :
371+
ctx.qpcStart;
372+
const auto currentSimTime = ctx.pSourceFrameData->present_event.*pEnd != 0 ? ctx.pSourceFrameData->present_event.*pEnd :
373+
ctx.cpuStart;
374+
const auto val = TimestampDeltaToUnsignedMilliSeconds(firstSimStartTime, currentSimTime, ctx.performanceCounterPeriodMs);
375+
reinterpret_cast<double&>(pDestBlob[outputOffset_]) = val;
376+
} else {
377+
const auto qpcDuration = ctx.cpuStart - ctx.qpcStart;
378+
const auto val = ctx.performanceCounterPeriodMs * double(qpcDuration);
379+
reinterpret_cast<double&>(pDestBlob[outputOffset_]) = val;
380+
}
361381
}
362382
uint32_t GetBeginOffset() const override
363383
{
@@ -935,7 +955,7 @@ std::unique_ptr<mid::GatherCommand_> PM_FRAME_QUERY::MapQueryElementToGatherComm
935955
case PM_METRIC_PRESENT_FLAGS:
936956
return std::make_unique<CopyGatherCommand_<&Pre::PresentFlags>>(pos);
937957
case PM_METRIC_CPU_START_TIME:
938-
return std::make_unique<StartDifferenceGatherCommand_<&Pre::PresentStartTime>>(pos);
958+
return std::make_unique<StartDifferenceGatherCommand_<&Pre::PresentStartTime, 0, 0>>(pos);
939959
case PM_METRIC_CPU_FRAME_TIME:
940960
return std::make_unique<CpuFrameQpcFrameTimeCommand_>(pos);
941961
case PM_METRIC_CPU_BUSY:
@@ -950,6 +970,8 @@ std::unique_ptr<mid::GatherCommand_> PM_FRAME_QUERY::MapQueryElementToGatherComm
950970
return std::make_unique<DisplayDifferenceGatherCommand_>(pos);
951971
case PM_METRIC_ANIMATION_ERROR:
952972
return std::make_unique<AnimationErrorGatherCommand_<1,1>>(pos);
973+
case PM_METRIC_ANIMATION_TIME:
974+
return std::make_unique<StartDifferenceGatherCommand_<&Pre::AppSimStartTime, 1, 1>>(pos);
953975
case PM_METRIC_GPU_LATENCY:
954976
return std::make_unique<CpuFrameQpcDifferenceGatherCommand_<&Pre::GPUStartTime, 0>>(pos);
955977
case PM_METRIC_DISPLAY_LATENCY:
@@ -984,6 +1006,10 @@ void PM_FRAME_QUERY::Context::UpdateSourceData(const PmNsmFrameData* pSourceFram
9841006
}
9851007
}
9861008

1009+
if (firstAppSimStartTime == 0) {
1010+
firstAppSimStartTime = pSourceFrameData->present_event.AppSimStartTime;
1011+
}
1012+
9871013
if (pFrameDataOfLastPresented) {
9881014
cpuStart = pFrameDataOfLastPresented->present_event.PresentStartTime +
9891015
pFrameDataOfLastPresented->present_event.TimeInPresent;

IntelPresentMon/PresentMonMiddleware/FrameEventQuery.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ struct PM_FRAME_QUERY
2222
struct Context
2323
{
2424
// functions
25-
Context(uint64_t qpcStart, long long perfCounterFrequency) : qpcStart{ qpcStart },
26-
performanceCounterPeriodMs{ perfCounterFrequency != 0.f ? 1000.0 / perfCounterFrequency : 0.f } {}
25+
Context(uint64_t qpcStart, long long perfCounterFrequency, uint64_t appSimStartTime) : qpcStart{ qpcStart },
26+
performanceCounterPeriodMs{ perfCounterFrequency != 0.f ? 1000.0 / perfCounterFrequency : 0.f },
27+
firstAppSimStartTime { appSimStartTime} {}
2728
void UpdateSourceData(const PmNsmFrameData* pSourceFrameData_in,
2829
const PmNsmFrameData* pFrameDataOfNextDisplayed,
2930
const PmNsmFrameData* pFrameDataofLastPresented,
@@ -52,6 +53,8 @@ struct PM_FRAME_QUERY
5253
uint64_t lastReceivedNotDisplayedClickQpc = 0;
5354
// All other input time qpc of non displayed frame
5455
uint64_t lastReceivedNotDisplayedAllInputTime = 0;
56+
// The first app sim start time
57+
uint64_t firstAppSimStartTime = 0;
5558
};
5659
// functions
5760
PM_FRAME_QUERY(std::span<PM_QUERY_ELEMENT> queryElements);

0 commit comments

Comments
 (0)