File: TimerTest.cpp

package info (click to toggle)
spring 106.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 55,260 kB
  • sloc: cpp: 543,946; ansic: 44,800; python: 12,575; java: 12,201; awk: 5,889; sh: 1,796; asm: 1,546; xml: 655; perl: 405; php: 211; objc: 194; makefile: 76; sed: 2
file content (112 lines) | stat: -rw-r--r-- 3,607 bytes parent folder | download | duplicates (3)
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
112
//
#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;
}