forked from spring/spring
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTimerTest.cpp
More file actions
112 lines (81 loc) · 3.52 KB
/
TimerTest.cpp
File metadata and controls
112 lines (81 loc) · 3.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
//
#include <cstdio>
#include <cstdlib>
#include <thread>
#include "System/Misc/SpringTime.h"
#define GAME_SPEED_HZ 30
#define FRAME_TIME_MS (1000.0f / GAME_SPEED_HZ)
static unsigned int lastSimFrame = 0;
static unsigned int lastSimFrameRateUpdateFrame = 0;
static spring_time lastDrawFrameTime = spring_notime;
static spring_time lastSimFrameTime = spring_notime;
static spring_time lastSimFrameRateUpdateTime = spring_notime;
static float simFrameRate = 0.0f; // globalUnsynced->simFPS (undefined during first 30 sim-frames)
static float simFrameTimeOffset = 0.0f; // globalRendering->timeOffset
static float simSpeedFactor = 0.0f; // globalRendering->weightedSpeedFactor
static void NewSimFrame(unsigned int currSimFrame) {
if (currSimFrame > GAME_SPEED_HZ) {
printf("[%s] sf=%u fps=%f to=%f\n\n", __func__, currSimFrame, simFrameRate, simFrameTimeOffset);
}
lastSimFrame = currSimFrame;
lastSimFrameTime = spring_gettime();
}
static void GameUpdateUnsynced(unsigned int currSimFrame, unsigned int currDrawFrame) {
const spring_time currentTime = spring_gettime();
const float dt = (currentTime - lastSimFrameRateUpdateTime).toSecsf();
// update simFPS counter
if (dt >= 1.0f) {
simFrameRate = (currSimFrame - lastSimFrameRateUpdateFrame) / dt;
lastSimFrameRateUpdateTime = currentTime;
lastSimFrameRateUpdateFrame = currSimFrame;
}
simSpeedFactor = 0.001f * simFrameRate;
simFrameTimeOffset = (currentTime - lastSimFrameTime).toMilliSecsf() * simSpeedFactor;
}
static void GameDraw(unsigned int currSimFrame, unsigned int currDrawFrame) {
// do something useful that takes non-trivial time, eg. sleeping
// at ~5 milliseconds per draw-frame, rFPS would be at most ~200
// wake-up can vary and affects FPS too much, busy-loop instead
{
const spring_time currentTime = spring_gettime();
const spring_time wakeUpTime = currentTime + spring_time(1 + (random() % 5)); // MILLIseconds
while (spring_gettime() < wakeUpTime) {
}
}
const float currTimeOffset = simFrameTimeOffset;
static float lastTimeOffset = simFrameTimeOffset;
// do nothing first 30 frames
if (currSimFrame < GAME_SPEED_HZ)
return;
if (currTimeOffset < 0.0f)
printf("[%s] assert(timeOffset >= 0.0f) failed (SF=%u : DF=%u : TO=%f)\n", __func__, currSimFrame, currDrawFrame, currTimeOffset);
if (currTimeOffset > 1.0f)
printf("[%s] assert(timeOffset <= 1.0f) failed (SF=%u : DF=%u : TO=%f)\n", __func__, currSimFrame, currDrawFrame, currTimeOffset);
// test for monotonicity
if (currTimeOffset < lastTimeOffset)
printf("[%s] assert(timeOffset < lastTimeOffset) failed (SF=%u : DF=%u : CTO=%f LTO=%f)\n", __func__, currSimFrame, currDrawFrame, currTimeOffset, lastTimeOffset);
lastTimeOffset = currTimeOffset;
}
static void NewDrawFrame(unsigned int currSimFrame, unsigned int currDrawFrame) {
lastDrawFrameTime = spring_gettime();
GameUpdateUnsynced(currSimFrame, currDrawFrame);
GameDraw(currSimFrame, currDrawFrame);
}
static void TimerFunc(unsigned int N) {
printf("[%s][N=%u]\n\n", __func__, N);
lastDrawFrameTime = spring_gettime();
lastSimFrameTime = spring_gettime();
lastSimFrameRateUpdateTime = spring_gettime();
for (unsigned int sf = 0, df = 0; sf < N; /*no-op*/) {
NewDrawFrame(sf, df++);
if ((spring_gettime() - lastSimFrameTime).toMilliSecsf() > FRAME_TIME_MS) {
NewSimFrame(sf++);
}
}
}
int main(int argc, char** argv) {
srandom(time(nullptr));
std::thread timer = std::thread(std::bind(&TimerFunc, (argc >= 2)? atoi(argv[1]): (GAME_SPEED_HZ * 60 * 60)));
timer.join();
return 0;
}