File: TimerTest.cpp

package info (click to toggle)
spring 103.0%2Bdfsg2-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 43,720 kB
  • ctags: 63,685
  • sloc: cpp: 368,283; ansic: 33,988; python: 12,417; java: 12,203; awk: 5,879; sh: 1,846; xml: 655; perl: 405; php: 211; objc: 194; makefile: 77; sed: 2
file content (118 lines) | stat: -rw-r--r-- 4,024 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
113
114
115
116
117
118
// ldd libboost_chrono.so.* --> must be linked against librt (for nanosecond-precision timer) which must be present
// g++  -Wall -Wextra -Wno-unused -O2  -o tst TimerTest.cpp  -I ../../../rts/  -lboost_system -lboost_thread -lboost_chrono {-lrt}
//
#include <cstdio>
#include <cstdlib>
#include <boost/thread.hpp>
#include "System/Misc/SpringTime.h"

#define GAME_SPEED_HZ 30
#define FRAME_TIME_MS (1000.0f / GAME_SPEED_HZ)
// #define SLEEP_DRAW

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", __FUNCTION__, 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
	{
	#ifdef SLEEP_DRAW
		boost::this_thread::sleep(boost::posix_time::milliseconds(1 + (random() % 5)));
	#else
		const spring_time currentTime = spring_gettime();
		const spring_time wakeUpTime = currentTime + spring_time(1 + (random() % 5)); // MILLIseconds

		while (spring_gettime() < wakeUpTime) {
		}
	#endif
	}

	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", __FUNCTION__, currSimFrame, currDrawFrame, currTimeOffset);
	if (currTimeOffset > 1.0f)
		printf("[%s] assert(timeOffset <= 1.0f) failed (SF=%u : DF=%u : TO=%f)\n", __FUNCTION__, currSimFrame, currDrawFrame, currTimeOffset);

	// test for monotonicity
	if (currTimeOffset < lastTimeOffset)
		printf("[%s] assert(timeOffset < lastTimeOffset) failed (SF=%u : DF=%u : CTO=%f LTO=%f)\n", __FUNCTION__, 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", __FUNCTION__, 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(NULL));

	boost::thread timer = boost::thread(boost::bind(&TimerFunc, (argc >= 2)? atoi(argv[1]): (GAME_SPEED_HZ * 60 * 60)));
	timer.join();
	return 0;
}