| 52 | |
| 53 | template<typename T> |
| 54 | void QpcTimeTest(bool qpc) |
| 55 | { |
| 56 | LARGE_INTEGER freq = {}; |
| 57 | QueryPerformanceFrequency(&freq); |
| 58 | |
| 59 | LARGE_INTEGER qpcMin = {}; |
| 60 | LARGE_INTEGER qpcMax = {}; |
| 61 | std::wstring csvPath(outDir_ + (qpc ? L"qpc_time" : L"qpc_time_ms") + L".csv"); |
| 62 | |
| 63 | PresentMon pm; |
| 64 | pm.Add(L"--stop_existing_session --terminate_after_timed --timed 1 --no_track_gpu --no_track_input --no_track_display --v1_metrics"); |
| 65 | if (qpc) { |
| 66 | pm.Add(L"--qpc_time"); |
| 67 | } else { |
| 68 | pm.Add(L"--qpc_time_ms"); |
| 69 | } |
| 70 | pm.AddCsvPath(csvPath); |
| 71 | |
| 72 | QueryPerformanceCounter(&qpcMin); |
| 73 | pm.PMSTART(); |
| 74 | pm.PMEXITED(2000, 0); |
| 75 | QueryPerformanceCounter(&qpcMax); |
| 76 | if (::testing::Test::HasFailure()) { |
| 77 | return; |
| 78 | } |
| 79 | |
| 80 | auto qmin = Convert<T>((uint64_t) qpcMin.QuadPart, freq); |
| 81 | auto qmax = Convert<T>((uint64_t) qpcMax.QuadPart, freq); |
| 82 | |
| 83 | PresentMonCsv csv; |
| 84 | if (!csv.CSVOPEN(csvPath)) { |
| 85 | printf(" PresentMon didn't create a CSV file, likely because there were no presents to capture.\n" |
| 86 | " Re-run the test with a graphics application running.\n"); |
| 87 | return; |
| 88 | } |
| 89 | |
| 90 | auto idxProcessID = csv.GetColumnIndex("ProcessID"); |
| 91 | auto idxTimeInSeconds = csv.GetColumnIndex("TimeInSeconds"); |
| 92 | auto idxQPCTime = csv.GetColumnIndex("QPCTime"); |
| 93 | if (idxProcessID == SIZE_MAX) AddTestFailure(__FILE__, __LINE__, " Output missing required column: ProcessID"); |
| 94 | if (idxTimeInSeconds == SIZE_MAX) AddTestFailure(__FILE__, __LINE__, " Output missing required column: TimeInSeconds"); |
| 95 | if (idxQPCTime == SIZE_MAX) AddTestFailure(__FILE__, __LINE__, " Output missing required column: QPCTime"); |
| 96 | if (::testing::Test::HasFailure()) { |
| 97 | return; |
| 98 | } |
| 99 | |
| 100 | // TimeInSeconds is only ordered per-process, so we track each process separately |
| 101 | std::unordered_map<uint32_t, std::pair<double, T>> firstMeasurement; |
| 102 | |
| 103 | while (!::testing::Test::HasFailure() && csv.ReadRow()) { |
| 104 | auto pid = strtoul(csv.cols_[idxProcessID], nullptr, 10); |
| 105 | auto t = Convert<double>(csv.cols_[idxTimeInSeconds], freq); |
| 106 | auto q = Convert<T> (csv.cols_[idxQPCTime], freq); |
| 107 | |
| 108 | EXPECT_LE(qmin, q); |
| 109 | EXPECT_LE(q, qmax); |
| 110 | |
| 111 | auto const& first = firstMeasurement.emplace(std::make_pair(pid, std::make_pair(t, q))).first->second; |
nothing calls this directly
no test coverage detected