summaryrefslogtreecommitdiff
path: root/src/tests/core/host_timing.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tests/core/host_timing.cpp')
-rw-r--r--src/tests/core/host_timing.cpp142
1 files changed, 142 insertions, 0 deletions
diff --git a/src/tests/core/host_timing.cpp b/src/tests/core/host_timing.cpp
new file mode 100644
index 000000000..556254098
--- /dev/null
+++ b/src/tests/core/host_timing.cpp
@@ -0,0 +1,142 @@
1// Copyright 2016 Dolphin Emulator Project / 2017 Dolphin Emulator Project
2// Licensed under GPLv2+
3// Refer to the license.txt file included.
4
5#include <catch2/catch.hpp>
6
7#include <array>
8#include <bitset>
9#include <cstdlib>
10#include <memory>
11#include <string>
12
13#include "common/file_util.h"
14#include "core/core.h"
15#include "core/host_timing.h"
16
17// Numbers are chosen randomly to make sure the correct one is given.
18static constexpr std::array<u64, 5> CB_IDS{{42, 144, 93, 1026, UINT64_C(0xFFFF7FFFF7FFFF)}};
19static constexpr int MAX_SLICE_LENGTH = 10000; // Copied from CoreTiming internals
20static constexpr std::array<u64, 5> calls_order{{2, 0, 1, 4, 3}};
21static std::array<s64, 5> delays{};
22
23static std::bitset<CB_IDS.size()> callbacks_ran_flags;
24static u64 expected_callback = 0;
25
26template <unsigned int IDX>
27void HostCallbackTemplate(u64 userdata, s64 nanoseconds_late) {
28 static_assert(IDX < CB_IDS.size(), "IDX out of range");
29 callbacks_ran_flags.set(IDX);
30 REQUIRE(CB_IDS[IDX] == userdata);
31 REQUIRE(CB_IDS[IDX] == CB_IDS[calls_order[expected_callback]]);
32 delays[IDX] = nanoseconds_late;
33 ++expected_callback;
34}
35
36struct ScopeInit final {
37 ScopeInit() {
38 core_timing.Initialize();
39 }
40 ~ScopeInit() {
41 core_timing.Shutdown();
42 }
43
44 Core::HostTiming::CoreTiming core_timing;
45};
46
47#pragma optimize("", off)
48
49static u64 TestTimerSpeed(Core::HostTiming::CoreTiming& core_timing) {
50 u64 start = core_timing.GetGlobalTimeNs().count();
51 u64 placebo = 0;
52 for (std::size_t i = 0; i < 1000; i++) {
53 placebo += core_timing.GetGlobalTimeNs().count();
54 }
55 u64 end = core_timing.GetGlobalTimeNs().count();
56 return (end - start);
57}
58
59#pragma optimize("", on)
60
61TEST_CASE("HostTiming[BasicOrder]", "[core]") {
62 ScopeInit guard;
63 auto& core_timing = guard.core_timing;
64 std::vector<std::shared_ptr<Core::HostTiming::EventType>> events{
65 Core::HostTiming::CreateEvent("callbackA", HostCallbackTemplate<0>),
66 Core::HostTiming::CreateEvent("callbackB", HostCallbackTemplate<1>),
67 Core::HostTiming::CreateEvent("callbackC", HostCallbackTemplate<2>),
68 Core::HostTiming::CreateEvent("callbackD", HostCallbackTemplate<3>),
69 Core::HostTiming::CreateEvent("callbackE", HostCallbackTemplate<4>),
70 };
71
72 expected_callback = 0;
73
74 core_timing.SyncPause(true);
75
76 u64 one_micro = 1000U;
77 for (std::size_t i = 0; i < events.size(); i++) {
78 u64 order = calls_order[i];
79 core_timing.ScheduleEvent(i * one_micro + 100U, events[order], CB_IDS[order]);
80 }
81 /// test pause
82 REQUIRE(callbacks_ran_flags.none());
83
84 core_timing.Pause(false); // No need to sync
85
86 while (core_timing.HasPendingEvents())
87 ;
88
89 REQUIRE(callbacks_ran_flags.all());
90
91 for (std::size_t i = 0; i < delays.size(); i++) {
92 const double delay = static_cast<double>(delays[i]);
93 const double micro = delay / 1000.0f;
94 const double mili = micro / 1000.0f;
95 printf("HostTimer Pausing Delay[%zu]: %.3f %.6f\n", i, micro, mili);
96 }
97}
98
99TEST_CASE("HostTiming[BasicOrderNoPausing]", "[core]") {
100 ScopeInit guard;
101 auto& core_timing = guard.core_timing;
102 std::vector<std::shared_ptr<Core::HostTiming::EventType>> events{
103 Core::HostTiming::CreateEvent("callbackA", HostCallbackTemplate<0>),
104 Core::HostTiming::CreateEvent("callbackB", HostCallbackTemplate<1>),
105 Core::HostTiming::CreateEvent("callbackC", HostCallbackTemplate<2>),
106 Core::HostTiming::CreateEvent("callbackD", HostCallbackTemplate<3>),
107 Core::HostTiming::CreateEvent("callbackE", HostCallbackTemplate<4>),
108 };
109
110 core_timing.SyncPause(true);
111 core_timing.SyncPause(false);
112
113 expected_callback = 0;
114
115 u64 start = core_timing.GetGlobalTimeNs().count();
116 u64 one_micro = 1000U;
117 for (std::size_t i = 0; i < events.size(); i++) {
118 u64 order = calls_order[i];
119 core_timing.ScheduleEvent(i * one_micro + 100U, events[order], CB_IDS[order]);
120 }
121 u64 end = core_timing.GetGlobalTimeNs().count();
122 const double scheduling_time = static_cast<double>(end - start);
123 const double timer_time = static_cast<double>(TestTimerSpeed(core_timing));
124
125 while (core_timing.HasPendingEvents())
126 ;
127
128 REQUIRE(callbacks_ran_flags.all());
129
130 for (std::size_t i = 0; i < delays.size(); i++) {
131 const double delay = static_cast<double>(delays[i]);
132 const double micro = delay / 1000.0f;
133 const double mili = micro / 1000.0f;
134 printf("HostTimer No Pausing Delay[%zu]: %.3f %.6f\n", i, micro, mili);
135 }
136
137 const double micro = scheduling_time / 1000.0f;
138 const double mili = micro / 1000.0f;
139 printf("HostTimer No Pausing Scheduling Time: %.3f %.6f\n", micro, mili);
140 printf("HostTimer No Pausing Timer Time: %.3f %.6f\n", timer_time / 1000.f,
141 timer_time / 1000000.f);
142}