Merge remote-tracking branch 'upstream/master' into 13.0

This commit is contained in:
dP
2023-01-19 04:08:55 +04:00
336 changed files with 13062 additions and 8849 deletions

View File

@@ -25,8 +25,16 @@
#include "game/game_instance.hpp"
#include "widgets/framerate_widget.h"
#include <atomic>
#include <mutex>
#include <vector>
#include "safeguards.h"
static std::mutex _sound_perf_lock;
static std::atomic<bool> _sound_perf_pending;
static std::vector<TimingMeasurement> _sound_perf_measurements;
/**
* Private declarations for performance measurement implementation
@@ -251,6 +259,20 @@ PerformanceMeasurer::~PerformanceMeasurer()
return;
}
}
if (this->elem == PFE_SOUND) {
/* PFE_SOUND measurements are made from the mixer thread.
* _pf_data cannot be concurrently accessed from the mixer thread
* and the main thread, so store the measurement results in a
* mutex-protected queue which is drained by the main thread.
* See: ProcessPendingPerformanceMeasurements() */
TimingMeasurement end = GetPerformanceTimer();
std::lock_guard lk(_sound_perf_lock);
if (_sound_perf_measurements.size() >= NUM_FRAMERATE_POINTS * 2) return;
_sound_perf_measurements.push_back(this->start_time);
_sound_perf_measurements.push_back(end);
_sound_perf_pending.store(true, std::memory_order_release);
return;
}
_pf_data[this->elem].Add(this->start_time, GetPerformanceTimer());
}
@@ -358,7 +380,7 @@ static const NWidgetPart _framerate_window_widgets[] = {
NWidget(WWT_STICKYBOX, COLOUR_GREY),
EndContainer(),
NWidget(WWT_PANEL, COLOUR_GREY),
NWidget(NWID_VERTICAL), SetPadding(6), SetPIP(0, 3, 0),
NWidget(NWID_VERTICAL), SetPadding(WidgetDimensions::unscaled.frametext), SetPIP(0, WidgetDimensions::unscaled.vsep_normal, 0),
NWidget(WWT_TEXT, COLOUR_GREY, WID_FRW_RATE_GAMELOOP), SetDataTip(STR_FRAMERATE_RATE_GAMELOOP, STR_FRAMERATE_RATE_GAMELOOP_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
NWidget(WWT_TEXT, COLOUR_GREY, WID_FRW_RATE_DRAWING), SetDataTip(STR_FRAMERATE_RATE_BLITTER, STR_FRAMERATE_RATE_BLITTER_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
NWidget(WWT_TEXT, COLOUR_GREY, WID_FRW_RATE_FACTOR), SetDataTip(STR_FRAMERATE_SPEED_FACTOR, STR_FRAMERATE_SPEED_FACTOR_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
@@ -366,8 +388,8 @@ static const NWidgetPart _framerate_window_widgets[] = {
EndContainer(),
NWidget(NWID_HORIZONTAL),
NWidget(WWT_PANEL, COLOUR_GREY),
NWidget(NWID_VERTICAL), SetPadding(6), SetPIP(0, 3, 0),
NWidget(NWID_HORIZONTAL), SetPIP(0, 8, 0),
NWidget(NWID_VERTICAL), SetPadding(WidgetDimensions::unscaled.frametext), SetPIP(0, WidgetDimensions::unscaled.vsep_wide, 0),
NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_wide, 0),
NWidget(WWT_EMPTY, COLOUR_GREY, WID_FRW_TIMES_NAMES), SetScrollbar(WID_FRW_SCROLLBAR),
NWidget(WWT_EMPTY, COLOUR_GREY, WID_FRW_TIMES_CURRENT), SetScrollbar(WID_FRW_SCROLLBAR),
NWidget(WWT_EMPTY, COLOUR_GREY, WID_FRW_TIMES_AVERAGE), SetScrollbar(WID_FRW_SCROLLBAR),
@@ -425,7 +447,6 @@ struct FramerateWindow : Window {
CachedDecimal times_shortterm[PFE_MAX]; ///< cached short term average times
CachedDecimal times_longterm[PFE_MAX]; ///< cached long term average times
static constexpr int VSPACING = 3; ///< space between column heading and values
static constexpr int MIN_ELEMENTS = 5; ///< smallest number of elements to display
FramerateWindow(WindowDesc *desc, WindowNumber number) : Window(desc)
@@ -545,7 +566,7 @@ struct FramerateWindow : Window {
case WID_FRW_TIMES_NAMES: {
size->width = 0;
size->height = FONT_HEIGHT_NORMAL + VSPACING + MIN_ELEMENTS * FONT_HEIGHT_NORMAL;
size->height = FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_normal + MIN_ELEMENTS * FONT_HEIGHT_NORMAL;
resize->width = 0;
resize->height = FONT_HEIGHT_NORMAL;
for (PerformanceElement e : DISPLAY_ORDER_PFE) {
@@ -571,7 +592,7 @@ struct FramerateWindow : Window {
SetDParam(1, 2);
Dimension item_size = GetStringBoundingBox(STR_FRAMERATE_MS_GOOD);
size->width = std::max(size->width, item_size.width);
size->height += FONT_HEIGHT_NORMAL * MIN_ELEMENTS + VSPACING;
size->height += FONT_HEIGHT_NORMAL * MIN_ELEMENTS + WidgetDimensions::scaled.vsep_normal;
resize->width = 0;
resize->height = FONT_HEIGHT_NORMAL;
break;
@@ -587,7 +608,7 @@ struct FramerateWindow : Window {
int drawable = this->num_displayed;
int y = r.top;
DrawString(r.left, r.right, y, heading_str, TC_FROMSTRING, SA_CENTER, true);
y += FONT_HEIGHT_NORMAL + VSPACING;
y += FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_normal;
for (PerformanceElement e : DISPLAY_ORDER_PFE) {
if (_pf_data[e].num_valid == 0) continue;
if (skip > 0) {
@@ -609,7 +630,7 @@ struct FramerateWindow : Window {
int drawable = this->num_displayed;
int y = r.top;
DrawString(r.left, r.right, y, STR_FRAMERATE_MEMORYUSE, TC_FROMSTRING, SA_CENTER, true);
y += FONT_HEIGHT_NORMAL + VSPACING;
y += FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_normal;
for (PerformanceElement e : DISPLAY_ORDER_PFE) {
if (_pf_data[e].num_valid == 0) continue;
if (skip > 0) {
@@ -641,7 +662,7 @@ struct FramerateWindow : Window {
const Scrollbar *sb = this->GetScrollbar(WID_FRW_SCROLLBAR);
uint16 skip = sb->GetPosition();
int drawable = this->num_displayed;
int y = r.top + FONT_HEIGHT_NORMAL + VSPACING; // first line contains headings in the value columns
int y = r.top + FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_normal; // first line contains headings in the value columns
for (PerformanceElement e : DISPLAY_ORDER_PFE) {
if (_pf_data[e].num_valid == 0) continue;
if (skip > 0) {
@@ -683,7 +704,7 @@ struct FramerateWindow : Window {
case WID_FRW_TIMES_AVERAGE: {
/* Open time graph windows when clicking detail measurement lines */
const Scrollbar *sb = this->GetScrollbar(WID_FRW_SCROLLBAR);
int line = sb->GetScrolledRowFromWidget(pt.y, this, widget, VSPACING + FONT_HEIGHT_NORMAL);
int line = sb->GetScrolledRowFromWidget(pt.y, this, widget, WidgetDimensions::scaled.vsep_normal + FONT_HEIGHT_NORMAL);
if (line != INT_MAX) {
line++;
/* Find the visible line that was clicked */
@@ -703,7 +724,7 @@ struct FramerateWindow : Window {
void OnResize() override
{
auto *wid = this->GetWidget<NWidgetResizeBase>(WID_FRW_TIMES_NAMES);
this->num_displayed = (wid->current_y - wid->min_y - VSPACING) / FONT_HEIGHT_NORMAL - 1; // subtract 1 for headings
this->num_displayed = (wid->current_y - wid->min_y - WidgetDimensions::scaled.vsep_normal) / FONT_HEIGHT_NORMAL - 1; // subtract 1 for headings
this->GetScrollbar(WID_FRW_SCROLLBAR)->SetCapacity(this->num_displayed);
}
};
@@ -1079,3 +1100,22 @@ void ConPrintFramerate()
IConsolePrint(CC_ERROR, "No performance measurements have been taken yet.");
}
}
/**
* This drains the PFE_SOUND measurement data queue into _pf_data.
* PFE_SOUND measurements are made by the mixer thread and so cannot be stored
* into _pf_data directly, because this would not be thread safe and would violate
* the invariants of the FPS and frame graph windows.
* @see PerformanceMeasurement::~PerformanceMeasurement()
*/
void ProcessPendingPerformanceMeasurements()
{
if (_sound_perf_pending.load(std::memory_order_acquire)) {
std::lock_guard lk(_sound_perf_lock);
for (size_t i = 0; i < _sound_perf_measurements.size(); i += 2) {
_pf_data[PFE_SOUND].Add(_sound_perf_measurements[i], _sound_perf_measurements[i + 1]);
}
_sound_perf_measurements.clear();
_sound_perf_pending.store(false, std::memory_order_relaxed);
}
}