summaryrefslogtreecommitdiff
path: root/src/tests/core/host_timing.cpp
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2020-02-08 12:48:57 -0400
committerGravatar Fernando Sahmkow2020-06-18 16:29:17 -0400
commit0f8e5a146563d1f245f8f62cb931dc1e0b55de2f (patch)
tree1145873a1269aca9e259ceb0b14ce946f6f3cbfd /src/tests/core/host_timing.cpp
parentCore: Implement a Host Timer. (diff)
downloadyuzu-0f8e5a146563d1f245f8f62cb931dc1e0b55de2f.tar.gz
yuzu-0f8e5a146563d1f245f8f62cb931dc1e0b55de2f.tar.xz
yuzu-0f8e5a146563d1f245f8f62cb931dc1e0b55de2f.zip
Tests: Add base tests to host timing
Diffstat (limited to 'src/tests/core/host_timing.cpp')
-rw-r--r--src/tests/core/host_timing.cpp150
1 files changed, 150 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..ca9c8e50a
--- /dev/null
+++ b/src/tests/core/host_timing.cpp
@@ -0,0 +1,150 @@
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;
25static s64 lateness = 0;
26
27template <unsigned int IDX>
28void HostCallbackTemplate(u64 userdata, s64 nanoseconds_late) {
29 static_assert(IDX < CB_IDS.size(), "IDX out of range");
30 callbacks_ran_flags.set(IDX);
31 REQUIRE(CB_IDS[IDX] == userdata);
32 REQUIRE(CB_IDS[IDX] == CB_IDS[calls_order[expected_callback]]);
33 delays[IDX] = nanoseconds_late;
34 ++expected_callback;
35}
36
37static u64 callbacks_done = 0;
38
39struct ScopeInit final {
40 ScopeInit() {
41 core_timing.Initialize();
42 }
43 ~ScopeInit() {
44 core_timing.Shutdown();
45 }
46
47 Core::HostTiming::CoreTiming core_timing;
48};
49
50TEST_CASE("HostTiming[BasicOrder]", "[core]") {
51 ScopeInit guard;
52 auto& core_timing = guard.core_timing;
53 std::vector<std::shared_ptr<Core::HostTiming::EventType>> events;
54 events.resize(5);
55 events[0] =
56 Core::HostTiming::CreateEvent("callbackA", HostCallbackTemplate<0>);
57 events[1] =
58 Core::HostTiming::CreateEvent("callbackB", HostCallbackTemplate<1>);
59 events[2] =
60 Core::HostTiming::CreateEvent("callbackC", HostCallbackTemplate<2>);
61 events[3] =
62 Core::HostTiming::CreateEvent("callbackD", HostCallbackTemplate<3>);
63 events[4] =
64 Core::HostTiming::CreateEvent("callbackE", HostCallbackTemplate<4>);
65
66 expected_callback = 0;
67
68 core_timing.SyncPause(true);
69
70 u64 one_micro = 1000U;
71 for (std::size_t i = 0; i < events.size(); i++) {
72 u64 order = calls_order[i];
73 core_timing.ScheduleEvent(i*one_micro + 100U, events[order], CB_IDS[order]);
74 }
75 /// test pause
76 REQUIRE(callbacks_ran_flags.none());
77
78 core_timing.Pause(false); // No need to sync
79
80 while (core_timing.HasPendingEvents());
81
82 REQUIRE(callbacks_ran_flags.all());
83
84 for (std::size_t i = 0; i < delays.size(); i++) {
85 const double delay = static_cast<double>(delays[i]);
86 const double micro = delay / 1000.0f;
87 const double mili = micro / 1000.0f;
88 printf("HostTimer Pausing Delay[%zu]: %.3f %.6f\n", i, micro, mili);
89 }
90}
91
92#pragma optimize("", off)
93u64 TestTimerSpeed(Core::HostTiming::CoreTiming& core_timing) {
94 u64 start = core_timing.GetGlobalTimeNs().count();
95 u64 placebo = 0;
96 for (std::size_t i = 0; i < 1000; i++) {
97 placebo += core_timing.GetGlobalTimeNs().count();
98 }
99 u64 end = core_timing.GetGlobalTimeNs().count();
100 return (end - start);
101}
102#pragma optimize("", on)
103
104TEST_CASE("HostTiming[BasicOrderNoPausing]", "[core]") {
105 ScopeInit guard;
106 auto& core_timing = guard.core_timing;
107 std::vector<std::shared_ptr<Core::HostTiming::EventType>> events;
108 events.resize(5);
109 events[0] =
110 Core::HostTiming::CreateEvent("callbackA", HostCallbackTemplate<0>);
111 events[1] =
112 Core::HostTiming::CreateEvent("callbackB", HostCallbackTemplate<1>);
113 events[2] =
114 Core::HostTiming::CreateEvent("callbackC", HostCallbackTemplate<2>);
115 events[3] =
116 Core::HostTiming::CreateEvent("callbackD", HostCallbackTemplate<3>);
117 events[4] =
118 Core::HostTiming::CreateEvent("callbackE", HostCallbackTemplate<4>);
119
120 core_timing.SyncPause(true);
121 core_timing.SyncPause(false);
122
123 expected_callback = 0;
124
125 u64 start = core_timing.GetGlobalTimeNs().count();
126 u64 one_micro = 1000U;
127 for (std::size_t i = 0; i < events.size(); i++) {
128 u64 order = calls_order[i];
129 core_timing.ScheduleEvent(i*one_micro + 100U, events[order], CB_IDS[order]);
130 }
131 u64 end = core_timing.GetGlobalTimeNs().count();
132 const double scheduling_time = static_cast<double>(end - start);
133 const double timer_time = static_cast<double>(TestTimerSpeed(core_timing));
134
135 while (core_timing.HasPendingEvents());
136
137 REQUIRE(callbacks_ran_flags.all());
138
139 for (std::size_t i = 0; i < delays.size(); i++) {
140 const double delay = static_cast<double>(delays[i]);
141 const double micro = delay / 1000.0f;
142 const double mili = micro / 1000.0f;
143 printf("HostTimer No Pausing Delay[%zu]: %.3f %.6f\n", i, micro, mili);
144 }
145
146 const double micro = scheduling_time / 1000.0f;
147 const double mili = micro / 1000.0f;
148 printf("HostTimer No Pausing Scheduling Time: %.3f %.6f\n", micro, mili);
149 printf("HostTimer No Pausing Timer Time: %.3f %.6f\n", timer_time / 1000.f, timer_time / 1000000.f);
150}