Skip to content

Commit a6cecd2

Browse files
committed
First steps for a benchmark mode
* Add a button in the graphics options to start a benchmark * Added logic to play a custom replay for benchmarking * Added logic to automatically start and end the profiling as the race starts and ends, when in benchmark mode * Disable the profiler drawings in benchmark mode, they take additional resources and are useless * Keep the race going when the pause menu is opened, as it would otherwise distort the results * Added logic to clean up the profiler data each time profiling is switched back from off to on. This avoids multiple profiling sessions piling up in one report, for example when benchmarking tw * Added a sped up Black Forest replay for use during the benchmark Missing features and known issues: * The end screen should display a benchmark result summary instead of a normal end screen * Entering and leaving the pause menu in benchmark mode makes some parts of the race UI disappear * The end screen should send the player back to the graphics settings, not the main menu * Pausing and quitting can leave the profiler enabled when it should not be * The options in the pause menu should be customized in benchmark mode * The replay used for benchmarking should be configurable in a data file * Automatically testing multiple graphics settings and providing an overall summary * And more advanced options.
1 parent 8577408 commit a6cecd2

10 files changed

+1286
-11
lines changed

data/gui/screens/options_video.stkgui

+19
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,25 @@
124124
I18N="In the video settings" text="Apply new resolution" />
125125
</div>
126126

127+
<!-- ************ BENCHMARK OPTIONS ************ -->
128+
<spacer width="5" height="3%"/>
129+
130+
<label width="100%" I18N="In the video settings" text="Performance tests"/>
131+
132+
<spacer width="5" height="1%"/>
133+
134+
<div width="100%" height="fit" layout="horizontal-row" id="outer_box" >
135+
<spacer width="5%" height="100%" />
136+
<button id="benchmarkCurrent" text="Benchmark current settings" I18N="In the video settings" align="center"/>
137+
</div>
138+
<!--
139+
<spacer width="5" height="1%"/>
140+
141+
<div width="100%" height="fit" layout="horizontal-row" id="outer_box" >
142+
<spacer width="5%" height="100%" />
143+
<button id="benchmarkStandard" text="Standard Benchmark" I18N="In the video settings" align="center"/>
144+
</div>
145+
-->
127146
</box>
128147
</div>
129148
</div>

data/replay/benchmark_black_forest.replay

+1,162
Large diffs are not rendered by default.

src/modes/world.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -1024,9 +1024,11 @@ void World::updateWorld(int ticks)
10241024
}
10251025

10261026
// Don't update world if a menu is shown or the race is over.
1027-
if (getPhase() == FINISH_PHASE ||
1028-
(!NetworkConfig::get()->isNetworking() &&
1029-
getPhase() == IN_GAME_MENU_PHASE))
1027+
// Exceptions : - Networking (local pause doesn't affect the server or other players)
1028+
// - Benchmarking (a pause would mess up measurements)
1029+
if ((getPhase() == FINISH_PHASE) ||
1030+
((getPhase() == IN_GAME_MENU_PHASE) &&
1031+
(!NetworkConfig::get()->isNetworking() || !RaceManager::get()->isBenchmarking())))
10301032
return;
10311033

10321034
try

src/modes/world_status.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "network/rewind_manager.hpp"
3434
#include "network/race_event_manager.hpp"
3535
#include "tracks/track.hpp"
36+
#include "utils/profiler.hpp"
3637
#include "utils/stk_process.hpp"
3738

3839
#include <IrrlichtDevice.h>
@@ -352,6 +353,13 @@ void WorldStatus::updateTime(int ticks)
352353
m_start_sound->play();
353354
}
354355

356+
if(RaceManager::get()->isBenchmarking())
357+
{
358+
// The profiler drawings cost performance
359+
profiler.setDrawing(false);
360+
profiler.toggleStatus();
361+
}
362+
355363
// event
356364
onGo();
357365
// In artist debug mode, when without opponents,
@@ -430,6 +438,13 @@ void WorldStatus::updateTime(int ticks)
430438
stk_config->time2Ticks(stk_config->m_delay_finish_time))
431439
{
432440
m_phase = RESULT_DISPLAY_PHASE;
441+
if(RaceManager::get()->isBenchmarking())
442+
{
443+
// End profiling
444+
profiler.toggleStatus();
445+
profiler.writeToFile();
446+
profiler.setDrawing(true);
447+
}
433448
terminateRace();
434449
}
435450

src/race/race_manager.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ RaceManager::RaceManager()
144144
setRecordRace(false);
145145
setRaceGhostKarts(false);
146146
setWatchingReplay(false);
147+
setBenchmarking(false);
147148
setTrack("jungle");
148149
m_default_ai_list.clear();
149150
setNumPlayers(0);

src/race/race_manager.hpp

+12-3
Original file line numberDiff line numberDiff line change
@@ -364,12 +364,11 @@ class RaceManager
364364

365365
/** Determines if saved GP should be continued or not*/
366366
bool m_continue_saved_gp;
367-
368367
bool m_is_recording_race;
369-
370368
bool m_has_ghost_karts;
371-
372369
bool m_watching_replay;
370+
bool m_benchmarking;
371+
373372
public:
374373
// ----------------------------------------------------------------------------------------
375374
static RaceManager* get();
@@ -855,6 +854,11 @@ class RaceManager
855854
m_watching_replay = watch;
856855
} // setWatchingReplay
857856
// ----------------------------------------------------------------------------------------
857+
void setBenchmarking(bool benchmark)
858+
{
859+
m_benchmarking = benchmark;
860+
} // setBenchmarking
861+
// ----------------------------------------------------------------------------------------
858862
bool isRecordingRace() const
859863
{
860864
return m_is_recording_race;
@@ -870,6 +874,11 @@ class RaceManager
870874
return m_watching_replay;
871875
} // isWatchingReplay
872876
// ----------------------------------------------------------------------------------------
877+
bool isBenchmarking() const
878+
{
879+
return m_benchmarking;
880+
} // isBenchmarking
881+
// ----------------------------------------------------------------------------------------
873882
void addSpareTireKart(const std::string& name)
874883
{
875884
m_kart_status.push_back(KartStatus(name, 0, -1, -1,

src/states_screens/dialogs/race_paused_dialog.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ RacePausedDialog::RacePausedDialog(const float percentWidth,
121121
getWidget("team")->setVisible(false);
122122
}
123123
}
124-
else
124+
else if (!RaceManager::get()->isBenchmarking())
125125
{
126126
World::getWorld()->schedulePause(WorldStatus::IN_GAME_MENU_PHASE);
127127
}

src/states_screens/options/options_screen_video.cpp

+31
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
#include "guiengine/widgets/spinner_widget.hpp"
3131
#include "guiengine/widget.hpp"
3232
#include "io/file_manager.hpp"
33+
#include "race/race_manager.hpp"
34+
#include "replay/replay_play.hpp"
3335
#include "states_screens/dialogs/custom_video_settings.hpp"
3436
#include "states_screens/options/options_screen_audio.hpp"
3537
#include "states_screens/options/options_screen_general.hpp"
@@ -906,6 +908,35 @@ void OptionsScreenVideo::eventCallback(Widget* widget, const std::string& name,
906908
#endif
907909
updateScaleRTTsSlider();
908910
}
911+
else if (name == "benchmarkCurrent")
912+
{
913+
// TODO - Add the possibility to benchmark more tracks and define replay benchmarks in
914+
// a config file
915+
const std::string bf_bench("benchmark_black_forest.replay");
916+
const bool result = ReplayPlay::get()->addReplayFile(file_manager
917+
->getAsset(FileManager::REPLAY, bf_bench), true/*custom_replay*/);
918+
919+
if (!result)
920+
Log::fatal("OptionsScreenVideo", "Can't open replay for benchmark!");
921+
RaceManager::get()->setRaceGhostKarts(true);
922+
923+
RaceManager::get()->setMinorMode(RaceManager::MINOR_MODE_TIME_TRIAL);
924+
ReplayPlay::ReplayData bench_rd = ReplayPlay::get()->getCurrentReplayData();
925+
RaceManager::get()->setReverseTrack(bench_rd.m_reverse);
926+
RaceManager::get()->setRecordRace(false);
927+
RaceManager::get()->setWatchingReplay(true);
928+
RaceManager::get()->setDifficulty((RaceManager::Difficulty)bench_rd.m_difficulty);
929+
930+
// The race manager automatically adds karts for the ghosts
931+
RaceManager::get()->setNumKarts(0);
932+
RaceManager::get()->setBenchmarking(true);
933+
RaceManager::get()->startWatchingReplay(bench_rd.m_track_name, bench_rd.m_laps);
934+
}
935+
// TODO - Add a standard benchmark testing multiple presets
936+
/*else if (name == "benchmarkStandard")
937+
{
938+
// DO NOTHING FOR NOW
939+
}*/
909940
else if (name == "rememberWinpos")
910941
{
911942
CheckBoxWidget* rememberWinpos = getWidget<CheckBoxWidget>("rememberWinpos");

src/utils/profiler.cpp

+32-2
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,12 @@ Profiler::Profiler()
8989
// When initializing profile class during static initialization
9090
// UserConfigParams::m_max_fps may not be properly initialized with default
9191
// value, so we use hard-coded default value
92-
m_max_frames = 20 * 120;
92+
m_max_frames = 60 * 1000;
9393
m_current_frame = 0;
9494
m_has_wrapped_around = false;
95+
m_drawing = true;
9596
m_threads_used = 1;
96-
} // Profile
97+
} // Profiler
9798

9899
//-----------------------------------------------------------------------------
99100
Profiler::~Profiler()
@@ -115,6 +116,27 @@ void Profiler::init()
115116
m_gpu_times.resize(Q_LAST * m_max_frames);
116117
} // init
117118

119+
//------------------------------------------------------------------------------
120+
/** Reset profiling data held in memory, to allow starting a new clean profiling run
121+
*/
122+
void Profiler::reset()
123+
{
124+
for (int i = 0; i < m_threads_used; i++)
125+
{
126+
ThreadData &td = m_all_threads_data[i];
127+
td.m_all_event_data.clear();
128+
td.m_event_stack.clear();
129+
td.m_ordered_headings.clear();
130+
} // for i in threads
131+
132+
m_all_threads_data.clear();
133+
m_gpu_times.clear();
134+
m_all_event_names.clear();
135+
m_current_frame = 0;
136+
m_has_wrapped_around = false;
137+
m_freeze_state = UNFROZEN;
138+
} // reset
139+
118140
//-----------------------------------------------------------------------------
119141
/** Returns a unique index for a thread. If the calling thread is not yet in
120142
* the mapping, it will assign a new unique id to this thread. */
@@ -206,6 +228,11 @@ void Profiler::popCPUMarker()
206228
void Profiler::toggleStatus()
207229
{
208230
UserConfigParams::m_profiler_enabled = !UserConfigParams::m_profiler_enabled;
231+
232+
// Avoid data from multiple profiling sessions from merging in one report
233+
if (UserConfigParams::m_profiler_enabled)
234+
reset();
235+
209236
// If the profiler would immediately enabled, calls that have started but
210237
// not finished would not be registered correctly. So set the state to
211238
// waiting, so the unfreeze started at the next sync frame (which is
@@ -290,6 +317,9 @@ void Profiler::synchronizeFrame()
290317
void Profiler::draw()
291318
{
292319
#ifndef SERVER_ONLY
320+
if (!m_drawing)
321+
return;
322+
293323
PROFILER_PUSH_CPU_MARKER("ProfilerDraw", 0xFF, 0xFF, 0x00);
294324
video::IVideoDriver* driver = irr_driver->getVideoDriver();
295325

src/utils/profiler.hpp

+8-2
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,9 @@ class Profiler
244244
/** True if the circular buffer has wrapped around. */
245245
bool m_has_wrapped_around;
246246

247+
/** True if the profiler UI should be rendered */
248+
bool m_drawing;
249+
247250
/** The maximum number of frames to be buffered. Used to minimise
248251
* reallocations. */
249252
int m_max_frames;
@@ -279,18 +282,21 @@ class Profiler
279282
Profiler();
280283
virtual ~Profiler();
281284
void init();
285+
void reset();
282286
void pushCPUMarker(const char* name="N/A",
283287
const video::SColor& color=video::SColor());
284288
void popCPUMarker();
285-
void toggleStatus();
289+
void toggleStatus();
286290
void synchronizeFrame();
287291
void draw();
288292
void onClick(const core::vector2di& mouse_pos);
289293
void writeToFile();
290294

291295
// ------------------------------------------------------------------------
292296
bool isFrozen() const { return m_freeze_state == FROZEN; }
297+
// ------------------------------------------------------------------------
298+
void setDrawing(bool drawing) { m_drawing = drawing; }
293299

294-
};
295300

301+
};
296302
#endif // PROFILER_HPP

0 commit comments

Comments
 (0)