1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#pragma once
4
5#include "Prerequisites/BsPrerequisitesUtil.h"
6#include "Utility/BsModule.h"
7
8namespace bs
9{
10 /** @addtogroup General
11 * @{
12 */
13
14 /**
15 * Manages all time related functionality.
16 *
17 * @note Sim thread only unless where specified otherwise.
18 */
19 class BS_UTILITY_EXPORT Time : public Module<Time>
20 {
21 public:
22 Time();
23 ~Time();
24
25 /**
26 * Gets the time elapsed since application start. Only gets updated once per frame.
27 *
28 * @return The time since application start, in seconds.
29 */
30 float getTime() const { return mTimeSinceStart; }
31
32 /**
33 * Gets the time elapsed since application start. Only gets updated once per frame.
34 *
35 * @return The time since application start, in miliseconds.
36 */
37 UINT64 getTimeMs() const { return mTimeSinceStartMs; }
38
39 /**
40 * Gets the time since last frame was executed. Only gets updated once per frame.
41 *
42 * @return Time since last frame was executed, in seconds.
43 */
44 float getFrameDelta() const { return mFrameDelta; }
45
46 /** Returns the step (in seconds) between fixed frame updates. */
47 float getFixedFrameDelta() const { return (float)(mFixedStep * MICROSEC_TO_SEC); }
48
49 /** Returns the time (in seconds) the latest frame has started. */
50 float getLastFrameTime() const { return (float)(mLastFrameTime * MICROSEC_TO_SEC); }
51
52 /** Returns the time (in seconds) the latest fixed update has started. */
53 float getLastFixedUpdateTime() const { return (float)(mLastFixedUpdateTime * MICROSEC_TO_SEC); }
54
55 /**
56 * Returns the sequential index of the current frame. First frame is 0.
57 *
58 * @return The current frame.
59 *
60 * @note Thread safe, but only counts sim thread frames.
61 */
62 UINT64 getFrameIdx() const { return mCurrentFrame.load(); }
63
64 /**
65 * Returns the precise time since application start, in microseconds. Unlike other time methods this is not only
66 * updated every frame, but will return exact time at the moment it is called.
67 *
68 * @return Time in microseconds.
69 *
70 * @note
71 * You will generally only want to use this for performance measurements and similar. Use non-precise methods in
72 * majority of code as it is useful to keep the time value equal in all methods during a single frame.
73 */
74 UINT64 getTimePrecise() const;
75
76 /**
77 * Gets the time at which the application was started, counting from system start.
78 *
79 * @return The time since system to application start, in milliseconds.
80 */
81 UINT64 getStartTimeMs() const { return mAppStartTime; }
82
83 /**
84 * Gets the current date and time in textual form.
85 *
86 * @param[in] isUTC Outputs the date and time in Coordinated Universal Time, otherwise in local time.
87 *
88 * @return A String containing the current date and time.
89 *
90 * @note
91 * Thread safe.
92 * The output format is [DayOfWeek], [Month] [NumericalDate], [NumericalYear] [HH]::[MM]::[SS].
93 */
94 String getCurrentDateTimeString(bool isUTC);
95
96 /**
97 * Gets the current time in textual form
98 *
99 * @param[in] isUTC Outputs the time in Coordinated Universal Time, otherwise in local time.
100 *
101 * @return A String containing the current time.
102 *
103 * @note
104 * Thread safe.
105 * The output format is [HH]::[MM]::[SS].
106 */
107 String getCurrentTimeString(bool isUTC);
108
109 /**
110 * Gets the date and time where the application has been started in textual form.
111 *
112 * @param[in] isUTC Outputs the date and time in Coordinated Universal Time, otherwise in local time.
113 *
114 * @return A String containing the application startup date and time.
115 *
116 * @note
117 * Thread safe.
118 * The output format is [DayOfWeek], [Month] [NumericalDate], [NumericalYear] [HH]::[MM]::[SS].
119 */
120 String getAppStartUpDateString(bool isUTC);
121
122 /** @name Internal
123 * @{
124 */
125
126 /** Called every frame. Should only be called by Application. */
127 void _update();
128
129 /**
130 * Calculates the number of fixed update iterations required and their step size. Values depend on the current
131 * time and previous calls to _advanceFixedUpdate().;
132 *
133 * @param[out] step Duration of the fixed step in microseconds. In most cases this is the same duration as
134 * the fixed time delta, but in the cases where frame is taking a very long time the step
135 * might be increased to avoid a large number of fixed updates per frame.
136 * @return Returns the number of fixed frame updates to execute (each of @p step duration). In most
137 * cases this will be either 1 or 0, or a larger amount of frames are taking a long time
138 * to execute (longer than a multiple of fixed frame step).
139 */
140 UINT32 _getFixedUpdateStep(UINT64& step);
141
142 /**
143 * Advances the fixed update timers by @p step microseconds. Should be called once for each iteration as returned
144 * by _getFixedUpdateStep(), per frame.
145 */
146 void _advanceFixedUpdate(UINT64 step);
147
148 /** @} */
149
150 /** Multiply with time in microseconds to get a time in seconds. */
151 static const double MICROSEC_TO_SEC;
152 private:
153 /** Maximum number of fixed updates that can ever be accumulated. */
154 static constexpr UINT32 MAX_ACCUM_FIXED_UPDATES = 200;
155
156 /** Determines how many new fixed updates are regenerated per frame. */
157 static constexpr UINT32 NEW_FIXED_UPDATES_PER_FRAME = 4;
158
159 float mFrameDelta = 0.0f; /**< Frame delta in seconds */
160 float mTimeSinceStart = 0.0f; /**< Time since start in seconds */
161 UINT64 mTimeSinceStartMs = 0u;
162 bool mFirstFrame = true;
163
164 UINT64 mAppStartTime = 0u; /**< Time the application started, in microseconds */
165 UINT64 mLastFrameTime = 0u; /**< Time since last runOneFrame call, In microseconds */
166 std::atomic<unsigned long> mCurrentFrame{0UL};
167
168 // Fixed update
169 UINT64 mFixedStep = 16666; // 60 times a second in microseconds
170 UINT64 mLastFixedUpdateTime = 0;
171 bool mFirstFixedFrame = true;
172 UINT32 mNumRemainingFixedUpdates = MAX_ACCUM_FIXED_UPDATES;
173
174 std::time_t mAppStartUpDate;
175
176 Timer* mTimer;
177 };
178
179 /** Easier way to access the Time module. */
180 BS_UTILITY_EXPORT Time& gTime();
181
182 /** @} */
183}
184