36static std::mutex _sound_perf_lock;
37static std::atomic<bool> _sound_perf_pending;
38static std::vector<TimingMeasurement> _sound_perf_measurements;
78 explicit PerformanceData(
double expected_rate) : expected_rate(expected_rate), next_index(0), prev_index(0), num_valid(0) { }
83 this->durations[this->next_index] = end_time - start_time;
84 this->timestamps[this->next_index] = start_time;
85 this->prev_index = this->next_index;
86 this->next_index += 1;
94 this->timestamps[this->next_index] = this->acc_timestamp;
95 this->durations[this->next_index] = this->acc_duration;
96 this->prev_index = this->next_index;
97 this->next_index += 1;
101 this->acc_duration = 0;
102 this->acc_timestamp = start_time;
108 this->acc_duration += duration;
114 if (this->durations[this->prev_index] != INVALID_DURATION) {
115 this->timestamps[this->next_index] = start_time;
116 this->durations[this->next_index] = INVALID_DURATION;
117 this->prev_index = this->next_index;
118 this->next_index += 1;
120 this->num_valid += 1;
127 count = std::min(count, this->num_valid);
129 int first_point = this->prev_index - count;
134 for (
int i = first_point; i < first_point + count; i++) {
136 if (d != INVALID_DURATION) {
144 if (count == 0)
return 0;
152 int point = this->prev_index;
153 int last_point = this->next_index - this->num_valid;
167 while (point != last_point) {
169 if (this->durations[point] != INVALID_DURATION) {
170 total += last - this->timestamps[point];
173 last = this->timestamps[point];
179 if (total == 0 || count == 0)
return 0;
234 using namespace std::chrono;
235 return (
TimingMeasurement)time_point_cast<microseconds>(high_resolution_clock::now()).time_since_epoch().count();
257 for (uint e =
PFE_AI0; e <
PFE_MAX; e++) any_active |= _pf_data[e].num_valid > 0;
270 std::lock_guard lk(_sound_perf_lock);
271 if (_sound_perf_measurements.size() >= NUM_FRAMERATE_POINTS * 2)
return;
272 _sound_perf_measurements.push_back(this->start_time);
273 _sound_perf_measurements.push_back(end);
274 _sound_perf_pending.store(
true, std::memory_order_release);
369static const char * GetAIName(
int ai_index)
372 return Company::Get(ai_index)->ai_info->GetName().c_str();
376static constexpr NWidgetPart _framerate_window_widgets[] = {
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 void InsertDParams(uint n)
const
454 this->num_displayed = this->num_active;
463 if (this->small != this->
IsShaded()) {
482 if (this->small)
return;
499 sb->
SetCapacity(std::min(this->num_displayed, this->num_active));
506 case WID_FRW_CAPTION:
508 if (!this->small)
break;
510 this->rate_gameloop.InsertDParams(1);
511 this->speed_gameloop.InsertDParams(3);
514 case WID_FRW_RATE_GAMELOOP:
516 this->rate_gameloop.InsertDParams(1);
518 case WID_FRW_RATE_DRAWING:
520 this->rate_drawing.InsertDParams(1);
522 case WID_FRW_RATE_FACTOR:
523 this->speed_gameloop.InsertDParams(0);
525 case WID_FRW_INFO_DATA_POINTS:
534 case WID_FRW_RATE_GAMELOOP:
540 case WID_FRW_RATE_DRAWING:
546 case WID_FRW_RATE_FACTOR:
552 case WID_FRW_TIMES_NAMES: {
558 if (
_pf_data[
e].num_valid == 0)
continue;
567 size.width = std::max(size.width,
line_size.width);
572 case WID_FRW_TIMES_CURRENT:
573 case WID_FRW_TIMES_AVERAGE:
574 case WID_FRW_ALLOCSIZE: {
579 size.width = std::max(size.width,
item_size.width);
598 if (
_pf_data[
e].num_valid == 0)
continue;
602 values[
e].InsertDParams(0);
611 void DrawElementAllocationsColumn(
const Rect &r)
const
620 if (
_pf_data[
e].num_valid == 0)
continue;
651 case WID_FRW_TIMES_NAMES: {
658 if (
_pf_data[
e].num_valid == 0)
continue;
676 case WID_FRW_TIMES_CURRENT:
680 case WID_FRW_TIMES_AVERAGE:
684 case WID_FRW_ALLOCSIZE:
685 DrawElementAllocationsColumn(r);
693 case WID_FRW_TIMES_NAMES:
694 case WID_FRW_TIMES_CURRENT:
695 case WID_FRW_TIMES_AVERAGE: {
724 WDP_AUTO,
"framerate_display", 0, 0,
727 _framerate_window_widgets
732static constexpr NWidgetPart _frametime_graph_window_widgets[] = {
755 this->horizontal_scale = 4;
765 case WID_FGW_CAPTION:
779 if (widget == WID_FGW_GRAPH) {
807 static const std::initializer_list<ScaleDef>
hscales = {
815 if (
range <
sc.range) this->horizontal_scale =
sc.scale;
822 static const std::initializer_list<TimingMeasurement>
vscales = {
852 this->horizontal_scale = 4;
854 for (
int i = 1; i < num_valid; i++) {
872 if (count == 60) this->SelectHorizontalScale(
time_sum);
902 if (widget == WID_FGW_GRAPH) {
907 const int x_zero = r.right - (
int)this->graph_size.width;
908 const int x_max = r.right;
909 const int y_zero = r.top + (
int)this->graph_size.height;
910 const int y_max = r.top;
919 const uint
horz_div_scl = (this->horizontal_scale <= 20) ? 1 : 10;
1014static WindowDesc _frametime_graph_window_desc(
1015 WDP_AUTO,
"frametime_graph", 140, 90,
1018 _frametime_graph_window_widgets
1026 AllocateWindowDescFront<FramerateWindow>(_framerate_display_desc, 0);
1032 if (elem < PFE_FIRST || elem >=
PFE_MAX)
return;
1033 AllocateWindowDescFront<FrametimeGraphWindow>(_frametime_graph_window_desc, elem,
true);
1043 IConsolePrint(TC_SILVER,
"Based on num. data points: {} {} {}", count1, count2, count3);
1045 static const std::array<std::string_view, PFE_MAX> MEASUREMENT_NAMES = {
1047 " GL station ticks",
1049 " GL road vehicle ticks",
1051 " GL aircraft ticks",
1052 " GL landscape ticks",
1053 " GL link graph delays",
1055 " Viewport drawing",
1058 "AI/GS scripts total",
1061 std::string ai_name_buf;
1063 bool printed_anything =
false;
1067 if (pf.num_valid == 0)
continue;
1068 IConsolePrint(TC_GREEN,
"{} rate: {:.2f}fps (expected: {:.2f}fps)",
1069 MEASUREMENT_NAMES[e],
1072 printed_anything =
true;
1077 if (pf.num_valid == 0)
continue;
1078 std::string_view name;
1080 name = MEASUREMENT_NAMES[e];
1082 ai_name_buf = fmt::format(
"AI {} {}", e -
PFE_AI0 + 1, GetAIName(e -
PFE_AI0));
1085 IConsolePrint(TC_LIGHT_BLUE,
"{} times: {:.2f}ms {:.2f}ms {:.2f}ms",
1087 pf.GetAverageDurationMilliseconds(count1),
1088 pf.GetAverageDurationMilliseconds(count2),
1089 pf.GetAverageDurationMilliseconds(count3));
1090 printed_anything =
true;
1093 if (!printed_anything) {
1107 if (_sound_perf_pending.load(std::memory_order_acquire)) {
1108 std::lock_guard lk(_sound_perf_lock);
1109 for (
size_t i = 0; i < _sound_perf_measurements.size(); i += 2) {
1112 _sound_perf_measurements.clear();
1113 _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.
@ 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.
@ FS_SMALL
Index of the small font in the font tables.
@ FS_NORMAL
Index of the normal font in the font tables.
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.
This file contains all sprite-related enums and defines.
Functions related to low-level strings.
void SetDParam(size_t n, uint64_t v)
Set a string parameter v at index n in the global string parameter array.
void SetDParamStr(size_t n, const char *str)
This function is used to "bind" a C string to a OpenTTD dparam slot.
void SetDParamMaxDigits(size_t n, uint count, FontSize size)
Set DParam n to 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(size_t 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.
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.
IntervalTimer< TimerWindow > update_interval
Update the window on a regular interval.
void DrawElementTimesColumn(const Rect &r, StringID heading_str, const CachedDecimal *values) const
Render a column of formatted average durations.
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.
void SetStringParameters(WidgetID widget) const override
Initialize string parameters for a widget.
void OnRealtimeTick(uint delta_ms) override
Called periodically.
CachedDecimal rate_gameloop
cached game loop tick rate
CachedDecimal times_longterm[PFE_MAX]
cached long term average times
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
CachedDecimal times_shortterm[PFE_MAX]
cached short term average times
int horizontal_scale
number of half-second units horizontally
void SetStringParameters(WidgetID widget) const override
Initialize string parameters for a widget.
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.
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(size_t index)
Returns Titem with given index.
Specification of a rectangle with absolute coordinates of all edges.
High level window description.
Data structure for an opened window.
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.
int32_t WindowNumber
Number to differentiate different windows of the same class.
@ WC_FRAMETIME_GRAPH
Frame time graph; Window numbers:
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
@ WC_FRAMERATE_DISPLAY
Framerate display; Window numbers: