33#include "table/strings.h"
37static std::mutex _sound_perf_lock;
38static std::atomic<bool> _sound_perf_pending;
39static std::vector<TimingMeasurement> _sound_perf_measurements;
56 std::array<TimingMeasurement, NUM_FRAMERATE_POINTS> durations{};
58 std::array<TimingMeasurement, NUM_FRAMERATE_POINTS> timestamps{};
60 double expected_rate = 0;
84 this->durations[this->next_index] = end_time - start_time;
85 this->timestamps[this->next_index] = start_time;
86 this->prev_index = this->next_index;
87 this->next_index += 1;
95 this->timestamps[this->next_index] = this->acc_timestamp;
96 this->durations[this->next_index] = this->acc_duration;
97 this->prev_index = this->next_index;
98 this->next_index += 1;
102 this->acc_duration = 0;
103 this->acc_timestamp = start_time;
109 this->acc_duration += duration;
115 if (this->durations[this->prev_index] != INVALID_DURATION) {
116 this->timestamps[this->next_index] = start_time;
117 this->durations[this->next_index] = INVALID_DURATION;
118 this->prev_index = this->next_index;
119 this->next_index += 1;
121 this->num_valid += 1;
128 count = std::min(count, this->num_valid);
130 int first_point = this->prev_index - count;
135 for (
int i = first_point; i < first_point + count; i++) {
137 if (d != INVALID_DURATION) {
145 if (count == 0)
return 0;
153 int point = this->prev_index;
154 int last_point = this->next_index - this->num_valid;
168 while (point != last_point) {
170 if (this->durations[point] != INVALID_DURATION) {
171 total += last - this->timestamps[point];
174 last = this->timestamps[point];
180 if (total == 0 || count == 0)
return 0;
235 using namespace std::chrono;
236 return (
TimingMeasurement)time_point_cast<microseconds>(high_resolution_clock::now()).time_since_epoch().count();
258 for (uint e =
PFE_AI0; e <
PFE_MAX; e++) any_active |= _pf_data[e].num_valid > 0;
271 std::lock_guard lk(_sound_perf_lock);
272 if (_sound_perf_measurements.size() >= NUM_FRAMERATE_POINTS * 2)
return;
273 _sound_perf_measurements.push_back(this->start_time);
274 _sound_perf_measurements.push_back(end);
275 _sound_perf_pending.store(
true, std::memory_order_release);
370static const char * GetAIName(
int ai_index)
373 return Company::Get(ai_index)->ai_info->GetName().c_str();
377static constexpr NWidgetPart _framerate_window_widgets[] = {
412 int num_displayed = 0;
418 inline void SetRate(
double value,
double target)
422 this->value = (
uint32_t)(value * 100);
426 inline void SetTime(
double value,
double target)
430 this->value = (
uint32_t)(value * 100);
434 inline uint32_t GetValue()
const {
return this->value; }
435 inline uint32_t GetDecimals()
const {
return 2; }
450 this->num_displayed = this->num_active;
484 sb->
SetCapacity(std::min(this->num_displayed, this->num_active));
491 case WID_FRW_CAPTION:
497 case WID_FRW_RATE_GAMELOOP:
500 case WID_FRW_RATE_DRAWING:
503 case WID_FRW_RATE_FACTOR:
506 case WID_FRW_INFO_DATA_POINTS:
517 case WID_FRW_RATE_GAMELOOP:
520 case WID_FRW_RATE_DRAWING:
523 case WID_FRW_RATE_FACTOR:
527 case WID_FRW_TIMES_NAMES: {
533 if (
_pf_data[
e].num_valid == 0)
continue;
540 size.width = std::max(size.width,
line_size.width);
545 case WID_FRW_TIMES_CURRENT:
546 case WID_FRW_TIMES_AVERAGE:
547 case WID_FRW_ALLOCSIZE: {
550 size.width = std::max(size.width,
item_size.width);
569 if (
_pf_data[
e].num_valid == 0)
continue;
581 void DrawElementAllocationsColumn(
const Rect &r)
const
590 if (
_pf_data[
e].num_valid == 0)
continue;
616 case WID_FRW_TIMES_NAMES: {
623 if (
_pf_data[
e].num_valid == 0)
continue;
639 case WID_FRW_TIMES_CURRENT:
643 case WID_FRW_TIMES_AVERAGE:
647 case WID_FRW_ALLOCSIZE:
648 DrawElementAllocationsColumn(r);
656 case WID_FRW_TIMES_NAMES:
657 case WID_FRW_TIMES_CURRENT:
658 case WID_FRW_TIMES_AVERAGE: {
687 WDP_AUTO,
"framerate_display", 0, 0,
690 _framerate_window_widgets
695static constexpr NWidgetPart _frametime_graph_window_widgets[] = {
724 case WID_FGW_CAPTION:
737 if (widget == WID_FGW_GRAPH) {
763 static const std::initializer_list<ScaleDef>
hscales = {
771 if (
range <
sc.range) this->horizontal_scale =
sc.scale;
778 static const std::initializer_list<TimingMeasurement>
vscales = {
808 this->horizontal_scale = 4;
810 for (
int i = 1; i < num_valid; i++) {
828 if (count == 60) this->SelectHorizontalScale(
time_sum);
848 template <
typename T>
858 if (widget == WID_FGW_GRAPH) {
864 const int x_max = r.right;
866 const int y_max = r.top;
875 const uint
horz_div_scl = (this->horizontal_scale <= 20) ? 1 : 10;
973static WindowDesc _frametime_graph_window_desc(
974 WDP_AUTO,
"frametime_graph", 140, 90,
977 _frametime_graph_window_widgets
985 AllocateWindowDescFront<FramerateWindow>(_framerate_display_desc, 0);
991 if (elem < PFE_FIRST || elem >=
PFE_MAX)
return;
992 AllocateWindowDescFront<FrametimeGraphWindow>(_frametime_graph_window_desc, elem);
1002 IConsolePrint(TC_SILVER,
"Based on num. data points: {} {} {}", count1, count2, count3);
1004 static const std::array<std::string_view, PFE_MAX> MEASUREMENT_NAMES = {
1006 " GL station ticks",
1008 " GL road vehicle ticks",
1010 " GL aircraft ticks",
1011 " GL landscape ticks",
1012 " GL link graph delays",
1014 " Viewport drawing",
1017 "AI/GS scripts total",
1020 std::string ai_name_buf;
1022 bool printed_anything =
false;
1026 if (pf.num_valid == 0)
continue;
1027 IConsolePrint(TC_GREEN,
"{} rate: {:.2f}fps (expected: {:.2f}fps)",
1028 MEASUREMENT_NAMES[e],
1031 printed_anything =
true;
1036 if (pf.num_valid == 0)
continue;
1037 std::string_view name;
1039 name = MEASUREMENT_NAMES[e];
1041 ai_name_buf = fmt::format(
"AI {} {}", e -
PFE_AI0 + 1, GetAIName(e -
PFE_AI0));
1044 IConsolePrint(TC_LIGHT_BLUE,
"{} times: {:.2f}ms {:.2f}ms {:.2f}ms",
1046 pf.GetAverageDurationMilliseconds(count1),
1047 pf.GetAverageDurationMilliseconds(count2),
1048 pf.GetAverageDurationMilliseconds(count3));
1049 printed_anything =
true;
1052 if (!printed_anything) {
1066 if (_sound_perf_pending.load(std::memory_order_acquire)) {
1067 std::lock_guard lk(_sound_perf_lock);
1068 for (
size_t i = 0; i < _sound_perf_measurements.size(); i += 2) {
1071 _sound_perf_measurements.clear();
1072 _sound_perf_pending.store(
false, std::memory_order_relaxed);
AIInfo keeps track of all information of an AI, like Author, Description, ...
The AIInstance tracks an AI.
static class GameInstance * GetInstance()
Get the current active instance.
An interval timer will fire every interval, and will continue to fire until it is deleted.
Definition of stuff that is very close to a company, like the company struct itself.
void IConsolePrint(TextColour colour_code, const std::string &string)
Handle the printing of text entered into the console or redirected there by any other means.
Console functions used outside of the console code.
Globally used console related types.
static const TextColour CC_ERROR
Colour for error lines.
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
void ShowFramerateWindow()
Open the general framerate window.
static TimingMeasurement GetPerformanceTimer()
Return a timestamp with TIMESTAMP_PRECISION ticks per second precision.
void ProcessPendingPerformanceMeasurements()
This drains the PFE_SOUND measurement data queue into _pf_data.
void ShowFrametimeGraphWindow(PerformanceElement elem)
Open a graph window for a performance element.
void ConPrintFramerate()
Print performance statistics to game console.
Types for recording game performance data.
PerformanceElement
Elements of game performance that can be measured.
@ PFE_AI6
AI execution for player slot 7.
@ PFE_AI1
AI execution for player slot 2.
@ PFE_GAMELOOP
Speed of gameloop processing.
@ PFE_AI9
AI execution for player slot 10.
@ PFE_GL_SHIPS
Time spent processing ships.
@ PFE_AI3
AI execution for player slot 4.
@ PFE_AI4
AI execution for player slot 5.
@ PFE_AI11
AI execution for player slot 12.
@ PFE_AI8
AI execution for player slot 9.
@ PFE_GAMESCRIPT
Game script execution.
@ PFE_VIDEO
Speed of painting drawn video buffer.
@ PFE_GL_LINKGRAPH
Time spent waiting for link graph background jobs.
@ PFE_AI13
AI execution for player slot 14.
@ PFE_AI7
AI execution for player slot 8.
@ PFE_GL_AIRCRAFT
Time spent processing aircraft.
@ PFE_GL_ECONOMY
Time spent processing cargo movement.
@ PFE_AI0
AI execution for player slot 1.
@ PFE_DRAWING
Speed of drawing world and GUI.
@ PFE_AI12
AI execution for player slot 13.
@ PFE_AI2
AI execution for player slot 3.
@ PFE_AI10
AI execution for player slot 11.
@ PFE_GL_LANDSCAPE
Time spent processing other world features.
@ PFE_GL_ROADVEHS
Time spend processing road vehicles.
@ PFE_GL_TRAINS
Time spent processing trains.
@ PFE_MAX
End of enum, must be last.
@ PFE_ALLSCRIPTS
Sum of all GS/AI scripts.
@ PFE_SOUND
Speed of mixing audio samples.
@ PFE_DRAWWORLD
Time spent drawing world viewports in GUI.
@ PFE_AI14
AI execution for player slot 15.
@ PFE_AI5
AI execution for player slot 6.
uint64_t TimingMeasurement
Type used to hold a performance timing measurement.
Base functions for all Games.
The GameInstance tracks games.
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
int DrawString(int left, int right, int top, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectMode mode)
Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen.
Functions related to the gfx engine.
@ FS_SMALL
Index of the small font in the font tables.
@ FS_NORMAL
Index of the normal font in the font tables.
@ SA_LEFT
Left align the text.
@ SA_RIGHT
Right align the text (must be a single bit).
@ SA_FORCE
Force the alignment, i.e. don't swap for RTL languages.
@ SA_CENTER
Center both horizontally and vertically.
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
@ TC_IS_PALETTE_COLOUR
Colour value is already a real palette colour index, not an index of a StringColour.
static const uint MILLISECONDS_PER_TICK
The number of milliseconds per game tick.
void SetDirty() const
Mark entire window as dirty (in need of re-paint)
const TimingMeasurement TIMESTAMP_PRECISION
Units a second is divided into in performance measurements
static const double GL_RATE
Game loop rate, cycles per second
const int NUM_FRAMERATE_POINTS
Number of data points to keep in buffer for each performance measurement.
PerformanceData _pf_data[PFE_MAX]
Storage for all performance element measurements.
size_t GetSoundPoolAllocatedMemory()
Get size of memory allocated to sound effects.
Functions related to NewGRF provided sounds.
static const uint8_t PC_DARK_GREY
Dark grey palette colour.
static const uint8_t PC_BLACK
Black palette colour.
static const uint8_t PC_DARK_RED
Dark red palette colour.
A number of safeguards to prevent using unsafe methods.
ClientSettings _settings_client
The current settings for this game.
Functions related to low-level strings.
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
uint64_t GetParamMaxDigits(uint count, FontSize size)
Get some number that is suitable for string size computations.
Functions related to OTTD's strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
GUISettings gui
settings related to the GUI
static bool IsValidAiID(auto index)
Is this company a valid company, controlled by the computer (a NoAI program)?
Dimensions (a width and height) of a rectangle in 2D.
void OnResize() override
Called after the window got resized.
void DrawElementTimesColumn(const Rect &r, StringID heading_str, std::span< const CachedDecimal > values) const
Render a column of formatted average durations.
CachedDecimal rate_drawing
cached drawing frame rate
void UpdateWidgetSize(WidgetID widget, Dimension &size, const Dimension &padding, Dimension &fill, Dimension &resize) override
Update size and resize step of a widget in the window.
std::array< CachedDecimal, PFE_MAX > times_longterm
cached long term average times
std::array< CachedDecimal, PFE_MAX > times_shortterm
cached short term average times
IntervalTimer< TimerWindow > update_interval
Update the window on a regular interval.
CachedDecimal speed_gameloop
cached game loop speed factor
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
CachedDecimal rate_gameloop
cached game loop tick rate
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
static constexpr int MIN_ELEMENTS
smallest number of elements to display
int horizontal_scale
number of half-second units horizontally
void OnRealtimeTick(uint delta_ms) override
Called periodically.
void UpdateScale()
Recalculate the graph scaling factors based on current recorded data.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
IntervalTimer< TimerWindow > update_interval
Update the scaling on a regular interval.
Dimension graph_size
size of the main graph area (excluding axis labels)
PerformanceElement element
what element this window renders graph for
void UpdateWidgetSize(WidgetID widget, Dimension &size, const Dimension &padding, Dimension &fill, Dimension &resize) override
Update size and resize step of a widget in the window.
static T Scinterlate(T dst_min, T dst_max, T src_min, T src_max, T value)
Scale and interpolate a value from a source range into a destination range.
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
int vertical_scale
number of TIMESTAMP_PRECISION units vertically
uint16_t refresh_rate
How often we refresh the screen (time between draw-ticks).
Coordinates of a point in 2D.
static Titem * Get(auto index)
Returns Titem with given index.
Specification of a rectangle with absolute coordinates of all edges.
High level window description.
Number to differentiate different windows of the same class.
Data structure for an opened window.
virtual std::string GetWidgetString(WidgetID widget, StringID stringid) const
Get the raw string for a widget.
ResizeInfo resize
Resize information.
int scale
Scale of this window – used to determine how to resize.
bool IsShaded() const
Is window shaded currently?
const NWID * GetWidget(WidgetID widnum) const
Get the nested widget with number widnum from the nested widget tree.
void InitNested(WindowNumber number=0)
Perform complete initialization of the Window with nested widgets, to allow use.
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition of Interval and OneShot timers.
Definition of the Window system.
void ResizeWindow(Window *w, int delta_x, int delta_y, bool clamp_to_screen, bool schedule_resize)
Resize the window.
Window functions not directly related to making/drawing windows.
Functions, definitions and such used only by the GUI.
@ WDP_AUTO
Find a place automatically.
@ WC_FRAMETIME_GRAPH
Frame time graph; Window numbers:
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
@ WC_FRAMERATE_DISPLAY
Framerate display; Window numbers: