1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00

Rework drawtime and related timekeeping code to use microseconds

This commit is contained in:
sfan5 2022-01-22 17:56:35 +01:00
parent fc161e757c
commit 058846d687
7 changed files with 101 additions and 85 deletions

View file

@ -575,10 +575,19 @@ public:
/****************************************************************************
****************************************************************************/
const float object_hit_delay = 0.2;
const static float object_hit_delay = 0.2;
struct FpsControl {
u32 last_time, busy_time, sleep_time;
FpsControl() : last_time(0), busy_time(0), sleep_time(0) {}
void reset();
void limit(IrrlichtDevice *device, f32 *dtime);
u32 getBusyMs() const { return busy_time / 1000; }
// all values in microseconds (us)
u64 last_time, busy_time, sleep_time;
};
@ -712,7 +721,7 @@ protected:
void updatePlayerControl(const CameraOrientation &cam);
void step(f32 *dtime);
void processClientEvents(CameraOrientation *cam);
void updateCamera(u32 busy_time, f32 dtime);
void updateCamera(f32 dtime);
void updateSound(f32 dtime);
void processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug);
/*!
@ -743,8 +752,6 @@ protected:
void updateShadows();
// Misc
void limitFps(FpsControl *fps_timings, f32 *dtime);
void showOverlayMessage(const char *msg, float dtime, int percent,
bool draw_clouds = true);
@ -1056,14 +1063,14 @@ void Game::run()
RunStats stats = { 0 };
CameraOrientation cam_view_target = { 0 };
CameraOrientation cam_view = { 0 };
FpsControl draw_times = { 0 };
FpsControl draw_times;
f32 dtime; // in seconds
/* Clear the profiler */
Profiler::GraphValues dummyvalues;
g_profiler->graphGet(dummyvalues);
draw_times.last_time = m_rendering_engine->get_timer_time();
draw_times.reset();
set_light_table(g_settings->getFloat("display_gamma"));
@ -1095,7 +1102,7 @@ void Game::run()
// Calculate dtime =
// m_rendering_engine->run() from this iteration
// + Sleep time until the wanted FPS are reached
limitFps(&draw_times, &dtime);
draw_times.limit(device, &dtime);
// Prepare render data for next iteration
@ -1125,7 +1132,7 @@ void Game::run()
step(&dtime);
processClientEvents(&cam_view_target);
updateDebugState();
updateCamera(draw_times.busy_time, dtime);
updateCamera(dtime);
updateSound(dtime);
processPlayerInteraction(dtime, m_game_ui->m_flags.show_hud,
m_game_ui->m_flags.show_basic_debug);
@ -1495,15 +1502,15 @@ bool Game::connectToServer(const GameStartData &start_data,
try {
input->clear();
FpsControl fps_control = { 0 };
FpsControl fps_control;
f32 dtime;
f32 wait_time = 0; // in seconds
fps_control.last_time = m_rendering_engine->get_timer_time();
fps_control.reset();
while (m_rendering_engine->run()) {
limitFps(&fps_control, &dtime);
fps_control.limit(device, &dtime);
// Update client and server
client->step(dtime);
@ -1570,14 +1577,14 @@ bool Game::getServerContent(bool *aborted)
{
input->clear();
FpsControl fps_control = { 0 };
FpsControl fps_control;
f32 dtime; // in seconds
fps_control.last_time = m_rendering_engine->get_timer_time();
fps_control.reset();
while (m_rendering_engine->run()) {
limitFps(&fps_control, &dtime);
fps_control.limit(device, &dtime);
// Update client and server
client->step(dtime);
@ -1774,10 +1781,10 @@ void Game::updateProfilers(const RunStats &stats, const FpsControl &draw_times,
}
// Update update graphs
g_profiler->graphAdd("Time non-rendering [ms]",
g_profiler->graphAdd("Time non-rendering [us]",
draw_times.busy_time - stats.drawtime);
g_profiler->graphAdd("Sleep [ms]", draw_times.sleep_time);
g_profiler->graphAdd("Sleep [us]", draw_times.sleep_time);
g_profiler->graphAdd("FPS", 1.0f / dtime);
}
@ -1810,9 +1817,9 @@ void Game::updateStats(RunStats *stats, const FpsControl &draw_times,
/* Busytime average and jitter calculation
*/
jp = &stats->busy_time_jitter;
jp->avg = jp->avg + draw_times.busy_time * 0.02;
jp->avg = jp->avg + draw_times.getBusyMs() * 0.02;
jitter = draw_times.busy_time - jp->avg;
jitter = draw_times.getBusyMs() - jp->avg;
if (jitter > jp->max)
jp->max = jitter;
@ -2932,7 +2939,7 @@ void Game::updateChat(f32 dtime)
m_game_ui->updateChatSize();
}
void Game::updateCamera(u32 busy_time, f32 dtime)
void Game::updateCamera(f32 dtime)
{
LocalPlayer *player = client->getEnv().getLocalPlayer();
@ -2971,7 +2978,7 @@ void Game::updateCamera(u32 busy_time, f32 dtime)
float tool_reload_ratio = runData.time_from_last_punch / full_punch_interval;
tool_reload_ratio = MYMIN(tool_reload_ratio, 1.0);
camera->update(player, dtime, busy_time / 1000.0f, tool_reload_ratio);
camera->update(player, dtime, tool_reload_ratio);
camera->step(dtime);
v3f camera_position = camera->getPosition();
@ -3847,6 +3854,24 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime,
);
}
/*
Damage camera tilt
*/
if (player->hurt_tilt_timer > 0.0f) {
player->hurt_tilt_timer -= dtime * 6.0f;
if (player->hurt_tilt_timer < 0.0f)
player->hurt_tilt_strength = 0.0f;
}
/*
Update minimap pos and rotation
*/
if (mapper && m_game_ui->m_flags.show_hud) {
mapper->setPos(floatToInt(player->getPosition(), BS));
mapper->setAngle(player->getYaw());
}
/*
Get chat messages from client
*/
@ -3920,11 +3945,11 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime,
} while (false);
/*
Drawing begins
==================== Drawing begins ====================
*/
const video::SColor &skycolor = sky->getSkyColor();
const video::SColor skycolor = sky->getSkyColor();
TimeTaker tt_draw("Draw scene");
TimeTaker tt_draw("Draw scene", nullptr, PRECISION_MICRO);
driver->beginScene(true, true, skycolor);
bool draw_wield_tool = (m_game_ui->m_flags.show_hud &&
@ -3963,25 +3988,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime,
}
/*
Damage camera tilt
*/
if (player->hurt_tilt_timer > 0.0f) {
player->hurt_tilt_timer -= dtime * 6.0f;
if (player->hurt_tilt_timer < 0.0f)
player->hurt_tilt_strength = 0.0f;
}
/*
Update minimap pos and rotation
*/
if (mapper && m_game_ui->m_flags.show_hud) {
mapper->setPos(floatToInt(player->getPosition(), BS));
mapper->setAngle(player->getYaw());
}
/*
End scene
==================== End scene ====================
*/
if (++m_reset_HW_buffer_counter > 500) {
/*
@ -4004,11 +4011,12 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime,
driver->removeAllHardwareBuffers();
m_reset_HW_buffer_counter = 0;
}
driver->endScene();
stats->drawtime = tt_draw.stop(true);
g_profiler->avg("Game::updateFrame(): draw scene [ms]", stats->drawtime);
g_profiler->graphAdd("Update frame [ms]", tt_update.stop(true));
g_profiler->graphAdd("Draw scene [us]", stats->drawtime);
g_profiler->avg("Game::updateFrame(): update frame [ms]", tt_update.stop(true));
}
/* Log times and stuff for visualization */
@ -4052,47 +4060,46 @@ void Game::updateShadows()
Misc
****************************************************************************/
/* On some computers framerate doesn't seem to be automatically limited
*/
inline void Game::limitFps(FpsControl *fps_timings, f32 *dtime)
void FpsControl::reset()
{
// not using getRealTime is necessary for wine
device->getTimer()->tick(); // Maker sure device time is up-to-date
u32 time = device->getTimer()->getTime();
u32 last_time = fps_timings->last_time;
last_time = porting::getTimeUs();
}
if (time > last_time) // Make sure time hasn't overflowed
fps_timings->busy_time = time - last_time;
else
fps_timings->busy_time = 0;
u32 frametime_min = 1000 / (
/*
* On some computers framerate doesn't seem to be automatically limited
*/
void FpsControl::limit(IrrlichtDevice *device, f32 *dtime)
{
const u64 frametime_min = 1000000.0f / (
device->isWindowFocused() && !g_menumgr.pausesGame()
? g_settings->getFloat("fps_max")
: g_settings->getFloat("fps_max_unfocused"));
if (fps_timings->busy_time < frametime_min) {
fps_timings->sleep_time = frametime_min - fps_timings->busy_time;
device->sleep(fps_timings->sleep_time);
u64 time = porting::getTimeUs();
if (time > last_time) // Make sure time hasn't overflowed
busy_time = time - last_time;
else
busy_time = 0;
if (busy_time < frametime_min) {
sleep_time = frametime_min - busy_time;
if (sleep_time > 1000)
sleep_ms(sleep_time / 1000);
} else {
fps_timings->sleep_time = 0;
sleep_time = 0;
}
/* Get the new value of the device timer. Note that device->sleep() may
* not sleep for the entire requested time as sleep may be interrupted and
* therefore it is arguably more accurate to get the new time from the
* device rather than calculating it by adding sleep_time to time.
*/
// Read the timer again to accurately determine how long we actually slept,
// rather than calculating it by adding sleep_time to time.
time = porting::getTimeUs();
device->getTimer()->tick(); // Update device timer
time = device->getTimer()->getTime();
if (time > last_time) // Make sure last_time hasn't overflowed
*dtime = (time - last_time) / 1000.0;
if (time > last_time) // Make sure last_time hasn't overflowed
*dtime = (time - last_time) / 1000000.0f;
else
*dtime = 0;
fps_timings->last_time = time;
last_time = time;
}
void Game::showOverlayMessage(const char *msg, float dtime, int percent, bool draw_clouds)