Skip to content

Commit f9f9b85

Browse files
authored
Merge pull request #470 from GameTechDev/feature/pc-latency-diagnostics
Feature/pc latency diagnostics
2 parents d9c2e08 + 37d144a commit f9f9b85

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+1940
-333
lines changed

ETLTrimmer/main.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,8 @@ int main(int argc, const char** argv)
374374
traceConsumer.mTrackGPUVideo = true; // ... GPU video work (separately from non-video GPU work).
375375
traceConsumer.mTrackInput = true; // ... keyboard/mouse latency.
376376
traceConsumer.mTrackFrameType = true; // ... the frame type communicated through the Intel-PresentMon provider.
377+
traceConsumer.mTrackAppTiming = true; // ... app timing data communicated through the Intel-PresentMon provider.
378+
traceConsumer.mTrackPcLatency = true; // ... Nvidia PCL stats.
377379
EnableProvidersListing(0, nullptr, &traceConsumer, true, true, pFilter);
378380
}
379381

IntelPresentMon/AppCef/ipm-ui-vue/BlockLists/TargetBlockList.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ bethesdanethelper.exe
2525
bethesdanetlauncher.exe
2626
blend.exe
2727
blender.exe
28+
bootstrapperui_v2.exe
2829
bsglauncher.exe
2930
calculator.exe
3031
calculatorapp.exe

IntelPresentMon/CommonUtilities/CommonUtilities.vcxproj.filters

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,6 @@
171171
<ClInclude Include="log\TimePoint.h">
172172
<Filter>Header Files</Filter>
173173
</ClInclude>
174-
<ClInclude Include="Math.h">
175-
<Filter>Header Files</Filter>
176-
</ClInclude>
177174
<ClInclude Include="log\Subsystem.h">
178175
<Filter>Header Files</Filter>
179176
</ClInclude>
@@ -234,6 +231,9 @@
234231
<ClInclude Include="ref\GeneratedReflectionHelpers.h">
235232
<Filter>Header Files</Filter>
236233
</ClInclude>
234+
<ClInclude Include="Math.h">
235+
<Filter>Header Files</Filter>
236+
</ClInclude>
237237
<ClInclude Include="win\MessageBox.h">
238238
<Filter>Header Files</Filter>
239239
</ClInclude>
@@ -395,6 +395,9 @@
395395
<ClCompile Include="win\ProcessMapBuilder.cpp">
396396
<Filter>Source Files</Filter>
397397
</ClCompile>
398+
<ClCompile Include="Math.cpp">
399+
<Filter>Source Files</Filter>
400+
</ClCompile>
398401
</ItemGroup>
399402
<ItemGroup>
400403
<None Include="vcpkg.json" />

IntelPresentMon/CommonUtilities/Math.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22
#include <cmath>
33
#include <limits>
4+
#include <algorithm>
45

56
namespace pmon::util
67
{
@@ -53,4 +54,9 @@ namespace pmon::util
5354
const auto conversionFactor = srcFactor / dstFactor;
5455
return To(fromExtended * conversionFactor);
5556
}
57+
template<typename T>
58+
T CalculateEma(T prevEma, T newSample, T alpha)
59+
{
60+
return prevEma + alpha * (newSample - prevEma);
61+
}
5662
}

IntelPresentMon/CommonUtilities/Meta.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44

55
namespace pmon::util
66
{
7+
// Helper: dependent_false for static_assert in templates.
8+
template<typename T>
9+
struct dependent_false : std::false_type {};
10+
711
// deconstruct member pointer into the object type the pointer works with and the member type
812
template <typename T> struct MemberPointerInfo;
913
template <typename S, typename M>

IntelPresentMon/Core/source/pmon/RawFrameDataMetricList.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,12 @@ namespace p2c::pmon
4747
Element{.metricId = PM_METRIC_GPU_BUSY, .deviceId = 0 },
4848
Element{.metricId = PM_METRIC_GPU_WAIT, .deviceId = 0 },
4949
Element{.metricId = PM_METRIC_ANIMATION_ERROR, .deviceId = 0 },
50+
Element{.metricId = PM_METRIC_FLIP_DELAY, .deviceId = 0 },
5051
Element{.metricId = PM_METRIC_ANIMATION_TIME, .deviceId = 0 },
5152
Element{.metricId = PM_METRIC_ALL_INPUT_TO_PHOTON_LATENCY, .deviceId = 0 },
5253
Element{.metricId = PM_METRIC_CLICK_TO_PHOTON_LATENCY, .deviceId = 0 },
5354
Element{.metricId = PM_METRIC_INSTRUMENTED_LATENCY, .deviceId = 0 },
55+
Element{.metricId = PM_METRIC_PC_LATENCY, .deviceId = 0 },
5456

5557
Element{.metricId = PM_METRIC_GPU_POWER, .deviceId = activeDeviceId },
5658
Element{.metricId = PM_METRIC_GPU_VOLTAGE, .deviceId = activeDeviceId },

IntelPresentMon/Interprocess/source/metadata/MetricList.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,4 @@
9393
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) \
9494
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) \
9595
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) \
96+
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) \

IntelPresentMon/PresentMonAPI2/PresentMonAPI.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ extern "C" {
132132
PM_METRIC_DISPLAYED_FRAME_TIME,
133133
PM_METRIC_BETWEEN_APP_START,
134134
PM_METRIC_PRESENTED_FRAME_TIME,
135+
PM_METRIC_FLIP_DELAY,
135136
};
136137

137138
enum PM_METRIC_TYPE

IntelPresentMon/PresentMonAPI2Tests/CsvHelper.h

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -306,18 +306,22 @@ void CharConvert<T>::Convert(const std::string data, T& convertedData, Header co
306306
}
307307

308308
size_t countDecimalPlaces(double value) {
309-
// Convert double to string
310309
std::string str = std::to_string(value);
310+
auto dotPos = str.find('.');
311+
if (dotPos == std::string::npos) return 0;
311312

312-
char const* a = str.c_str();
313+
// Get the decimal part
314+
std::string decimals = str.substr(dotPos + 1);
313315

314-
double testNumber = 0.0;
315-
double goldNumber = 0.0;
316-
int testSucceededCount = sscanf_s(a, "%lf", &testNumber);
316+
// Remove trailing zeros
317+
decimals.erase(decimals.find_last_not_of('0') + 1);
317318

318-
const char* testDecimalAddr = strchr(a, '.');
319-
size_t testDecimalNumbersCount = testDecimalAddr == nullptr ? 0 : ((a + strlen(a)) - testDecimalAddr - 1);
320-
return testDecimalNumbersCount;
319+
// Count non-zero decimal digits
320+
size_t count = 0;
321+
for (char c : decimals) {
322+
if (c != '0') ++count;
323+
}
324+
return count;
321325
}
322326

323327
template<typename T>
@@ -357,7 +361,7 @@ std::optional<std::ofstream> CreateCsvFile(std::string& output_dir, std::string&
357361
",MsBetweenDisplayChange,MsInPresent,MsRenderPresentLatency"
358362
",MsUntilDisplayed,MsPCLatency,CPUStartQPC,MsBetweenAppStart"
359363
",MsCPUBusy,MsCPUWait,MsGPULatency,MsGPUTime,MsGPUBusy,MsGPUWait"
360-
",MsVideoBusy,MsAnimationError,AnimationTime,MsAllInputToPhotonLatency"
364+
",MsVideoBusy,MsAnimationError,AnimationTime,MsFlipDelay,MsAllInputToPhotonLatency"
361365
",MsClickToPhotonLatency,MsInstrumentedLatency";
362366
csvFile << std::endl;
363367
return csvFile;
@@ -416,7 +420,7 @@ std::string TranslateFrameType(PM_FRAME_TYPE frameType) {
416420
}
417421

418422
void WriteToCSV(std::optional<std::ofstream>& debugCsvFile, const std::string& processName, const unsigned int& processId,
419-
PM_QUERY_ELEMENT(&queryElements)[28], pmapi::BlobContainer& blobs)
423+
PM_QUERY_ELEMENT(&queryElements)[29], pmapi::BlobContainer& blobs)
420424
{
421425

422426
if (!debugCsvFile.has_value()) {
@@ -449,9 +453,10 @@ void WriteToCSV(std::optional<std::ofstream>& debugCsvFile, const std::string& p
449453
const auto msGpuWait = *reinterpret_cast<const double*>(&pBlob[queryElements[22].dataOffset]);
450454
const auto msAnimationError = *reinterpret_cast<const double*>(&pBlob[queryElements[23].dataOffset]);
451455
const auto animationTime = *reinterpret_cast<const double*>(&pBlob[queryElements[24].dataOffset]);
452-
const auto msAllInputToPhotonLatency = *reinterpret_cast<const double*>(&pBlob[queryElements[25].dataOffset]);
453-
const auto msClickToPhotonLatency = *reinterpret_cast<const double*>(&pBlob[queryElements[26].dataOffset]);
454-
const auto msInstrumentedLatency = *reinterpret_cast<const double*>(&pBlob[queryElements[27].dataOffset]);
456+
const auto msFlipDelay = *reinterpret_cast<const double*>(&pBlob[queryElements[25].dataOffset]);
457+
const auto msAllInputToPhotonLatency = *reinterpret_cast<const double*>(&pBlob[queryElements[26].dataOffset]);
458+
const auto msClickToPhotonLatency = *reinterpret_cast<const double*>(&pBlob[queryElements[27].dataOffset]);
459+
const auto msInstrumentedLatency = *reinterpret_cast<const double*>(&pBlob[queryElements[28].dataOffset]);
455460
*debugCsvFile << processName << ",";
456461
*debugCsvFile << processId << ",";
457462
*debugCsvFile << std::hex << "0x" << std::dec << swapChain << ",";
@@ -480,6 +485,7 @@ void WriteToCSV(std::optional<std::ofstream>& debugCsvFile, const std::string& p
480485
*debugCsvFile << 0 << ",";
481486
*debugCsvFile << msAnimationError << ",";
482487
*debugCsvFile << animationTime << ",";
488+
*debugCsvFile << msFlipDelay << ",";
483489
*debugCsvFile << msAllInputToPhotonLatency << ",";
484490
*debugCsvFile << msClickToPhotonLatency << ",";
485491
*debugCsvFile << msInstrumentedLatency << std::endl;
@@ -497,7 +503,7 @@ class CsvParser {
497503
bool Open(std::wstring const& path, uint32_t processId);
498504
void Close();
499505
bool VerifyBlobAgainstCsv(const std::string& processName, const unsigned int& processId,
500-
PM_QUERY_ELEMENT(&queryElements)[28], pmapi::BlobContainer& blobs, std::optional<std::ofstream>& debugCsvFile);
506+
PM_QUERY_ELEMENT(&queryElements)[29], pmapi::BlobContainer& blobs, std::optional<std::ofstream>& debugCsvFile);
501507
bool ResetCsv();
502508

503509
private:
@@ -526,7 +532,7 @@ CsvParser::CsvParser()
526532
{}
527533

528534
bool CsvParser::VerifyBlobAgainstCsv(const std::string& processName, const unsigned int& processId,
529-
PM_QUERY_ELEMENT(&queryElements)[28], pmapi::BlobContainer& blobs, std::optional<std::ofstream>& debugCsvFile)
535+
PM_QUERY_ELEMENT(&queryElements)[29], pmapi::BlobContainer& blobs, std::optional<std::ofstream>& debugCsvFile)
530536
{
531537
if (debugCsvFile.has_value()) {
532538
WriteToCSV(debugCsvFile, processName, processId, queryElements, blobs);
@@ -559,11 +565,10 @@ bool CsvParser::VerifyBlobAgainstCsv(const std::string& processName, const unsig
559565
const auto msGpuWait = *reinterpret_cast<const double*>(&pBlob[queryElements[22].dataOffset]);
560566
const auto msAnimationError = *reinterpret_cast<const double*>(&pBlob[queryElements[23].dataOffset]);
561567
const auto animationTime = *reinterpret_cast<const double*>(&pBlob[queryElements[24].dataOffset]);
562-
const auto msAllInputToPhotonLatency = *reinterpret_cast<const double*>(&pBlob[queryElements[25].dataOffset]);
563-
const auto msClickToPhotonLatency = *reinterpret_cast<const double*>(&pBlob[queryElements[26].dataOffset]);
564-
const auto msInstrumentedLatency = *reinterpret_cast<const double*>(&pBlob[queryElements[27].dataOffset]);
565-
566-
568+
const auto msFrameDelay = *reinterpret_cast<const double*>(&pBlob[queryElements[25].dataOffset]);
569+
const auto msAllInputToPhotonLatency = *reinterpret_cast<const double*>(&pBlob[queryElements[26].dataOffset]);
570+
const auto msClickToPhotonLatency = *reinterpret_cast<const double*>(&pBlob[queryElements[27].dataOffset]);
571+
const auto msInstrumentedLatency = *reinterpret_cast<const double*>(&pBlob[queryElements[28].dataOffset]);
567572

568573
// Read rows until we find one with the process we are interested in
569574
// or we are out of data.
@@ -689,6 +694,9 @@ bool CsvParser::VerifyBlobAgainstCsv(const std::string& processName, const unsig
689694
case Header_MsPCLatency:
690695
if (v2MetricRow_.msPcLatency.has_value()) {
691696
columnsMatch = Validate(v2MetricRow_.msPcLatency.value(), msPcLatency);
697+
if (!columnsMatch) {
698+
OutputDebugStringA("What!?\n");
699+
}
692700
}
693701
else
694702
{
@@ -780,6 +788,11 @@ bool CsvParser::VerifyBlobAgainstCsv(const std::string& processName, const unsig
780788
columnsMatch = true;
781789
break;
782790
}
791+
if (columnsMatch == false) {
792+
// If the columns do not match, create an error string
793+
// and assert failure.
794+
Assert::Fail(CreateErrorString(pair.second, line_).c_str());
795+
}
783796
Assert::IsTrue(columnsMatch, CreateErrorString(pair.second, line_).c_str());
784797
}
785798
}
@@ -1185,7 +1198,6 @@ void CsvParser::ConvertToMetricDataType(const char* data, Header columnId)
11851198
}
11861199
}
11871200
break;
1188-
11891201
default:
11901202
Assert::Fail(CreateErrorString(UnknownHeader, line_).c_str());
11911203
}

0 commit comments

Comments
 (0)