From 28401cd674eaaf04ed5a642587af93f45bd48da0 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 10 Nov 2017 22:26:59 +0100 Subject: [PATCH 01/17] - Rewrite win32 game tick timer backend to use performance counters and only calculate values once per frame --- src/d_net.cpp | 2 - src/win32/i_system.cpp | 470 ++++++++++++----------------------------- 2 files changed, 133 insertions(+), 339 deletions(-) diff --git a/src/d_net.cpp b/src/d_net.cpp index 8a21205bd..e69839485 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -1947,8 +1947,6 @@ void TryRunTics (void) if (debugfile) fprintf (debugfile, "run tic %d\n", gametic); C_Ticker (); M_Ticker (); - I_GetTime (true); - I_SetFrameTime(); G_Ticker(); gametic++; diff --git a/src/win32/i_system.cpp b/src/win32/i_system.cpp index 2f1270697..be91dcec2 100644 --- a/src/win32/i_system.cpp +++ b/src/win32/i_system.cpp @@ -118,7 +118,6 @@ extern void LayoutMainWindow(HWND hWnd, HWND pane); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void CalculateCPUSpeed(); -static void I_SelectTimer(); static int I_GetTimePolled(bool saveMS); static int I_WaitForTicPolled(int prevtic); @@ -158,15 +157,9 @@ CVAR (String, queryiwad_key, "shift", CVAR_GLOBALCONFIG|CVAR_ARCHIVE); CVAR (Bool, con_debugoutput, false, 0); double PerfToSec, PerfToMillisec; -UINT TimerPeriod; -UINT TimerEventID; -UINT MillisecondsPerTic; -HANDLE NewTicArrived; uint32_t LanguageIDs[4]; -int (*I_GetTime) (bool saveMS); -int (*I_WaitForTic) (int); -void (*I_FreezeTime) (bool frozen); +UINT TimerPeriod; bool gameisdead; @@ -175,23 +168,142 @@ bool gameisdead; static ticcmd_t emptycmd; static bool HasExited; -static DWORD basetime = 0; -// These are for the polled timer. -static DWORD TicStart; -static DWORD TicNext; -static int TicFrozen; - -// These are for the event-driven timer. -static int tics; -static DWORD ted_start, ted_next; - static WadStuff *WadList; static int NumWads; static int DefaultWad; static HCURSOR CustomCursor; -// CODE -------------------------------------------------------------------- +//========================================================================== +// +// Tick time functions +// +//========================================================================== + +static LARGE_INTEGER frequency; + +static uint32_t performanceGetTime() +{ + if (frequency.QuadPart != 0) + { + LARGE_INTEGER current; + QueryPerformanceCounter(¤t); + return current.QuadPart * 1000 / frequency.QuadPart; + } + else + { + return timeGetTime(); + } +} + +static unsigned int FirstFrameStartTime; +static unsigned int CurrentFrameStartTime; +static bool TimeFrozen; + +void I_SetFrameTime() +{ + // It is critical that all timing is calculated only once at a start of a frame. + // + // performanceGetTime() must only ever be called once or otherwise the playsim + // processing time will affect the interpolation done by the renderer. + + if (!TimeFrozen) + { + CurrentFrameStartTime = performanceGetTime(); + if (FirstFrameStartTime == 0) + FirstFrameStartTime = CurrentFrameStartTime; + } +} + +void I_WaitVBL(int count) +{ + // I_WaitVBL is never used to actually synchronize to the vertical blank. + // Instead, it's used for delay purposes. Doom used a 70 Hz display mode, + // so that's what we use to determine how long to wait for. + + Sleep(1000 * count / 70); + I_SetFrameTime(); +} + +static int I_WaitForTicWin32(int prevtic) +{ + // Waits until the current tic is greater than prevtic. Time must not be frozen. + + int time; + assert(TicFrozen == 0); + while ((time = I_GetTime(false)) <= prevtic) + { + // The minimum amount of time a thread can sleep is controlled by timeBeginPeriod. + // We set this to 1 ms in DoMain. + int sleepTime = prevtic - time; + if (sleepTime > 2) + Sleep(sleepTime - 2); + + I_SetFrameTime(); + } + + return time; +} + +unsigned int I_FPSTime() +{ + if (!TimeFrozen) + return CurrentFrameStartTime; + else + return performanceGetTime(); +} + +unsigned int I_MSTime() +{ + if (!TimeFrozen) + { + return CurrentFrameStartTime - FirstFrameStartTime; + } + else + { + if (FirstFrameStartTime == 0) + { + FirstFrameStartTime = performanceGetTime(); + return 0; + } + else + { + return performanceGetTime() - FirstFrameStartTime; + } + } +} + +int I_GetTimeWin32(bool saveMS) +{ + return (CurrentFrameStartTime - FirstFrameStartTime) * TICRATE / 1000 + 1; +} + +double I_GetTimeFrac(uint32_t *ms) +{ + unsigned int currentTic = (CurrentFrameStartTime - FirstFrameStartTime) * TICRATE / 1000; + unsigned int ticStartTime = FirstFrameStartTime + currentTic * 1000 / TICRATE; + unsigned int ticNextTime = FirstFrameStartTime + (currentTic + 1) * 1000 / TICRATE; + + if (ms) + *ms = currentTic + 1; + + return (CurrentFrameStartTime - ticStartTime) / (double)(ticNextTime - ticStartTime); +} + +void I_FreezeTimeWin32(bool frozen) +{ + if (TimeFrozen && !frozen) + { + unsigned int timeFrozen = performanceGetTime() - CurrentFrameStartTime; + FirstFrameStartTime += timeFrozen; + } + + TimeFrozen = frozen; +} + +int(*I_GetTime)(bool saveMS) = I_GetTimeWin32; +int(*I_WaitForTic)(int) = I_WaitForTicWin32; +void(*I_FreezeTime)(bool frozen) = I_FreezeTimeWin32; //========================================================================== // @@ -222,314 +334,6 @@ ticcmd_t *I_BaseTiccmd() return &emptycmd; } -// Stubs that select the timer to use and then call into it ---------------- - -//========================================================================== -// -// I_GetTimeSelect -// -//========================================================================== - -static int I_GetTimeSelect(bool saveMS) -{ - I_SelectTimer(); - return I_GetTime(saveMS); -} - -//========================================================================== -// -// I_WaitForTicSelect -// -//========================================================================== - -static int I_WaitForTicSelect(int prevtic) -{ - I_SelectTimer(); - return I_WaitForTic(prevtic); -} - -//========================================================================== -// -// I_SelectTimer -// -// Tries to create a timer event for efficent CPU use when the FPS is -// capped. Failing that, it sets things up for a polling timer instead. -// -//========================================================================== - -static void I_SelectTimer() -{ - assert(basetime == 0); - - // Use a timer event if possible. - NewTicArrived = CreateEvent(NULL, FALSE, FALSE, NULL); - if (NewTicArrived) - { - UINT delay; - const char *cmdDelay; - - cmdDelay = Args->CheckValue("-timerdelay"); - delay = 0; - if (cmdDelay != 0) - { - delay = atoi(cmdDelay); - } - if (delay == 0) - { - delay = 1000/TICRATE; - } - MillisecondsPerTic = delay; - TimerEventID = timeSetEvent(delay, 0, TimerTicked, 0, TIME_PERIODIC); - } - // Get the current time as the basetime. - basetime = timeGetTime(); - // Set timer functions. - if (TimerEventID != 0) - { - I_GetTime = I_GetTimeEventDriven; - I_WaitForTic = I_WaitForTicEvent; - I_FreezeTime = I_FreezeTimeEventDriven; - } - else - { - I_GetTime = I_GetTimePolled; - I_WaitForTic = I_WaitForTicPolled; - I_FreezeTime = I_FreezeTimePolled; - } -} - -//========================================================================== -// -// I_MSTime -// -// Returns the current time in milliseconds, where 0 is the first call -// to I_GetTime or I_WaitForTic. -// -//========================================================================== - -unsigned int I_MSTime() -{ - assert(basetime != 0); - return timeGetTime() - basetime; -} - -//========================================================================== -// -// I_FPSTime -// -// Returns the current system time in milliseconds. This is used by the FPS -// meter of DFrameBuffer::DrawRateStuff(). Since the screen can display -// before the play simulation is ready to begin, this needs to be -// separate from I_MSTime(). -// -//========================================================================== - -unsigned int I_FPSTime() -{ - return timeGetTime(); -} - -//========================================================================== -// -// I_GetTimePolled -// -// Returns the current time in tics. If saveMS is true, then calls to -// I_GetTimeFrac() will use this tic as 0 and the next tic as 1. -// -//========================================================================== - -static int I_GetTimePolled(bool saveMS) -{ - DWORD tm; - - if (TicFrozen != 0) - { - return TicFrozen; - } - - tm = timeGetTime(); - if (basetime == 0) - { - basetime = tm; - } - if (saveMS) - { - TicStart = tm; - TicNext = (tm * TICRATE / 1000 + 1) * 1000 / TICRATE; - } - - return ((tm-basetime)*TICRATE)/1000; -} - -//========================================================================== -// -// I_WaitForTicPolled -// -// Busy waits until the current tic is greater than prevtic. Time must not -// be frozen. -// -//========================================================================== - -static int I_WaitForTicPolled(int prevtic) -{ - int time; - - assert(TicFrozen == 0); - while ((time = I_GetTimePolled(false)) <= prevtic) - { } - - return time; -} - -//========================================================================== -// -// I_FreezeTimePolled -// -// Freeze/unfreeze the timer. -// -//========================================================================== - -static void I_FreezeTimePolled(bool frozen) -{ - if (frozen) - { - assert(TicFrozen == 0); - TicFrozen = I_GetTimePolled(false); - } - else - { - assert(TicFrozen != 0); - int froze = TicFrozen; - TicFrozen = 0; - int now = I_GetTimePolled(false); - basetime += (now - froze) * 1000 / TICRATE; - } -} - -//========================================================================== -// -// I_GetTimeEventDriven -// -// Returns the current tick counter. This is incremented asynchronously as -// the timer event fires. -// -//========================================================================== - -static int I_GetTimeEventDriven(bool saveMS) -{ - if (saveMS) - { - TicStart = ted_start; - TicNext = ted_next; - } - return tics; -} - -//========================================================================== -// -// I_WaitForTicEvent -// -// Waits on the timer event as long as the current tic is not later than -// prevtic. -// -//========================================================================== - -static int I_WaitForTicEvent(int prevtic) -{ - assert(!TicFrozen); - while (prevtic >= tics) - { - WaitForSingleObject(NewTicArrived, 1000/TICRATE); - } - return tics; -} - -//========================================================================== -// -// I_FreezeTimeEventDriven -// -// Freeze/unfreeze the ticker. -// -//========================================================================== - -static void I_FreezeTimeEventDriven(bool frozen) -{ - TicFrozen = frozen; -} - -//========================================================================== -// -// TimerTicked -// -// Advance the tick count and signal the NewTicArrived event. -// -//========================================================================== - -static void CALLBACK TimerTicked(UINT id, UINT msg, DWORD_PTR user, DWORD_PTR dw1, DWORD_PTR dw2) -{ - if (!TicFrozen) - { - tics++; - } - ted_start = timeGetTime (); - ted_next = ted_start + MillisecondsPerTic; - SetEvent(NewTicArrived); -} - -//========================================================================== -// -// I_GetTimeFrac -// -// Returns the fractional amount of a tic passed since the most recently -// saved tic. -// -//========================================================================== -static uint32_t FrameTime; - -void I_SetFrameTime() -{ - FrameTime = timeGetTime(); -} - -double I_GetTimeFrac(uint32_t *ms) -{ - //DWORD now = MAX(FrameTime, TicStart); - DWORD now = FrameTime; - if (FrameTime < TicStart) - { - // Preliminary kept in to see if this can happen. Should be removed once confirmed ok. - Printf("Timer underflow!\n"); - } - if (ms != NULL) - { - *ms = TicNext; - } - DWORD step = TicNext - TicStart; - if (step == 0) - { - return 1.; - } - else - { - return clamp(double(now - TicStart) / step, 0, 1); - } -} - -//========================================================================== -// -// I_WaitVBL -// -// I_WaitVBL is never used to actually synchronize to the vertical blank. -// Instead, it's used for delay purposes. Doom used a 70 Hz display mode, -// so that's what we use to determine how long to wait for. -// -//========================================================================== - -void I_WaitVBL(int count) -{ - Sleep(1000 * count / 70); -} - //========================================================================== // // I_DetectOS @@ -736,8 +540,7 @@ void I_Init() CalculateCPUSpeed(); DumpCPUInfo(&CPU); - I_GetTime = I_GetTimeSelect; - I_WaitForTic = I_WaitForTicSelect; + QueryPerformanceFrequency(&frequency); atterm (I_ShutdownSound); I_InitSound (); @@ -753,15 +556,8 @@ void I_Quit() { HasExited = true; /* Prevent infinitely recursive exits -- killough */ - if (TimerEventID != 0) - { - timeKillEvent(TimerEventID); - } - if (NewTicArrived != NULL) - { - CloseHandle(NewTicArrived); - } timeEndPeriod(TimerPeriod); + if (demorecording) { G_CheckDemoStatus(); From 090943eaa49baa2a60ac89e2cb6ed8681f0301f6 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 10 Nov 2017 23:17:31 +0100 Subject: [PATCH 02/17] - Fix freeze interpolation bug --- src/win32/i_system.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/win32/i_system.cpp b/src/win32/i_system.cpp index be91dcec2..2b4d86567 100644 --- a/src/win32/i_system.cpp +++ b/src/win32/i_system.cpp @@ -198,7 +198,7 @@ static uint32_t performanceGetTime() static unsigned int FirstFrameStartTime; static unsigned int CurrentFrameStartTime; -static bool TimeFrozen; +static unsigned int FreezeTime; void I_SetFrameTime() { @@ -207,7 +207,7 @@ void I_SetFrameTime() // performanceGetTime() must only ever be called once or otherwise the playsim // processing time will affect the interpolation done by the renderer. - if (!TimeFrozen) + if (FreezeTime == 0) { CurrentFrameStartTime = performanceGetTime(); if (FirstFrameStartTime == 0) @@ -247,7 +247,7 @@ static int I_WaitForTicWin32(int prevtic) unsigned int I_FPSTime() { - if (!TimeFrozen) + if (FreezeTime == 0) return CurrentFrameStartTime; else return performanceGetTime(); @@ -255,7 +255,7 @@ unsigned int I_FPSTime() unsigned int I_MSTime() { - if (!TimeFrozen) + if (FreezeTime == 0) { return CurrentFrameStartTime - FirstFrameStartTime; } @@ -292,13 +292,16 @@ double I_GetTimeFrac(uint32_t *ms) void I_FreezeTimeWin32(bool frozen) { - if (TimeFrozen && !frozen) + if (frozen) { - unsigned int timeFrozen = performanceGetTime() - CurrentFrameStartTime; - FirstFrameStartTime += timeFrozen; + FreezeTime = performanceGetTime(); + } + else + { + FirstFrameStartTime += performanceGetTime() - FreezeTime; + FreezeTime = 0; + I_SetFrameTime(); } - - TimeFrozen = frozen; } int(*I_GetTime)(bool saveMS) = I_GetTimeWin32; From 307d8931d894d8559025187ef0ae3a80f1a7dd99 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 12 Nov 2017 03:12:22 +0100 Subject: [PATCH 03/17] - Switch to C++11 steady clock - Move the C++11 implementation to d_main - Remove the platform specific timer implementations --- src/c_bind.cpp | 1 + src/c_console.cpp | 3 +- src/d_main.cpp | 125 ++++++++++++++++++- src/d_main.h | 20 ++++ src/d_net.cpp | 13 +- src/dobject.cpp | 1 + src/g_game.cpp | 3 +- src/g_level.cpp | 3 +- src/gl/models/gl_models.cpp | 1 + src/gl/scene/gl_scene.cpp | 1 + src/gl/utility/gl_clock.cpp | 2 +- src/menu/videomenu.cpp | 3 +- src/p_glnodes.cpp | 1 + src/p_setup.cpp | 1 + src/posix/cocoa/i_timer.cpp | 192 +----------------------------- src/posix/i_system.h | 4 - src/posix/sdl/i_timer.cpp | 192 +----------------------------- src/r_utility.cpp | 5 +- src/swrenderer/things/r_voxel.cpp | 1 + src/v_video.cpp | 3 +- src/win32/i_system.cpp | 140 ---------------------- src/win32/i_system.h | 19 --- 22 files changed, 174 insertions(+), 560 deletions(-) diff --git a/src/c_bind.cpp b/src/c_bind.cpp index 76c552db2..8fb29de87 100644 --- a/src/c_bind.cpp +++ b/src/c_bind.cpp @@ -47,6 +47,7 @@ #include "templates.h" #include "dobject.h" #include "vm.h" +#include "d_main.h" #include #include diff --git a/src/c_console.cpp b/src/c_console.cpp index 12be59818..4d8d64dd8 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -69,6 +69,7 @@ #include "c_consolebuffer.h" #include "g_levellocals.h" #include "vm.h" +#include "d_main.h" FString FStringFormat(VM_ARGS); // extern from thingdef_data.cpp @@ -528,7 +529,7 @@ static void maybedrawnow (bool tick, bool force) || gamestate == GS_STARTUP)) { static size_t lastprinttime = 0; - size_t nowtime = I_GetTime(false); + size_t nowtime = I_GetTime(); if (nowtime - lastprinttime > 1 || force) { diff --git a/src/d_main.cpp b/src/d_main.cpp index 29cc82a16..21383118d 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -117,6 +117,8 @@ #include "vm.h" #include "types.h" #include "r_data/r_vanillatrans.h" +#include +#include EXTERN_CVAR(Bool, hud_althud) void DrawHUD(); @@ -280,7 +282,7 @@ void D_ProcessEvents (void) { M_SetDefaultMode (); } - else if (testingmode <= I_GetTime(false)) + else if (testingmode <= I_GetTime()) { M_RestoreMode (); } @@ -1080,6 +1082,127 @@ void D_DoomLoop () } } +//========================================================================== +// +// Tick time functions +// +//========================================================================== + +static unsigned int FirstFrameStartTime; +static unsigned int CurrentFrameStartTime; +static unsigned int FreezeTime; + +static uint32_t performanceGetTime() +{ + using namespace std::chrono; + return (uint32_t)duration_cast(steady_clock::now().time_since_epoch()).count(); +} + +void I_SetFrameTime() +{ + // Must only be called once per frame/swapbuffers. + // + // Caches all timing information for the current rendered frame so that any + // calls to I_FPSTime, I_MSTime, I_GetTime or I_GetTimeFrac will return + // the same time. + + if (FreezeTime == 0) + { + CurrentFrameStartTime = performanceGetTime(); + if (FirstFrameStartTime == 0) + FirstFrameStartTime = CurrentFrameStartTime; + } +} + +void I_WaitVBL(int count) +{ + // I_WaitVBL is never used to actually synchronize to the vertical blank. + // Instead, it's used for delay purposes. Doom used a 70 Hz display mode, + // so that's what we use to determine how long to wait for. + + std::this_thread::sleep_for(std::chrono::milliseconds(1000 * count / 70)); + I_SetFrameTime(); +} + +int I_WaitForTic(int prevtic) +{ + // Waits until the current tic is greater than prevtic. Time must not be frozen. + + int time; + assert(TicFrozen == 0); + while ((time = I_GetTime()) <= prevtic) + { + // The minimum amount of time a thread can sleep is controlled by timeBeginPeriod. + // We set this to 1 ms in DoMain. + int sleepTime = prevtic - time; + if (sleepTime > 2) + std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime - 2)); + + I_SetFrameTime(); + } + + return time; +} + +unsigned int I_FPSTime() +{ + if (FreezeTime == 0) + return CurrentFrameStartTime; + else + return performanceGetTime(); +} + +unsigned int I_MSTime() +{ + if (FreezeTime == 0) + { + return CurrentFrameStartTime - FirstFrameStartTime; + } + else + { + if (FirstFrameStartTime == 0) + { + FirstFrameStartTime = performanceGetTime(); + return 0; + } + else + { + return performanceGetTime() - FirstFrameStartTime; + } + } +} + +int I_GetTime() +{ + return (CurrentFrameStartTime - FirstFrameStartTime) * TICRATE / 1000 + 1; +} + +double I_GetTimeFrac(uint32_t *ms) +{ + unsigned int currentTic = (CurrentFrameStartTime - FirstFrameStartTime) * TICRATE / 1000; + unsigned int ticStartTime = FirstFrameStartTime + currentTic * 1000 / TICRATE; + unsigned int ticNextTime = FirstFrameStartTime + (currentTic + 1) * 1000 / TICRATE; + + if (ms) + *ms = currentTic + 1; + + return (CurrentFrameStartTime - ticStartTime) / (double)(ticNextTime - ticStartTime); +} + +void I_FreezeTime(bool frozen) +{ + if (frozen) + { + FreezeTime = performanceGetTime(); + } + else + { + FirstFrameStartTime += performanceGetTime() - FreezeTime; + FreezeTime = 0; + I_SetFrameTime(); + } +} + //========================================================================== // // D_PageTicker diff --git a/src/d_main.h b/src/d_main.h index 1fa0368d6..73690cc05 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -162,5 +162,25 @@ public: }; +// Called by D_DoomLoop, sets the time for the current frame +void I_SetFrameTime(); + +// Called by D_DoomLoop, returns current time in tics. +int I_GetTime(); + +double I_GetTimeFrac(uint32_t *ms); + +// like I_GetTime, except it waits for a new tic before returning +int I_WaitForTic(int); + +// Freezes tic counting temporarily. While frozen, calls to I_GetTime() +// will always return the same value. This does not affect I_MSTime(). +// You must also not call I_WaitForTic() while freezing time, since the +// tic will never arrive (unless it's the current one). +void I_FreezeTime(bool frozen); + +// [RH] Returns millisecond-accurate time +unsigned int I_MSTime(); +unsigned int I_FPSTime(); #endif diff --git a/src/d_net.cpp b/src/d_net.cpp index e69839485..42f4d425a 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -68,6 +68,7 @@ #include "intermission/intermission.h" #include "g_levellocals.h" #include "events.h" +#include "d_main.h" EXTERN_CVAR (Int, disableautosave) EXTERN_CVAR (Int, autosavecount) @@ -956,7 +957,7 @@ void NetUpdate (void) } // check time - nowtime = I_GetTime (false); + nowtime = I_GetTime (); newtics = nowtime - gametime; gametime = nowtime; @@ -1830,7 +1831,7 @@ void TryRunTics (void) } else { - entertic = I_GetTime (false); + entertic = I_GetTime (); } realtics = entertic - oldentertics; oldentertics = entertic; @@ -1913,7 +1914,7 @@ void TryRunTics (void) Net_CheckLastReceived (counts); // don't stay in here forever -- give the menu a chance to work - if (I_GetTime (false) - entertic >= 1) + if (I_GetTime () - entertic >= 1) { C_Ticker (); M_Ticker (); @@ -1928,7 +1929,7 @@ void TryRunTics (void) hadlate = false; for (i = 0; i < MAXPLAYERS; i++) players[i].waiting = false; - lastglobalrecvtime = I_GetTime (false); //Update the last time the game tic'd over + lastglobalrecvtime = I_GetTime (); //Update the last time the game tic'd over // run the count tics if (counts > 0) @@ -1961,9 +1962,9 @@ void Net_CheckLastReceived (int counts) { // [Ed850] Check to see the last time a packet was received. // If it's longer then 3 seconds, a node has likely stalled. - if (I_GetTime(false) - lastglobalrecvtime >= TICRATE * 3) + if (I_GetTime() - lastglobalrecvtime >= TICRATE * 3) { - lastglobalrecvtime = I_GetTime(false); //Bump the count + lastglobalrecvtime = I_GetTime(); //Bump the count if (NetMode == NET_PeerToPeer || consoleplayer == Net_Arbitrator) { diff --git a/src/dobject.cpp b/src/dobject.cpp index 39c55f2b5..1e399908e 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -51,6 +51,7 @@ #include "vm.h" #include "g_levellocals.h" #include "types.h" +#include "d_main.h" //========================================================================== // diff --git a/src/g_game.cpp b/src/g_game.cpp index db5c1cb2e..77db68a8d 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -92,6 +92,7 @@ #include "g_hub.h" #include "g_levellocals.h" #include "events.h" +#include "d_main.h" static FRandom pr_dmspawn ("DMSpawn"); @@ -2887,7 +2888,7 @@ bool G_CheckDemoStatus (void) int endtime = 0; if (timingdemo) - endtime = I_GetTime (false) - starttime; + endtime = I_GetTime () - starttime; C_RestoreCVars (); // [RH] Restore cvars demo might have changed M_Free (demobuffer); diff --git a/src/g_level.cpp b/src/g_level.cpp index d5044942e..5309e72cc 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -94,6 +94,7 @@ #include "g_levellocals.h" #include "actorinlines.h" #include "vm.h" +#include "d_main.h" #include @@ -1020,7 +1021,7 @@ void G_DoLoadLevel (int position, bool autosave) if (firstTime) { - starttime = I_GetTime (false); + starttime = I_GetTime (); firstTime = false; } } diff --git a/src/gl/models/gl_models.cpp b/src/gl/models/gl_models.cpp index fcad2a95b..2e6df1ed5 100644 --- a/src/gl/models/gl_models.cpp +++ b/src/gl/models/gl_models.cpp @@ -39,6 +39,7 @@ #include "d_player.h" #include "g_levellocals.h" #include "r_utility.h" +#include "d_main.h" //#include "resources/voxels.h" //#include "gl/gl_intern.h" diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index 9bfca82ff..ce5fb524f 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -45,6 +45,7 @@ #include "serializer.h" #include "g_levellocals.h" #include "events.h" +#include "d_main.h" #include "gl/dynlights/gl_lightbuffer.h" #include "gl/system/gl_interface.h" diff --git a/src/gl/utility/gl_clock.cpp b/src/gl/utility/gl_clock.cpp index 81cb52b01..27e740318 100644 --- a/src/gl/utility/gl_clock.cpp +++ b/src/gl/utility/gl_clock.cpp @@ -52,7 +52,7 @@ #include "g_levellocals.h" #include "gl/utility/gl_clock.h" #include "gl/utility/gl_convert.h" - +#include "d_main.h" glcycle_t RenderWall,SetupWall,ClipWall; glcycle_t RenderFlat,SetupFlat; diff --git a/src/menu/videomenu.cpp b/src/menu/videomenu.cpp index cea99cd42..74fe71b67 100644 --- a/src/menu/videomenu.cpp +++ b/src/menu/videomenu.cpp @@ -55,6 +55,7 @@ #include "hardware.h" #include "vm.h" #include "r_videoscale.h" +#include "d_main.h" /*======================================= * @@ -312,7 +313,7 @@ DEFINE_ACTION_FUNCTION(DVideoModeMenu, SetSelectedSize) OldBits = DisplayBits; NewBits = BitTranslate[DummyDepthCvar]; setmodeneeded = true; - testingmode = I_GetTime(false) + 5 * TICRATE; + testingmode = I_GetTime() + 5 * TICRATE; SetModesMenu (NewWidth, NewHeight, NewBits); ACTION_RETURN_BOOL(true); } diff --git a/src/p_glnodes.cpp b/src/p_glnodes.cpp index 36873f4ba..8ec8ed8c3 100644 --- a/src/p_glnodes.cpp +++ b/src/p_glnodes.cpp @@ -68,6 +68,7 @@ #include "r_utility.h" #include "cmdlib.h" #include "g_levellocals.h" +#include "d_main.h" void P_GetPolySpots (MapData * lump, TArray &spots, TArray &anchors); diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 1bb0e9d8b..cb8b6e5b6 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -115,6 +115,7 @@ #endif #include "events.h" #include "types.h" +#include "d_main.h" #include "fragglescript/t_fs.h" diff --git a/src/posix/cocoa/i_timer.cpp b/src/posix/cocoa/i_timer.cpp index dbeca1270..503fa64ec 100644 --- a/src/posix/cocoa/i_timer.cpp +++ b/src/posix/cocoa/i_timer.cpp @@ -40,202 +40,12 @@ #include "i_system.h" #include "templates.h" - -namespace -{ - -timeval s_gameStartTicks; -timeval s_systemBootTicks; - -unsigned int GetMillisecondsSince(const timeval& time) -{ - timeval now; - gettimeofday(&now, NULL); - - return static_cast( - (now.tv_sec - time.tv_sec ) * 1000 - + (now.tv_usec - time.tv_usec) / 1000); -} - - -bool s_isTicFrozen; - -timespec GetNextTickTime() -{ - static const long MILLISECONDS_IN_SECOND = 1000; - static const long MICROSECONDS_IN_SECOND = 1000 * MILLISECONDS_IN_SECOND; - static const long NANOSECONDS_IN_SECOND = 1000 * MICROSECONDS_IN_SECOND; - - static timespec ts = {}; - - if (__builtin_expect((0 == ts.tv_sec), 0)) - { - timeval tv; - gettimeofday(&tv, NULL); - - ts.tv_sec = tv.tv_sec; - ts.tv_nsec = (tv.tv_usec + MICROSECONDS_IN_SECOND / TICRATE) * MILLISECONDS_IN_SECOND; - } - else - { - ts.tv_nsec += (MICROSECONDS_IN_SECOND / TICRATE) * MILLISECONDS_IN_SECOND; - } - - if (ts.tv_nsec >= NANOSECONDS_IN_SECOND) - { - ts.tv_sec++; - ts.tv_nsec -= NANOSECONDS_IN_SECOND; - } - - return ts; -} - - -pthread_cond_t s_timerEvent; -pthread_mutex_t s_timerMutex; -pthread_t s_timerThread; - -bool s_timerInitialized; -bool s_timerExitRequested; - -uint32_t s_ticStart; -uint32_t s_timerStart; - -int s_tics; - - -void* TimerThreadFunc(void*) -{ - assert(s_timerInitialized); - assert(!s_timerExitRequested); - - while (true) - { - if (s_timerExitRequested) - { - break; - } - - const timespec timeToNextTick = GetNextTickTime(); - - pthread_mutex_lock(&s_timerMutex); - pthread_cond_timedwait(&s_timerEvent, &s_timerMutex, &timeToNextTick); - - if (!s_isTicFrozen) - { - __sync_add_and_fetch(&s_tics, 1); - } - - s_timerStart = I_MSTime(); - - pthread_cond_broadcast(&s_timerEvent); - pthread_mutex_unlock(&s_timerMutex); - } - - return NULL; -} - -int GetTimeThreaded(bool saveMS) -{ - if (saveMS) - { - s_ticStart = s_timerStart; - } - - return s_tics; -} - -int WaitForTicThreaded(int prevTic) -{ - assert(!s_isTicFrozen); - - while (s_tics <= prevTic) - { - pthread_mutex_lock(&s_timerMutex); - pthread_cond_wait(&s_timerEvent, &s_timerMutex); - pthread_mutex_unlock(&s_timerMutex); - } - - return s_tics; -} - -void FreezeTimeThreaded(bool frozen) -{ - s_isTicFrozen = frozen; -} - -} // unnamed namespace - - -unsigned int I_MSTime() -{ - return GetMillisecondsSince(s_gameStartTicks); -} - -unsigned int I_FPSTime() -{ - return GetMillisecondsSince(s_systemBootTicks); -} - - -static uint32_t FrameTime; - -void I_SetFrameTime() -{ - FrameTime = I_MSTime(); -} - - -double I_GetTimeFrac(uint32_t* ms) -{ - const uint32_t now = FrameTime; - - if (NULL != ms) - { - *ms = s_ticStart + 1000 / TICRATE; - } - - return 0 == s_ticStart - ? 1. - : clamp( (now - s_ticStart) * TICRATE / 1000., 0, 1); -} - +// To do: this file is obviously not needed anymore. It needs to be removed. void I_InitTimer() { - assert(!s_timerInitialized); - s_timerInitialized = true; - - gettimeofday(&s_gameStartTicks, NULL); - - int mib[2] = { CTL_KERN, KERN_BOOTTIME }; - size_t len = sizeof s_systemBootTicks; - - sysctl(mib, 2, &s_systemBootTicks, &len, NULL, 0); - - pthread_cond_init (&s_timerEvent, NULL); - pthread_mutex_init(&s_timerMutex, NULL); - - pthread_create(&s_timerThread, NULL, TimerThreadFunc, NULL); - - I_GetTime = GetTimeThreaded; - I_WaitForTic = WaitForTicThreaded; - I_FreezeTime = FreezeTimeThreaded; } void I_ShutdownTimer() { - if (!s_timerInitialized) - { - // This might happen if Cancel button was pressed - // in the IWAD selector window - return; - } - - s_timerExitRequested = true; - - pthread_join(s_timerThread, NULL); - - pthread_mutex_destroy(&s_timerMutex); - pthread_cond_destroy (&s_timerEvent); } diff --git a/src/posix/i_system.h b/src/posix/i_system.h index 0649b7f3c..7e9f83939 100644 --- a/src/posix/i_system.h +++ b/src/posix/i_system.h @@ -140,10 +140,6 @@ TArray I_GetGogPaths(); // The ini could not be saved at exit bool I_WriteIniFailed (); -// [RH] Returns millisecond-accurate time -unsigned int I_MSTime (void); -unsigned int I_FPSTime(); - class FTexture; bool I_SetCursor(FTexture *); diff --git a/src/posix/sdl/i_timer.cpp b/src/posix/sdl/i_timer.cpp index a779852c7..dab7c30ac 100644 --- a/src/posix/sdl/i_timer.cpp +++ b/src/posix/sdl/i_timer.cpp @@ -44,201 +44,13 @@ #include "i_system.h" #include "templates.h" - -static uint32_t TicStart; -static uint32_t BaseTime; -static int TicFrozen; - -// Signal based timer. -static Semaphore timerWait; -static int tics; -static uint32_t sig_start; - -void I_SelectTimer(); - -// [RH] Returns time in milliseconds -unsigned int I_MSTime (void) -{ - unsigned int time = SDL_GetTicks (); - return time - BaseTime; -} - -// Exactly the same thing, but based does no modification to the time. -unsigned int I_FPSTime() -{ - return SDL_GetTicks(); -} - -// -// I_GetTime -// returns time in 1/35th second tics -// -int I_GetTimeSelect (bool saveMS) -{ - I_SelectTimer(); - return I_GetTime (saveMS); -} - -int I_GetTimePolled (bool saveMS) -{ - if (TicFrozen != 0) - { - return TicFrozen; - } - - uint32_t tm = SDL_GetTicks(); - - if (saveMS) - { - TicStart = tm; - } - return Scale(tm - BaseTime, TICRATE, 1000); -} - -int I_GetTimeSignaled (bool saveMS) -{ - if (saveMS) - { - TicStart = sig_start; - } - return tics; -} - -int I_WaitForTicPolled (int prevtic) -{ - int time; - - assert (TicFrozen == 0); - while ((time = I_GetTimePolled(false)) <= prevtic) - ; - - return time; -} - -int I_WaitForTicSignaled (int prevtic) -{ - assert (TicFrozen == 0); - - while(tics <= prevtic) - { - SEMAPHORE_WAIT(timerWait) - } - - return tics; -} - -void I_FreezeTimeSelect (bool frozen) -{ - I_SelectTimer(); - return I_FreezeTime (frozen); -} - -void I_FreezeTimePolled (bool frozen) -{ - if (frozen) - { - assert(TicFrozen == 0); - TicFrozen = I_GetTimePolled(false); - } - else - { - assert(TicFrozen != 0); - int froze = TicFrozen; - TicFrozen = 0; - int now = I_GetTimePolled(false); - BaseTime += (now - froze) * 1000 / TICRATE; - } -} - -void I_FreezeTimeSignaled (bool frozen) -{ - TicFrozen = frozen; -} - -int I_WaitForTicSelect (int prevtic) -{ - I_SelectTimer(); - return I_WaitForTic (prevtic); -} - -// -// I_HandleAlarm -// Should be called every time there is an alarm. -// -void I_HandleAlarm (int sig) -{ - if(!TicFrozen) - tics++; - sig_start = SDL_GetTicks(); - SEMAPHORE_SIGNAL(timerWait) -} - -// -// I_SelectTimer -// Sets up the timer function based on if we can use signals for efficent CPU -// usage. -// -void I_SelectTimer() -{ - SEMAPHORE_INIT(timerWait, 0, 0) -#ifndef __sun - signal(SIGALRM, I_HandleAlarm); -#else - struct sigaction alrmaction; - sigaction(SIGALRM, NULL, &alrmaction); - alrmaction.sa_handler = I_HandleAlarm; - sigaction(SIGALRM, &alrmaction, NULL); -#endif - - struct itimerval itv; - itv.it_interval.tv_sec = itv.it_value.tv_sec = 0; - itv.it_interval.tv_usec = itv.it_value.tv_usec = 1000000/TICRATE; - - if (setitimer(ITIMER_REAL, &itv, NULL) != 0) - { - I_GetTime = I_GetTimePolled; - I_FreezeTime = I_FreezeTimePolled; - I_WaitForTic = I_WaitForTicPolled; - } - else - { - I_GetTime = I_GetTimeSignaled; - I_FreezeTime = I_FreezeTimeSignaled; - I_WaitForTic = I_WaitForTicSignaled; - } -} - - -static uint32_t FrameTime; - -void I_SetFrameTime() -{ - FrameTime = SDL_GetTicks(); -} - -// Returns the fractional amount of a tic passed since the most recent tic -double I_GetTimeFrac (uint32_t *ms) -{ - uint32_t now = FrameTime; - if (ms) *ms = TicStart + (1000 / TICRATE); - if (TicStart == 0) - { - return 1; - } - else - { - return clamp((now - TicStart) * TICRATE / 1000., 0, 1); - } -} - void I_InitTimer () { if(SDL_InitSubSystem(SDL_INIT_TIMER) < 0) I_FatalError("Could not initialize SDL timers:\n%s\n", SDL_GetError()); - I_GetTime = I_GetTimeSelect; - I_WaitForTic = I_WaitForTicSelect; - I_FreezeTime = I_FreezeTimeSelect; + // Maybe this file isn't needed at all anymore. + // Someone with Linux should test if the timer subsystem is used elsewhere.. } void I_ShutdownTimer () diff --git a/src/r_utility.cpp b/src/r_utility.cpp index 22fba0f68..6e0f9a92b 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -66,6 +66,7 @@ #include "sbar.h" #include "math/cmath.h" #include "vm.h" +#include "d_main.h" // EXTERNAL DATA DECLARATIONS ---------------------------------------------- @@ -136,8 +137,6 @@ FRenderViewpoint::FRenderViewpoint() FRenderViewpoint r_viewpoint; FViewWindow r_viewwindow; -int otic; - bool r_NoInterpolate; angle_t LocalViewAngle; @@ -784,7 +783,7 @@ void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor iview = FindPastViewer (viewpoint.camera); - int nowtic = I_GetTime (false); + int nowtic = I_GetTime (); if (iview->otic != -1 && nowtic > iview->otic) { iview->otic = nowtic; diff --git a/src/swrenderer/things/r_voxel.cpp b/src/swrenderer/things/r_voxel.cpp index f32452399..4d2d98ab9 100644 --- a/src/swrenderer/things/r_voxel.cpp +++ b/src/swrenderer/things/r_voxel.cpp @@ -40,6 +40,7 @@ #include "r_data/voxels.h" #include "r_data/sprites.h" #include "d_net.h" +#include "d_main.h" #include "po_man.h" #include "r_utility.h" #include "swrenderer/drawers/r_draw.h" diff --git a/src/v_video.cpp b/src/v_video.cpp index 926812534..e7b4e5177 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -84,6 +84,7 @@ #include "r_data/voxels.h" #include "vm.h" #include "r_videoscale.h" +#include "d_main.h" EXTERN_CVAR(Bool, r_blendmethod) @@ -902,7 +903,7 @@ void DFrameBuffer::DrawRateStuff () // draws little dots on the bottom of the screen if (ticker) { - int i = I_GetTime(false); + int i = I_GetTime(); int tics = i - LastTic; uint8_t *buffer = GetBuffer(); diff --git a/src/win32/i_system.cpp b/src/win32/i_system.cpp index 2b4d86567..4a26b24be 100644 --- a/src/win32/i_system.cpp +++ b/src/win32/i_system.cpp @@ -122,10 +122,6 @@ static void CalculateCPUSpeed(); static int I_GetTimePolled(bool saveMS); static int I_WaitForTicPolled(int prevtic); static void I_FreezeTimePolled(bool frozen); -static int I_GetTimeEventDriven(bool saveMS); -static int I_WaitForTicEvent(int prevtic); -static void I_FreezeTimeEventDriven(bool frozen); -static void CALLBACK TimerTicked(UINT id, UINT msg, DWORD_PTR user, DWORD_PTR dw1, DWORD_PTR dw2); static HCURSOR CreateCompatibleCursor(FTexture *cursorpic); static HCURSOR CreateAlphaCursor(FTexture *cursorpic); @@ -174,140 +170,6 @@ static int DefaultWad; static HCURSOR CustomCursor; -//========================================================================== -// -// Tick time functions -// -//========================================================================== - -static LARGE_INTEGER frequency; - -static uint32_t performanceGetTime() -{ - if (frequency.QuadPart != 0) - { - LARGE_INTEGER current; - QueryPerformanceCounter(¤t); - return current.QuadPart * 1000 / frequency.QuadPart; - } - else - { - return timeGetTime(); - } -} - -static unsigned int FirstFrameStartTime; -static unsigned int CurrentFrameStartTime; -static unsigned int FreezeTime; - -void I_SetFrameTime() -{ - // It is critical that all timing is calculated only once at a start of a frame. - // - // performanceGetTime() must only ever be called once or otherwise the playsim - // processing time will affect the interpolation done by the renderer. - - if (FreezeTime == 0) - { - CurrentFrameStartTime = performanceGetTime(); - if (FirstFrameStartTime == 0) - FirstFrameStartTime = CurrentFrameStartTime; - } -} - -void I_WaitVBL(int count) -{ - // I_WaitVBL is never used to actually synchronize to the vertical blank. - // Instead, it's used for delay purposes. Doom used a 70 Hz display mode, - // so that's what we use to determine how long to wait for. - - Sleep(1000 * count / 70); - I_SetFrameTime(); -} - -static int I_WaitForTicWin32(int prevtic) -{ - // Waits until the current tic is greater than prevtic. Time must not be frozen. - - int time; - assert(TicFrozen == 0); - while ((time = I_GetTime(false)) <= prevtic) - { - // The minimum amount of time a thread can sleep is controlled by timeBeginPeriod. - // We set this to 1 ms in DoMain. - int sleepTime = prevtic - time; - if (sleepTime > 2) - Sleep(sleepTime - 2); - - I_SetFrameTime(); - } - - return time; -} - -unsigned int I_FPSTime() -{ - if (FreezeTime == 0) - return CurrentFrameStartTime; - else - return performanceGetTime(); -} - -unsigned int I_MSTime() -{ - if (FreezeTime == 0) - { - return CurrentFrameStartTime - FirstFrameStartTime; - } - else - { - if (FirstFrameStartTime == 0) - { - FirstFrameStartTime = performanceGetTime(); - return 0; - } - else - { - return performanceGetTime() - FirstFrameStartTime; - } - } -} - -int I_GetTimeWin32(bool saveMS) -{ - return (CurrentFrameStartTime - FirstFrameStartTime) * TICRATE / 1000 + 1; -} - -double I_GetTimeFrac(uint32_t *ms) -{ - unsigned int currentTic = (CurrentFrameStartTime - FirstFrameStartTime) * TICRATE / 1000; - unsigned int ticStartTime = FirstFrameStartTime + currentTic * 1000 / TICRATE; - unsigned int ticNextTime = FirstFrameStartTime + (currentTic + 1) * 1000 / TICRATE; - - if (ms) - *ms = currentTic + 1; - - return (CurrentFrameStartTime - ticStartTime) / (double)(ticNextTime - ticStartTime); -} - -void I_FreezeTimeWin32(bool frozen) -{ - if (frozen) - { - FreezeTime = performanceGetTime(); - } - else - { - FirstFrameStartTime += performanceGetTime() - FreezeTime; - FreezeTime = 0; - I_SetFrameTime(); - } -} - -int(*I_GetTime)(bool saveMS) = I_GetTimeWin32; -int(*I_WaitForTic)(int) = I_WaitForTicWin32; -void(*I_FreezeTime)(bool frozen) = I_FreezeTimeWin32; - //========================================================================== // // I_Tactile @@ -543,8 +405,6 @@ void I_Init() CalculateCPUSpeed(); DumpCPUInfo(&CPU); - QueryPerformanceFrequency(&frequency); - atterm (I_ShutdownSound); I_InitSound (); } diff --git a/src/win32/i_system.h b/src/win32/i_system.h index 8c4699c28..a5f7b5d0b 100644 --- a/src/win32/i_system.h +++ b/src/win32/i_system.h @@ -50,21 +50,6 @@ void I_DetectOS (void); // Called by DoomMain. void I_Init (void); -// Called by D_DoomLoop, returns current time in tics. -extern int (*I_GetTime) (bool saveMS); - -// like I_GetTime, except it waits for a new tic before returning -extern int (*I_WaitForTic) (int); - -// Freezes tic counting temporarily. While frozen, calls to I_GetTime() -// will always return the same value. This does not affect I_MSTime(). -// You must also not call I_WaitForTic() while freezing time, since the -// tic will never arrive (unless it's the current one). -extern void (*I_FreezeTime) (bool frozen); - -double I_GetTimeFrac (uint32_t *ms); -void I_SetFrameTime(); - // Return a seed value for the RNG. unsigned int I_MakeRNGSeed(); @@ -132,10 +117,6 @@ int I_PickIWad (WadStuff *wads, int numwads, bool queryiwad, int defaultiwad); // The ini could not be saved at exit bool I_WriteIniFailed (); -// [RH] Returns millisecond-accurate time -unsigned int I_MSTime (void); -unsigned int I_FPSTime(); - // [RH] Used by the display code to set the normal window procedure void I_SetWndProc(); From 7d63c3324d391090f59f6c97efa5f794dbfa94ca Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 12 Nov 2017 03:51:37 +0100 Subject: [PATCH 04/17] - Fix macOS compile errors --- src/posix/cocoa/i_system.mm | 12 ------------ src/posix/i_system.h | 16 ---------------- 2 files changed, 28 deletions(-) diff --git a/src/posix/cocoa/i_system.mm b/src/posix/cocoa/i_system.mm index 7b7c6dcc2..3390d65ba 100644 --- a/src/posix/cocoa/i_system.mm +++ b/src/posix/cocoa/i_system.mm @@ -73,18 +73,6 @@ ticcmd_t* I_BaseTiccmd() } -void I_WaitVBL(const int count) -{ - // I_WaitVBL is never used to actually synchronize to the - // vertical blank. Instead, it's used for delay purposes. - struct timespec delay, rem; - delay.tv_sec = count / 70; - /* Avoid overflow. Microsec res should be good enough. */ - delay.tv_nsec = (count%70)*1000000/70 * 1000; - while(nanosleep(&delay, &rem) == -1 && errno == EINTR) - delay = rem; -} - // // SetLanguageIDs diff --git a/src/posix/i_system.h b/src/posix/i_system.h index 7e9f83939..7f468f143 100644 --- a/src/posix/i_system.h +++ b/src/posix/i_system.h @@ -57,22 +57,6 @@ extern void SetLanguageIDs (); // Called by DoomMain. void I_Init (void); -// Called by D_DoomLoop, -// returns current time in tics. -extern int (*I_GetTime) (bool saveMS); - -// like I_GetTime, except it waits for a new tic before returning -extern int (*I_WaitForTic) (int); - -// Freezes tic counting temporarily. While frozen, calls to I_GetTime() -// will always return the same value. This does not affect I_MSTime(). -// You must also not call I_WaitForTic() while freezing time, since the -// tic will never arrive (unless it's the current one). -extern void (*I_FreezeTime) (bool frozen); - -double I_GetTimeFrac (uint32_t *ms); -void I_SetFrameTime(); - // Return a seed value for the RNG. unsigned int I_MakeRNGSeed(); From 6bd76d6b5adf230c190fe709889c639f38a5e0fd Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 12 Nov 2017 09:06:40 +0100 Subject: [PATCH 05/17] - fixed compilation in debug mode. - moved timer definitions into their own header/source files. d_main is not the right place for this. - removed some leftover cruft from the old timer code. --- src/CMakeLists.txt | 1 + src/c_bind.cpp | 2 +- src/c_console.cpp | 2 +- src/d_main.cpp | 124 +---------------------- src/d_main.h | 21 ---- src/d_net.cpp | 10 +- src/dobject.cpp | 2 +- src/doomdef.h | 18 ++-- src/g_game.cpp | 1 + src/g_level.cpp | 2 +- src/gl/models/gl_models.cpp | 2 +- src/gl/scene/gl_scene.cpp | 2 +- src/gl/utility/gl_clock.cpp | 2 +- src/i_time.cpp | 161 ++++++++++++++++++++++++++++++ src/i_time.h | 24 +++++ src/menu/videomenu.cpp | 2 +- src/p_glnodes.cpp | 2 +- src/p_setup.cpp | 2 +- src/posix/cocoa/st_console.mm | 1 + src/posix/sdl/i_system.cpp | 4 - src/r_utility.cpp | 2 +- src/swrenderer/things/r_voxel.cpp | 2 +- src/v_video.cpp | 2 +- src/win32/i_input.h | 1 + 24 files changed, 220 insertions(+), 172 deletions(-) create mode 100644 src/i_time.cpp create mode 100644 src/i_time.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7ede5128b..189ca980c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -877,6 +877,7 @@ set (PCH_SOURCES hu_scores.cpp i_module.cpp i_net.cpp + i_time.cpp info.cpp keysections.cpp lumpconfigfile.cpp diff --git a/src/c_bind.cpp b/src/c_bind.cpp index 8fb29de87..83e5e1820 100644 --- a/src/c_bind.cpp +++ b/src/c_bind.cpp @@ -47,7 +47,7 @@ #include "templates.h" #include "dobject.h" #include "vm.h" -#include "d_main.h" +#include "i_time.h" #include #include diff --git a/src/c_console.cpp b/src/c_console.cpp index 4d8d64dd8..c3ab76903 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -69,7 +69,7 @@ #include "c_consolebuffer.h" #include "g_levellocals.h" #include "vm.h" -#include "d_main.h" +#include "i_time.h" FString FStringFormat(VM_ARGS); // extern from thingdef_data.cpp diff --git a/src/d_main.cpp b/src/d_main.cpp index 21383118d..7c426375a 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -51,6 +51,7 @@ #include "doomerrors.h" +#include "i_time.h" #include "d_gui.h" #include "m_random.h" #include "doomdef.h" @@ -117,8 +118,6 @@ #include "vm.h" #include "types.h" #include "r_data/r_vanillatrans.h" -#include -#include EXTERN_CVAR(Bool, hud_althud) void DrawHUD(); @@ -1082,127 +1081,6 @@ void D_DoomLoop () } } -//========================================================================== -// -// Tick time functions -// -//========================================================================== - -static unsigned int FirstFrameStartTime; -static unsigned int CurrentFrameStartTime; -static unsigned int FreezeTime; - -static uint32_t performanceGetTime() -{ - using namespace std::chrono; - return (uint32_t)duration_cast(steady_clock::now().time_since_epoch()).count(); -} - -void I_SetFrameTime() -{ - // Must only be called once per frame/swapbuffers. - // - // Caches all timing information for the current rendered frame so that any - // calls to I_FPSTime, I_MSTime, I_GetTime or I_GetTimeFrac will return - // the same time. - - if (FreezeTime == 0) - { - CurrentFrameStartTime = performanceGetTime(); - if (FirstFrameStartTime == 0) - FirstFrameStartTime = CurrentFrameStartTime; - } -} - -void I_WaitVBL(int count) -{ - // I_WaitVBL is never used to actually synchronize to the vertical blank. - // Instead, it's used for delay purposes. Doom used a 70 Hz display mode, - // so that's what we use to determine how long to wait for. - - std::this_thread::sleep_for(std::chrono::milliseconds(1000 * count / 70)); - I_SetFrameTime(); -} - -int I_WaitForTic(int prevtic) -{ - // Waits until the current tic is greater than prevtic. Time must not be frozen. - - int time; - assert(TicFrozen == 0); - while ((time = I_GetTime()) <= prevtic) - { - // The minimum amount of time a thread can sleep is controlled by timeBeginPeriod. - // We set this to 1 ms in DoMain. - int sleepTime = prevtic - time; - if (sleepTime > 2) - std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime - 2)); - - I_SetFrameTime(); - } - - return time; -} - -unsigned int I_FPSTime() -{ - if (FreezeTime == 0) - return CurrentFrameStartTime; - else - return performanceGetTime(); -} - -unsigned int I_MSTime() -{ - if (FreezeTime == 0) - { - return CurrentFrameStartTime - FirstFrameStartTime; - } - else - { - if (FirstFrameStartTime == 0) - { - FirstFrameStartTime = performanceGetTime(); - return 0; - } - else - { - return performanceGetTime() - FirstFrameStartTime; - } - } -} - -int I_GetTime() -{ - return (CurrentFrameStartTime - FirstFrameStartTime) * TICRATE / 1000 + 1; -} - -double I_GetTimeFrac(uint32_t *ms) -{ - unsigned int currentTic = (CurrentFrameStartTime - FirstFrameStartTime) * TICRATE / 1000; - unsigned int ticStartTime = FirstFrameStartTime + currentTic * 1000 / TICRATE; - unsigned int ticNextTime = FirstFrameStartTime + (currentTic + 1) * 1000 / TICRATE; - - if (ms) - *ms = currentTic + 1; - - return (CurrentFrameStartTime - ticStartTime) / (double)(ticNextTime - ticStartTime); -} - -void I_FreezeTime(bool frozen) -{ - if (frozen) - { - FreezeTime = performanceGetTime(); - } - else - { - FirstFrameStartTime += performanceGetTime() - FreezeTime; - FreezeTime = 0; - I_SetFrameTime(); - } -} - //========================================================================== // // D_PageTicker diff --git a/src/d_main.h b/src/d_main.h index 73690cc05..5addc5eb4 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -162,25 +162,4 @@ public: }; -// Called by D_DoomLoop, sets the time for the current frame -void I_SetFrameTime(); - -// Called by D_DoomLoop, returns current time in tics. -int I_GetTime(); - -double I_GetTimeFrac(uint32_t *ms); - -// like I_GetTime, except it waits for a new tic before returning -int I_WaitForTic(int); - -// Freezes tic counting temporarily. While frozen, calls to I_GetTime() -// will always return the same value. This does not affect I_MSTime(). -// You must also not call I_WaitForTic() while freezing time, since the -// tic will never arrive (unless it's the current one). -void I_FreezeTime(bool frozen); - -// [RH] Returns millisecond-accurate time -unsigned int I_MSTime(); -unsigned int I_FPSTime(); - #endif diff --git a/src/d_net.cpp b/src/d_net.cpp index 42f4d425a..12de17c9e 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -68,7 +68,7 @@ #include "intermission/intermission.h" #include "g_levellocals.h" #include "events.h" -#include "d_main.h" +#include "i_time.h" EXTERN_CVAR (Int, disableautosave) EXTERN_CVAR (Int, autosavecount) @@ -532,7 +532,7 @@ void HSendPacket (int node, int len) { PacketStore store; store.message = doomcom; - store.timer = I_GetTime(false) + ((net_fakelatency / 2) / (1000 / TICRATE)); + store.timer = I_GetTime() + ((net_fakelatency / 2) / (1000 / TICRATE)); OutBuffer.Push(store); } else @@ -540,7 +540,7 @@ void HSendPacket (int node, int len) for (unsigned int i = 0; i < OutBuffer.Size(); i++) { - if (OutBuffer[i].timer <= I_GetTime(false)) + if (OutBuffer[i].timer <= I_GetTime()) { doomcom = OutBuffer[i].message; I_NetCmd(); @@ -581,7 +581,7 @@ bool HGetPacket (void) { PacketStore store; store.message = doomcom; - store.timer = I_GetTime(false) + ((net_fakelatency / 2) / (1000 / TICRATE)); + store.timer = I_GetTime() + ((net_fakelatency / 2) / (1000 / TICRATE)); InBuffer.Push(store); doomcom.remotenode = -1; } @@ -591,7 +591,7 @@ bool HGetPacket (void) bool gotmessage = false; for (unsigned int i = 0; i < InBuffer.Size(); i++) { - if (InBuffer[i].timer <= I_GetTime(false)) + if (InBuffer[i].timer <= I_GetTime()) { doomcom = InBuffer[i].message; InBuffer.Delete(i); diff --git a/src/dobject.cpp b/src/dobject.cpp index 1e399908e..17b9743f3 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -51,7 +51,7 @@ #include "vm.h" #include "g_levellocals.h" #include "types.h" -#include "d_main.h" +#include "i_time.h" //========================================================================== // diff --git a/src/doomdef.h b/src/doomdef.h index e64e5e215..b324fa90f 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -57,14 +57,19 @@ typedef enum #endif #endif -// The maximum number of players, multiplayer/networking. -#define MAXPLAYERS 8 +// Global constants that were defines. +enum +{ + // The maximum number of players, multiplayer/networking. + MAXPLAYERS = 8, -// State updates, number of tics / second. -#define TICRATE 35 + // State updates, number of tics / second. + TICRATE = 35, + + // Amount of damage done by a telefrag. + TELEFRAG_DAMAGE = 1000000 +}; -// Amount of damage done by a telefrag. -#define TELEFRAG_DAMAGE 1000000 // The current state of the game: whether we are // playing, gazing at the intermission screen, @@ -114,6 +119,7 @@ enum ESkillLevels // DOOM keyboard definition. Everything below 0x100 matches // a mode 1 keyboard scan code. // + #define KEY_PAUSE 0xc5 // DIK_PAUSE #define KEY_RIGHTARROW 0xcd // DIK_RIGHT #define KEY_LEFTARROW 0xcb // DIK_LEFT diff --git a/src/g_game.cpp b/src/g_game.cpp index 77db68a8d..ec1a7be50 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -32,6 +32,7 @@ #include #endif +#include "i_time.h" #include "templates.h" #include "version.h" #include "doomdef.h" diff --git a/src/g_level.cpp b/src/g_level.cpp index 5309e72cc..a2b15b02d 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -94,7 +94,7 @@ #include "g_levellocals.h" #include "actorinlines.h" #include "vm.h" -#include "d_main.h" +#include "i_time.h" #include diff --git a/src/gl/models/gl_models.cpp b/src/gl/models/gl_models.cpp index 2e6df1ed5..4b7054c2a 100644 --- a/src/gl/models/gl_models.cpp +++ b/src/gl/models/gl_models.cpp @@ -39,7 +39,7 @@ #include "d_player.h" #include "g_levellocals.h" #include "r_utility.h" -#include "d_main.h" +#include "i_time.h" //#include "resources/voxels.h" //#include "gl/gl_intern.h" diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index ce5fb524f..ae9e08989 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -26,6 +26,7 @@ */ #include "gl/system/gl_system.h" +#include "i_time.h" #include "gi.h" #include "m_png.h" #include "m_random.h" @@ -45,7 +46,6 @@ #include "serializer.h" #include "g_levellocals.h" #include "events.h" -#include "d_main.h" #include "gl/dynlights/gl_lightbuffer.h" #include "gl/system/gl_interface.h" diff --git a/src/gl/utility/gl_clock.cpp b/src/gl/utility/gl_clock.cpp index 27e740318..5cd1daa21 100644 --- a/src/gl/utility/gl_clock.cpp +++ b/src/gl/utility/gl_clock.cpp @@ -52,7 +52,7 @@ #include "g_levellocals.h" #include "gl/utility/gl_clock.h" #include "gl/utility/gl_convert.h" -#include "d_main.h" +#include "i_time.h" glcycle_t RenderWall,SetupWall,ClipWall; glcycle_t RenderFlat,SetupFlat; diff --git a/src/i_time.cpp b/src/i_time.cpp new file mode 100644 index 000000000..47b1b8bdd --- /dev/null +++ b/src/i_time.cpp @@ -0,0 +1,161 @@ +/* +** i_time.cpp +** Implements the timer +** +**--------------------------------------------------------------------------- +** Copyright 1998-2916 Randy Heit +** Copyright 2917 Magnus Norddahl +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include +#include +#include +#include "i_time.h" +#include "doomdef.h" + +//========================================================================== +// +// Tick time functions +// +//========================================================================== + +static unsigned int FirstFrameStartTime; +static unsigned int CurrentFrameStartTime; +static unsigned int FreezeTime; + +static uint32_t performanceGetTime() +{ + using namespace std::chrono; + return (uint32_t)duration_cast(steady_clock::now().time_since_epoch()).count(); +} + +void I_SetFrameTime() +{ + // Must only be called once per frame/swapbuffers. + // + // Caches all timing information for the current rendered frame so that any + // calls to I_FPSTime, I_MSTime, I_GetTime or I_GetTimeFrac will return + // the same time. + + if (FreezeTime == 0) + { + CurrentFrameStartTime = performanceGetTime(); + if (FirstFrameStartTime == 0) + FirstFrameStartTime = CurrentFrameStartTime; + } +} + +void I_WaitVBL(int count) +{ + // I_WaitVBL is never used to actually synchronize to the vertical blank. + // Instead, it's used for delay purposes. Doom used a 70 Hz display mode, + // so that's what we use to determine how long to wait for. + + std::this_thread::sleep_for(std::chrono::milliseconds(1000 * count / 70)); + I_SetFrameTime(); +} + +int I_WaitForTic(int prevtic) +{ + // Waits until the current tic is greater than prevtic. Time must not be frozen. + + int time; + while ((time = I_GetTime()) <= prevtic) + { + // The minimum amount of time a thread can sleep is controlled by timeBeginPeriod. + // We set this to 1 ms in DoMain. + int sleepTime = prevtic - time; + if (sleepTime > 2) + std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime - 2)); + + I_SetFrameTime(); + } + + return time; +} + +unsigned int I_FPSTime() +{ + if (FreezeTime == 0) + return CurrentFrameStartTime; + else + return performanceGetTime(); +} + +unsigned int I_MSTime() +{ + if (FreezeTime == 0) + { + return CurrentFrameStartTime - FirstFrameStartTime; + } + else + { + if (FirstFrameStartTime == 0) + { + FirstFrameStartTime = performanceGetTime(); + return 0; + } + else + { + return performanceGetTime() - FirstFrameStartTime; + } + } +} + +int I_GetTime() +{ + return (CurrentFrameStartTime - FirstFrameStartTime) * TICRATE / 1000 + 1; +} + +double I_GetTimeFrac(uint32_t *ms) +{ + unsigned int currentTic = (CurrentFrameStartTime - FirstFrameStartTime) * TICRATE / 1000; + unsigned int ticStartTime = FirstFrameStartTime + currentTic * 1000 / TICRATE; + unsigned int ticNextTime = FirstFrameStartTime + (currentTic + 1) * 1000 / TICRATE; + + if (ms) + *ms = currentTic + 1; + + return (CurrentFrameStartTime - ticStartTime) / (double)(ticNextTime - ticStartTime); +} + +void I_FreezeTime(bool frozen) +{ + if (frozen) + { + FreezeTime = performanceGetTime(); + } + else + { + FirstFrameStartTime += performanceGetTime() - FreezeTime; + FreezeTime = 0; + I_SetFrameTime(); + } +} + diff --git a/src/i_time.h b/src/i_time.h new file mode 100644 index 000000000..19d047cc2 --- /dev/null +++ b/src/i_time.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +// Called by D_DoomLoop, sets the time for the current frame +void I_SetFrameTime(); + +// Called by D_DoomLoop, returns current time in tics. +int I_GetTime(); + +double I_GetTimeFrac(uint32_t *ms); + +// like I_GetTime, except it waits for a new tic before returning +int I_WaitForTic(int); + +// Freezes tic counting temporarily. While frozen, calls to I_GetTime() +// will always return the same value. This does not affect I_MSTime(). +// You must also not call I_WaitForTic() while freezing time, since the +// tic will never arrive (unless it's the current one). +void I_FreezeTime(bool frozen); + +// [RH] Returns millisecond-accurate time +unsigned int I_MSTime(); +unsigned int I_FPSTime(); diff --git a/src/menu/videomenu.cpp b/src/menu/videomenu.cpp index 74fe71b67..d3ba14e92 100644 --- a/src/menu/videomenu.cpp +++ b/src/menu/videomenu.cpp @@ -55,7 +55,7 @@ #include "hardware.h" #include "vm.h" #include "r_videoscale.h" -#include "d_main.h" +#include "i_time.h" /*======================================= * diff --git a/src/p_glnodes.cpp b/src/p_glnodes.cpp index 8ec8ed8c3..3559887fa 100644 --- a/src/p_glnodes.cpp +++ b/src/p_glnodes.cpp @@ -68,7 +68,7 @@ #include "r_utility.h" #include "cmdlib.h" #include "g_levellocals.h" -#include "d_main.h" +#include "i_time.h" void P_GetPolySpots (MapData * lump, TArray &spots, TArray &anchors); diff --git a/src/p_setup.cpp b/src/p_setup.cpp index cb8b6e5b6..fb2f1cdb7 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -115,7 +115,7 @@ #endif #include "events.h" #include "types.h" -#include "d_main.h" +#include "i_time.h" #include "fragglescript/t_fs.h" diff --git a/src/posix/cocoa/st_console.mm b/src/posix/cocoa/st_console.mm index 87d93038f..216e795bd 100644 --- a/src/posix/cocoa/st_console.mm +++ b/src/posix/cocoa/st_console.mm @@ -38,6 +38,7 @@ #include "st_console.h" #include "v_text.h" #include "version.h" +#include "i_time.h" static NSColor* RGB(const uint8_t red, const uint8_t green, const uint8_t blue) diff --git a/src/posix/sdl/i_system.cpp b/src/posix/sdl/i_system.cpp index 02dc270e4..43b830490 100644 --- a/src/posix/sdl/i_system.cpp +++ b/src/posix/sdl/i_system.cpp @@ -86,10 +86,6 @@ int I_PickIWad_Cocoa (WadStuff *wads, int numwads, bool showwin, int defaultiwad double PerfToSec, PerfToMillisec; uint32_t LanguageIDs[4]; -int (*I_GetTime) (bool saveMS); -int (*I_WaitForTic) (int); -void (*I_FreezeTime) (bool frozen); - void I_Tactile (int /*on*/, int /*off*/, int /*total*/) { } diff --git a/src/r_utility.cpp b/src/r_utility.cpp index 6e0f9a92b..8a18c433d 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -66,7 +66,7 @@ #include "sbar.h" #include "math/cmath.h" #include "vm.h" -#include "d_main.h" +#include "i_time.h" // EXTERNAL DATA DECLARATIONS ---------------------------------------------- diff --git a/src/swrenderer/things/r_voxel.cpp b/src/swrenderer/things/r_voxel.cpp index 4d2d98ab9..8f2b80f0b 100644 --- a/src/swrenderer/things/r_voxel.cpp +++ b/src/swrenderer/things/r_voxel.cpp @@ -40,9 +40,9 @@ #include "r_data/voxels.h" #include "r_data/sprites.h" #include "d_net.h" -#include "d_main.h" #include "po_man.h" #include "r_utility.h" +#include "i_time.h" #include "swrenderer/drawers/r_draw.h" #include "swrenderer/drawers/r_thread.h" #include "swrenderer/things/r_visiblesprite.h" diff --git a/src/v_video.cpp b/src/v_video.cpp index e7b4e5177..d47ece201 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -84,7 +84,7 @@ #include "r_data/voxels.h" #include "vm.h" #include "r_videoscale.h" -#include "d_main.h" +#include "i_time.h" EXTERN_CVAR(Bool, r_blendmethod) diff --git a/src/win32/i_input.h b/src/win32/i_input.h index 500e27bb7..529ea83f5 100644 --- a/src/win32/i_input.h +++ b/src/win32/i_input.h @@ -56,6 +56,7 @@ enum // Don't make these definitions available to the main body of the source code. + struct tagRAWINPUT; class FInputDevice From d9808e6d68548e3f0050dcf4bb29daadd68a57c0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 12 Nov 2017 10:02:29 +0100 Subject: [PATCH 06/17] - there were still some old definitions left... --- src/posix/cocoa/i_system.mm | 5 ----- src/win32/i_system.cpp | 4 ---- 2 files changed, 9 deletions(-) diff --git a/src/posix/cocoa/i_system.mm b/src/posix/cocoa/i_system.mm index 3390d65ba..cc9dc613a 100644 --- a/src/posix/cocoa/i_system.mm +++ b/src/posix/cocoa/i_system.mm @@ -56,11 +56,6 @@ EXTERN_CVAR(String, language) uint32_t LanguageIDs[4]; -int (*I_GetTime)(bool saveMS); -int (*I_WaitForTic)(int); -void (*I_FreezeTime)(bool frozen); - - void I_Tactile(int /*on*/, int /*off*/, int /*total*/) { } diff --git a/src/win32/i_system.cpp b/src/win32/i_system.cpp index 4a26b24be..a537329e4 100644 --- a/src/win32/i_system.cpp +++ b/src/win32/i_system.cpp @@ -119,10 +119,6 @@ extern void LayoutMainWindow(HWND hWnd, HWND pane); static void CalculateCPUSpeed(); -static int I_GetTimePolled(bool saveMS); -static int I_WaitForTicPolled(int prevtic); -static void I_FreezeTimePolled(bool frozen); - static HCURSOR CreateCompatibleCursor(FTexture *cursorpic); static HCURSOR CreateAlphaCursor(FTexture *cursorpic); static HCURSOR CreateBitmapCursor(int xhot, int yhot, HBITMAP and_mask, HBITMAP color_mask); From e50b012c87e493b28f89bd05b7f7945d80a3cc62 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 12 Nov 2017 12:04:11 +0100 Subject: [PATCH 07/17] - fixed: Model rotation should use the time of the current frame's start, not the time of the time of processing the particular actor. Reading the time directly would result in different values for different viewpoints in a scene or for different objects in the same scene which is not how this is supposed to work. --- src/gl/models/gl_models.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gl/models/gl_models.cpp b/src/gl/models/gl_models.cpp index 4b7054c2a..6ef0acbfc 100644 --- a/src/gl/models/gl_models.cpp +++ b/src/gl/models/gl_models.cpp @@ -55,7 +55,7 @@ static inline float GetTimeFloat() { - return (float)I_MSTime() * (float)TICRATE / 1000.0f; + return (float)gl_frameMS * (float)TICRATE / 1000.0f; } CVAR(Bool, gl_interpolate_model_frames, true, CVAR_ARCHIVE) From 0db0f2f7b95e7268ab4dc0e44a6503bbee7ac11f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 12 Nov 2017 12:12:51 +0100 Subject: [PATCH 08/17] - removed redundant POSIX version of I_WaitVBL --- src/posix/sdl/i_system.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/posix/sdl/i_system.cpp b/src/posix/sdl/i_system.cpp index 43b830490..903563da0 100644 --- a/src/posix/sdl/i_system.cpp +++ b/src/posix/sdl/i_system.cpp @@ -105,18 +105,6 @@ void I_EndRead(void) } -void I_WaitVBL (int count) -{ - // I_WaitVBL is never used to actually synchronize to the - // vertical blank. Instead, it's used for delay purposes. - struct timespec delay, rem; - delay.tv_sec = count / 70; - /* Avoid overflow. Microsec res should be good enough. */ - delay.tv_nsec = (count%70)*1000000/70 * 1000; - while(nanosleep(&delay, &rem) == -1 && errno == EINTR) - delay = rem; -} - // // SetLanguageIDs // From e3141a4af37094335d76716e55aeba98714b1446 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 12 Nov 2017 12:57:19 +0100 Subject: [PATCH 09/17] - Upgrade timer code to use nanosecond accuracy internally --- src/i_time.cpp | 76 +++++++++++++++++++++++++++++++++++--------------- src/i_time.h | 4 +++ 2 files changed, 57 insertions(+), 23 deletions(-) diff --git a/src/i_time.cpp b/src/i_time.cpp index 47b1b8bdd..2c5727a4b 100644 --- a/src/i_time.cpp +++ b/src/i_time.cpp @@ -45,14 +45,34 @@ // //========================================================================== -static unsigned int FirstFrameStartTime; -static unsigned int CurrentFrameStartTime; -static unsigned int FreezeTime; +static uint64_t FirstFrameStartTime; +static uint64_t CurrentFrameStartTime; +static uint64_t FreezeTime; -static uint32_t performanceGetTime() +static uint64_t GetClockTimeNS() { using namespace std::chrono; - return (uint32_t)duration_cast(steady_clock::now().time_since_epoch()).count(); + return (uint64_t)duration_cast(steady_clock::now().time_since_epoch()).count(); +} + +static uint64_t MSToNS(unsigned int ms) +{ + return static_cast(ms) * 1'000'000; +} + +static uint32_t NSToMS(uint64_t ns) +{ + return static_cast(ns / 1'000'000); +} + +static int NSToTic(uint64_t ns) +{ + return static_cast(ns * TICRATE / 1'000'000'000); +} + +static uint64_t TicToNS(int tic) +{ + return static_cast(tic) * 1'000'000'000 / TICRATE; } void I_SetFrameTime() @@ -65,7 +85,7 @@ void I_SetFrameTime() if (FreezeTime == 0) { - CurrentFrameStartTime = performanceGetTime(); + CurrentFrameStartTime = GetClockTimeNS(); if (FirstFrameStartTime == 0) FirstFrameStartTime = CurrentFrameStartTime; } @@ -100,15 +120,7 @@ int I_WaitForTic(int prevtic) return time; } -unsigned int I_FPSTime() -{ - if (FreezeTime == 0) - return CurrentFrameStartTime; - else - return performanceGetTime(); -} - -unsigned int I_MSTime() +uint64_t I_NSTime() { if (FreezeTime == 0) { @@ -118,26 +130,44 @@ unsigned int I_MSTime() { if (FirstFrameStartTime == 0) { - FirstFrameStartTime = performanceGetTime(); + FirstFrameStartTime = GetClockTimeNS(); return 0; } else { - return performanceGetTime() - FirstFrameStartTime; + return GetClockTimeNS() - FirstFrameStartTime; } } } +uint64_t I_FPSTimeNS() +{ + if (FreezeTime == 0) + return NSToMS(CurrentFrameStartTime); + else + return NSToMS(GetClockTimeNS()); +} + +unsigned int I_MSTime() +{ + return NSToMS(I_NSTime()); +} + +unsigned int I_FPSTime() +{ + return NSToMS(I_FPSTimeNS()); +} + int I_GetTime() { - return (CurrentFrameStartTime - FirstFrameStartTime) * TICRATE / 1000 + 1; + return NSToTic(CurrentFrameStartTime - FirstFrameStartTime) + 1; } double I_GetTimeFrac(uint32_t *ms) { - unsigned int currentTic = (CurrentFrameStartTime - FirstFrameStartTime) * TICRATE / 1000; - unsigned int ticStartTime = FirstFrameStartTime + currentTic * 1000 / TICRATE; - unsigned int ticNextTime = FirstFrameStartTime + (currentTic + 1) * 1000 / TICRATE; + int currentTic = NSToTic(CurrentFrameStartTime - FirstFrameStartTime); + uint64_t ticStartTime = FirstFrameStartTime + TicToNS(currentTic); + uint64_t ticNextTime = FirstFrameStartTime + TicToNS(currentTic + 1); if (ms) *ms = currentTic + 1; @@ -149,11 +179,11 @@ void I_FreezeTime(bool frozen) { if (frozen) { - FreezeTime = performanceGetTime(); + FreezeTime = GetClockTimeNS(); } else { - FirstFrameStartTime += performanceGetTime() - FreezeTime; + FirstFrameStartTime += GetClockTimeNS() - FreezeTime; FreezeTime = 0; I_SetFrameTime(); } diff --git a/src/i_time.h b/src/i_time.h index 19d047cc2..5d1514924 100644 --- a/src/i_time.h +++ b/src/i_time.h @@ -22,3 +22,7 @@ void I_FreezeTime(bool frozen); // [RH] Returns millisecond-accurate time unsigned int I_MSTime(); unsigned int I_FPSTime(); + +// Nanosecond-accurate time +uint64_t I_NSTime(); +uint64_t I_FPSTimeNS(); From efa7c3cacf11767ad68cafe80d4517748cd0726d Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 12 Nov 2017 13:22:52 +0100 Subject: [PATCH 10/17] - Fix typo in I_FPSTimeNS --- src/i_time.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i_time.cpp b/src/i_time.cpp index 2c5727a4b..908dbdd59 100644 --- a/src/i_time.cpp +++ b/src/i_time.cpp @@ -143,9 +143,9 @@ uint64_t I_NSTime() uint64_t I_FPSTimeNS() { if (FreezeTime == 0) - return NSToMS(CurrentFrameStartTime); + return CurrentFrameStartTime; else - return NSToMS(GetClockTimeNS()); + return GetClockTimeNS(); } unsigned int I_MSTime() From 0289d9ad9f9544e2cca51e3ef45653dc4c9773ec Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 12 Nov 2017 13:49:53 +0100 Subject: [PATCH 11/17] - the timing compensation which was necessary for millisecond-precise timing is not needed anymore with nanoseconds. --- src/cmdlib.h | 16 +--------------- src/statistics.cpp | 4 ++-- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/src/cmdlib.h b/src/cmdlib.h index 605a56995..f8fdfc496 100644 --- a/src/cmdlib.h +++ b/src/cmdlib.h @@ -65,23 +65,9 @@ struct FFileList void ScanDirectory(TArray &list, const char *dirpath); -//========================================================================== -// -// Functions to compensate for a tic being a bit short. -// Since ZDoom uses a milliseconds timer for game timing -// 35 tics are actually only 0.98 seconds. -// For real time display this needs to be adjusted -// -//========================================================================== - -inline int AdjustTics(int tics) -{ - return Scale(tics, 98, 100); -} - inline int Tics2Seconds(int tics) { - return Scale(tics, 98, (100 * TICRATE)); + return tics * TICRATE; } diff --git a/src/statistics.cpp b/src/statistics.cpp index e96f10327..2abd0bf12 100644 --- a/src/statistics.cpp +++ b/src/statistics.cpp @@ -420,7 +420,7 @@ static void StoreLevelStats() LevelData[i].killcount = level.killed_monsters; LevelData[i].totalsecrets = level.total_secrets; LevelData[i].secretcount = level.found_secrets; - LevelData[i].leveltime = AdjustTics(level.maptime); + LevelData[i].leveltime = level.maptime; // Check for living monsters. On some maps it can happen // that the counter misses some. @@ -490,7 +490,7 @@ void STAT_ChangeLevel(const char *newl) } infostring.Format("%4d/%4d, %3d/%3d, %2d", statvals[0], statvals[1], statvals[2], statvals[3], validlevels); - FSessionStatistics *es = StatisticsEntry(sl, infostring, AdjustTics(level.totaltime)); + FSessionStatistics *es = StatisticsEntry(sl, infostring, level.totaltime); for(unsigned i = 0; i < LevelData.Size(); i++) { From 93e9c383faee3ea4971ec365bc14e71d09d07f06 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 12 Nov 2017 18:51:11 +0100 Subject: [PATCH 12/17] - get the timer used for animation only once at the very beginning of the frame and pass it on to the renderer to avoid any dependencies on the timer's implementation. --- src/d_main.cpp | 2 +- src/gl/renderer/gl_renderer.h | 2 +- src/gl/scene/gl_scene.cpp | 10 +++++----- src/gl/scene/gl_scenedrawer.h | 2 +- src/r_renderer.h | 2 +- src/swrenderer/r_swrenderer.cpp | 2 +- src/swrenderer/r_swrenderer.h | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 7c426375a..5e0eff1d1 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -808,7 +808,7 @@ void D_Display () // [ZZ] execute event hook that we just started the frame //E_RenderFrame(); // - Renderer->RenderView(&players[consoleplayer]); + Renderer->RenderView(&players[consoleplayer], nowtime); if ((hw2d = screen->Begin2D(viewactive))) { diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h index e3924ad40..f8d710467 100644 --- a/src/gl/renderer/gl_renderer.h +++ b/src/gl/renderer/gl_renderer.h @@ -171,7 +171,7 @@ public: unsigned char *GetTextureBuffer(FTexture *tex, int &w, int &h); void SetupLevel(); - void RenderView(player_t* player); + void RenderView(player_t* player, unsigned int nowtime); void RenderScreenQuad(); void PostProcessScene(int fixedcm); diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index ae9e08989..c900c21d7 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -878,7 +878,7 @@ sector_t * GLSceneDrawer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, f // //----------------------------------------------------------------------------- -void FGLRenderer::RenderView (player_t* player) +void FGLRenderer::RenderView (player_t* player, unsigned int nowtime) { checkBenchActive(); @@ -891,7 +891,7 @@ void FGLRenderer::RenderView (player_t* player) // Get this before everything else if (cl_capfps || r_NoInterpolate) r_viewpoint.TicFrac = 1.; else r_viewpoint.TicFrac = I_GetTimeFrac (&r_viewpoint.FrameTime); - gl_frameMS = I_MSTime(); + gl_frameMS = nowtime; P_FindParticleSubsectors (); @@ -984,7 +984,7 @@ void GLSceneDrawer::WriteSavePic (player_t *player, FileWriter *file, int width, struct FGLInterface : public FRenderer { void Precache(uint8_t *texhitlist, TMap &actorhitlist) override; - void RenderView(player_t *player) override; + void RenderView(player_t *player, unsigned int nowtime) override; void WriteSavePic (player_t *player, FileWriter *file, int width, int height) override; void StartSerialize(FSerializer &arc) override; void EndSerialize(FSerializer &arc) override; @@ -1075,9 +1075,9 @@ void FGLInterface::WriteSavePic (player_t *player, FileWriter *file, int width, // //=========================================================================== -void FGLInterface::RenderView(player_t *player) +void FGLInterface::RenderView(player_t *player, unsigned int nowtime) { - GLRenderer->RenderView(player); + GLRenderer->RenderView(player, nowtime); } //=========================================================================== diff --git a/src/gl/scene/gl_scenedrawer.h b/src/gl/scene/gl_scenedrawer.h index 9209e6dad..6e4fa143d 100644 --- a/src/gl/scene/gl_scenedrawer.h +++ b/src/gl/scene/gl_scenedrawer.h @@ -60,7 +60,7 @@ public: void CheckViewArea(vertex_t *v1, vertex_t *v2, sector_t *frontsector, sector_t *backsector); sector_t *RenderViewpoint(AActor * camera, GL_IRECT * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen); - void RenderView(player_t *player); + void RenderView(player_t *player, unsigned int nowtime); void WriteSavePic(player_t *player, FileWriter *file, int width, int height); void DrawPSprite(player_t * player, DPSprite *psp, float sx, float sy, bool hudModelStep, int OverrideShader, bool alphatexture); diff --git a/src/r_renderer.h b/src/r_renderer.h index 54952bc29..0165c33b8 100644 --- a/src/r_renderer.h +++ b/src/r_renderer.h @@ -29,7 +29,7 @@ struct FRenderer virtual void Precache(uint8_t *texhitlist, TMap &actorhitlist) = 0; // render 3D view - virtual void RenderView(player_t *player) = 0; + virtual void RenderView(player_t *player, unsigned int nowtime) = 0; // Remap voxel palette virtual void RemapVoxels() {} diff --git a/src/swrenderer/r_swrenderer.cpp b/src/swrenderer/r_swrenderer.cpp index 19bf055a6..ca8d03087 100644 --- a/src/swrenderer/r_swrenderer.cpp +++ b/src/swrenderer/r_swrenderer.cpp @@ -170,7 +170,7 @@ void FSoftwareRenderer::Precache(uint8_t *texhitlist, TMap & } } -void FSoftwareRenderer::RenderView(player_t *player) +void FSoftwareRenderer::RenderView(player_t *player, unsigned int /*nowtime*/) { if (r_polyrenderer) { diff --git a/src/swrenderer/r_swrenderer.h b/src/swrenderer/r_swrenderer.h index 19f75758f..05d00ecec 100644 --- a/src/swrenderer/r_swrenderer.h +++ b/src/swrenderer/r_swrenderer.h @@ -13,7 +13,7 @@ struct FSoftwareRenderer : public FRenderer void Precache(uint8_t *texhitlist, TMap &actorhitlist) override; // render 3D view - void RenderView(player_t *player) override; + void RenderView(player_t *player, unsigned int nowtime) override; // Remap voxel palette void RemapVoxels() override; From f54475b1f1e6e64a9a953c2df67566c17d83f3e6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 12 Nov 2017 23:39:48 +0100 Subject: [PATCH 13/17] - I_FPSTime may not return the time at frame start. This is used for real-time profiling and as such needs to return the current time or most of its uses will break. --- src/gl/utility/gl_clock.cpp | 6 +++--- src/i_time.cpp | 5 +---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/gl/utility/gl_clock.cpp b/src/gl/utility/gl_clock.cpp index 5cd1daa21..a67df0234 100644 --- a/src/gl/utility/gl_clock.cpp +++ b/src/gl/utility/gl_clock.cpp @@ -226,7 +226,7 @@ void CheckBench() { // if we started the FPS counter ourselves or ran from the console // we need to wait for it to stabilize before using it. - if (waitstart > 0 && I_MSTime() < waitstart + 5000) return; + if (waitstart > 0 && I_FPSTime() - waitstart < 5000) return; FString compose; @@ -257,12 +257,12 @@ CCMD(bench) if (vid_fps == 0) { vid_fps = 1; - waitstart = I_MSTime(); + waitstart = I_FPSTime(); switchfps = true; } else { - if (ConsoleState == c_up) waitstart = I_MSTime(); + if (ConsoleState == c_up) waitstart = I_FPSTime(); switchfps = false; } C_HideConsole (); diff --git a/src/i_time.cpp b/src/i_time.cpp index 908dbdd59..6fe65ef3c 100644 --- a/src/i_time.cpp +++ b/src/i_time.cpp @@ -142,10 +142,7 @@ uint64_t I_NSTime() uint64_t I_FPSTimeNS() { - if (FreezeTime == 0) - return CurrentFrameStartTime; - else - return GetClockTimeNS(); + return GetClockTimeNS(); } unsigned int I_MSTime() From e94109f1c35b619e766b7510b5160a3b069f0d58 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 12 Nov 2017 23:53:46 +0100 Subject: [PATCH 14/17] - Inside the renderer, use only the time value being passed to RenderView. The voxel rotation code of the software renderer and R_SetupFrame still called I_FPSTime directly. --- src/gl/scene/gl_scene.cpp | 2 +- src/polyrenderer/poly_renderer.cpp | 2 +- src/r_utility.cpp | 6 +++--- src/r_utility.h | 2 +- src/swrenderer/drawers/r_draw.cpp | 1 + src/swrenderer/drawers/r_draw.h | 1 + src/swrenderer/r_swrenderer.cpp | 3 ++- src/swrenderer/scene/r_scene.cpp | 2 +- src/swrenderer/things/r_voxel.cpp | 2 +- 9 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index c900c21d7..0f80dae66 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -785,7 +785,7 @@ sector_t * GLSceneDrawer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, f GLRenderer->mSceneClearColor[0] = 0.0f; GLRenderer->mSceneClearColor[1] = 0.0f; GLRenderer->mSceneClearColor[2] = 0.0f; - R_SetupFrame (r_viewpoint, r_viewwindow, camera); + R_SetupFrame (r_viewpoint, r_viewwindow, camera, gl_frameMS); SetViewArea(); GLRenderer->mGlobVis = R_GetGlobVis(r_viewwindow, r_visibility); diff --git a/src/polyrenderer/poly_renderer.cpp b/src/polyrenderer/poly_renderer.cpp index c3389bba5..7fe9062b0 100644 --- a/src/polyrenderer/poly_renderer.cpp +++ b/src/polyrenderer/poly_renderer.cpp @@ -115,7 +115,7 @@ void PolyRenderer::RenderActorView(AActor *actor, bool dontmaplines) DontMapLines = dontmaplines; - R_SetupFrame(Viewpoint, Viewwindow, actor); + R_SetupFrame(Viewpoint, Viewwindow, actor, swrenderer::renderTime); P_FindParticleSubsectors(); PO_LinkToSubsectors(); diff --git a/src/r_utility.cpp b/src/r_utility.cpp index 8a18c433d..70619d832 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -751,7 +751,7 @@ static double QuakePower(double factor, double intensity, double offset) // //========================================================================== -void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor *actor) +void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor *actor, unsigned int renderTime) { if (actor == NULL) { @@ -982,7 +982,7 @@ void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor if (hom == 3) { - hom = ((I_FPSTime() / 128) & 1) + 1; + hom = ((renderTime / 128) & 1) + 1; } if (hom == 1) { @@ -994,7 +994,7 @@ void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor } else if (hom == 4) { - color = (I_FPSTime() / 32) & 255; + color = (renderTime / 32) & 255; } else { diff --git a/src/r_utility.h b/src/r_utility.h index eb108e411..0254a114e 100644 --- a/src/r_utility.h +++ b/src/r_utility.h @@ -111,7 +111,7 @@ void R_ClearInterpolationPath(); void R_AddInterpolationPoint(const DVector3a &vec); void R_SetViewSize (int blocks); void R_SetFOV (FRenderViewpoint &viewpoint, DAngle fov); -void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor * camera); +void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor * camera, unsigned int renderTime); void R_SetViewAngle (FRenderViewpoint &viewpoint, const FViewWindow &viewwindow); // Called by startup code. diff --git a/src/swrenderer/drawers/r_draw.cpp b/src/swrenderer/drawers/r_draw.cpp index c894e46ce..e48746211 100644 --- a/src/swrenderer/drawers/r_draw.cpp +++ b/src/swrenderer/drawers/r_draw.cpp @@ -64,6 +64,7 @@ namespace swrenderer int fuzzoffset[FUZZTABLE + 1]; int fuzzpos; int fuzzviewheight; + unsigned int renderTime; int fuzz_random_x_offset[FUZZ_RANDOM_X_SIZE] = { diff --git a/src/swrenderer/drawers/r_draw.h b/src/swrenderer/drawers/r_draw.h index 4672a4fd3..4a31da74b 100644 --- a/src/swrenderer/drawers/r_draw.h +++ b/src/swrenderer/drawers/r_draw.h @@ -35,6 +35,7 @@ namespace swrenderer extern FDynamicColormap ShadeFakeColormap[16]; extern uint8_t identitymap[256]; extern FDynamicColormap identitycolormap; + extern unsigned int renderTime; // Constant arrays used for psprite clipping and initializing clipping. extern short zeroarray[MAXWIDTH]; diff --git a/src/swrenderer/r_swrenderer.cpp b/src/swrenderer/r_swrenderer.cpp index ca8d03087..69f5b2f43 100644 --- a/src/swrenderer/r_swrenderer.cpp +++ b/src/swrenderer/r_swrenderer.cpp @@ -170,8 +170,9 @@ void FSoftwareRenderer::Precache(uint8_t *texhitlist, TMap & } } -void FSoftwareRenderer::RenderView(player_t *player, unsigned int /*nowtime*/) +void FSoftwareRenderer::RenderView(player_t *player, unsigned int nowtime) { + renderTime = nowtime; if (r_polyrenderer) { PolyRenderer::Instance()->Viewpoint = r_viewpoint; diff --git a/src/swrenderer/scene/r_scene.cpp b/src/swrenderer/scene/r_scene.cpp index 4667f25eb..c2c63556e 100644 --- a/src/swrenderer/scene/r_scene.cpp +++ b/src/swrenderer/scene/r_scene.cpp @@ -136,7 +136,7 @@ namespace swrenderer MaskedCycles.Reset(); DrawerWaitCycles.Reset(); - R_SetupFrame(MainThread()->Viewport->viewpoint, MainThread()->Viewport->viewwindow, actor); + R_SetupFrame(MainThread()->Viewport->viewpoint, MainThread()->Viewport->viewwindow, actor, renderTime); if (APART(R_OldBlend)) NormalLight.Maps = realcolormaps.Maps; else NormalLight.Maps = realcolormaps.Maps + NUMCOLORMAPS * 256 * R_OldBlend; diff --git a/src/swrenderer/things/r_voxel.cpp b/src/swrenderer/things/r_voxel.cpp index 8f2b80f0b..beb7a474b 100644 --- a/src/swrenderer/things/r_voxel.cpp +++ b/src/swrenderer/things/r_voxel.cpp @@ -135,7 +135,7 @@ namespace swrenderer int voxelspin = (thing->flags & MF_DROPPED) ? voxel->DroppedSpin : voxel->PlacedSpin; if (voxelspin != 0) { - DAngle ang = double(I_FPSTime()) * voxelspin / 1000; + DAngle ang = double(renderTime) * voxelspin / 1000; vis->Angle -= ang; } From 2c65f0801151f198868ed55d1ca0a4c062cf733f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 13 Nov 2017 00:28:43 +0100 Subject: [PATCH 15/17] - more timer cleanup * store the frame time in the current screen buffer from where all render code can access it. * replace some uses of I_MSTime with I_FPSTime, because they should not use a per-frame timer. The only one left is the wipe code but even this doesn't look like it needs either a per-frame timer or a timer counting from the start of the playsim. --- src/c_bind.cpp | 4 ++-- src/d_main.cpp | 8 ++++---- src/d_net.cpp | 2 +- src/gl/data/gl_data.cpp | 1 - src/gl/data/gl_data.h | 2 -- src/gl/models/gl_models.cpp | 2 +- src/gl/renderer/gl_renderer.h | 2 +- src/gl/renderer/gl_renderstate.cpp | 2 +- src/gl/scene/gl_scene.cpp | 15 +++++++-------- src/gl/scene/gl_scenedrawer.h | 2 +- src/gl/system/gl_framebuffer.h | 1 - src/polyrenderer/poly_renderer.cpp | 2 +- src/posix/cocoa/st_console.mm | 2 +- src/r_renderer.h | 2 +- src/r_utility.cpp | 6 +++--- src/r_utility.h | 2 +- src/swrenderer/drawers/r_draw.cpp | 1 - src/swrenderer/drawers/r_draw.h | 1 - src/swrenderer/r_swrenderer.cpp | 3 +-- src/swrenderer/r_swrenderer.h | 2 +- src/swrenderer/scene/r_scene.cpp | 2 +- src/swrenderer/things/r_voxel.cpp | 2 +- src/v_video.cpp | 2 +- src/v_video.h | 1 + 24 files changed, 31 insertions(+), 38 deletions(-) diff --git a/src/c_bind.cpp b/src/c_bind.cpp index 83e5e1820..cbc65868f 100644 --- a/src/c_bind.cpp +++ b/src/c_bind.cpp @@ -744,8 +744,8 @@ bool C_DoKey (event_t *ev, FKeyBindings *binds, FKeyBindings *doublebinds) dclick = false; // This used level.time which didn't work outside a level. - nowtime = I_MSTime(); - if (doublebinds != NULL && DClickTime[ev->data1] > nowtime && ev->type == EV_KeyDown) + nowtime = I_FPSTime(); + if (doublebinds != NULL && int(DClickTime[ev->data1] - nowtime) > 0 && ev->type == EV_KeyDown) { // Key pressed for a double click binding = doublebinds->GetBinding(ev->data1); diff --git a/src/d_main.cpp b/src/d_main.cpp index 5e0eff1d1..e58c2f686 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -779,9 +779,9 @@ void D_Display () { - unsigned int nowtime = I_FPSTime(); - TexMan.UpdateAnimations(nowtime); - R_UpdateSky(nowtime); + screen->FrameTime = I_FPSTime(); + TexMan.UpdateAnimations(screen->FrameTime); + R_UpdateSky(screen->FrameTime); switch (gamestate) { case GS_FULLCONSOLE: @@ -808,7 +808,7 @@ void D_Display () // [ZZ] execute event hook that we just started the frame //E_RenderFrame(); // - Renderer->RenderView(&players[consoleplayer], nowtime); + Renderer->RenderView(&players[consoleplayer]); if ((hw2d = screen->Begin2D(viewactive))) { diff --git a/src/d_net.cpp b/src/d_net.cpp index 12de17c9e..95765e84c 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -783,7 +783,7 @@ void GetPackets (void) // [RH] Get "ping" times - totally useless, since it's bound to the frequency // packets go out at. lastrecvtime[netconsole] = currrecvtime[netconsole]; - currrecvtime[netconsole] = I_MSTime (); + currrecvtime[netconsole] = I_FPSTime (); // check for exiting the game if (netbuffer[0] & NCMD_EXIT) diff --git a/src/gl/data/gl_data.cpp b/src/gl/data/gl_data.cpp index 9a7c2e037..42fc6e96d 100644 --- a/src/gl/data/gl_data.cpp +++ b/src/gl/data/gl_data.cpp @@ -55,7 +55,6 @@ #include "gl/gl_functions.h" GLRenderSettings glset; -long gl_frameMS; EXTERN_CVAR(Int, gl_lightmode) EXTERN_CVAR(Bool, gl_brightfog) diff --git a/src/gl/data/gl_data.h b/src/gl/data/gl_data.h index a46680ab7..518f330c9 100644 --- a/src/gl/data/gl_data.h +++ b/src/gl/data/gl_data.h @@ -65,6 +65,4 @@ void gl_InitPortals(); void gl_BuildPortalCoverage(FPortalCoverage *coverage, subsector_t *subsector, const DVector2 &displacement); void gl_InitData(); -extern long gl_frameMS; - #endif diff --git a/src/gl/models/gl_models.cpp b/src/gl/models/gl_models.cpp index 6ef0acbfc..541a4c36c 100644 --- a/src/gl/models/gl_models.cpp +++ b/src/gl/models/gl_models.cpp @@ -55,7 +55,7 @@ static inline float GetTimeFloat() { - return (float)gl_frameMS * (float)TICRATE / 1000.0f; + return (float)screen->FrameTime * (float)TICRATE / 1000.0f; } CVAR(Bool, gl_interpolate_model_frames, true, CVAR_ARCHIVE) diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h index f8d710467..e3924ad40 100644 --- a/src/gl/renderer/gl_renderer.h +++ b/src/gl/renderer/gl_renderer.h @@ -171,7 +171,7 @@ public: unsigned char *GetTextureBuffer(FTexture *tex, int &w, int &h); void SetupLevel(); - void RenderView(player_t* player, unsigned int nowtime); + void RenderView(player_t* player); void RenderScreenQuad(); void PostProcessScene(int fixedcm); diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp index 67c9c21fa..1427e2350 100644 --- a/src/gl/renderer/gl_renderstate.cpp +++ b/src/gl/renderer/gl_renderstate.cpp @@ -161,7 +161,7 @@ bool FRenderState::ApplyShader() activeShader->muInterpolationFactor.Set(mInterpolationFactor); activeShader->muClipHeight.Set(mClipHeight); activeShader->muClipHeightDirection.Set(mClipHeightDirection); - activeShader->muTimer.Set(gl_frameMS * mShaderTimer / 1000.f); + activeShader->muTimer.Set(screen->FrameTime * mShaderTimer / 1000.f); activeShader->muAlphaThreshold.Set(mAlphaThreshold); activeShader->muLightIndex.Set(mLightIndex); // will always be -1 for now activeShader->muClipSplit.Set(mClipSplit); diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index 0f80dae66..c1351001d 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -785,7 +785,7 @@ sector_t * GLSceneDrawer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, f GLRenderer->mSceneClearColor[0] = 0.0f; GLRenderer->mSceneClearColor[1] = 0.0f; GLRenderer->mSceneClearColor[2] = 0.0f; - R_SetupFrame (r_viewpoint, r_viewwindow, camera, gl_frameMS); + R_SetupFrame (r_viewpoint, r_viewwindow, camera); SetViewArea(); GLRenderer->mGlobVis = R_GetGlobVis(r_viewwindow, r_visibility); @@ -800,8 +800,8 @@ sector_t * GLSceneDrawer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, f GLRenderer->mAngles.Roll.Degrees = r_viewpoint.Angles.Roll.Degrees; // Scroll the sky - GLRenderer->mSky1Pos = (float)fmod(gl_frameMS * level.skyspeed1, 1024.f) * 90.f/256.f; - GLRenderer->mSky2Pos = (float)fmod(gl_frameMS * level.skyspeed2, 1024.f) * 90.f/256.f; + GLRenderer->mSky1Pos = (float)fmod(screen->FrameTime * level.skyspeed1, 1024.f) * 90.f/256.f; + GLRenderer->mSky2Pos = (float)fmod(screen->FrameTime * level.skyspeed2, 1024.f) * 90.f/256.f; @@ -878,7 +878,7 @@ sector_t * GLSceneDrawer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, f // //----------------------------------------------------------------------------- -void FGLRenderer::RenderView (player_t* player, unsigned int nowtime) +void FGLRenderer::RenderView (player_t* player) { checkBenchActive(); @@ -891,7 +891,6 @@ void FGLRenderer::RenderView (player_t* player, unsigned int nowtime) // Get this before everything else if (cl_capfps || r_NoInterpolate) r_viewpoint.TicFrac = 1.; else r_viewpoint.TicFrac = I_GetTimeFrac (&r_viewpoint.FrameTime); - gl_frameMS = nowtime; P_FindParticleSubsectors (); @@ -984,7 +983,7 @@ void GLSceneDrawer::WriteSavePic (player_t *player, FileWriter *file, int width, struct FGLInterface : public FRenderer { void Precache(uint8_t *texhitlist, TMap &actorhitlist) override; - void RenderView(player_t *player, unsigned int nowtime) override; + void RenderView(player_t *player) override; void WriteSavePic (player_t *player, FileWriter *file, int width, int height) override; void StartSerialize(FSerializer &arc) override; void EndSerialize(FSerializer &arc) override; @@ -1075,9 +1074,9 @@ void FGLInterface::WriteSavePic (player_t *player, FileWriter *file, int width, // //=========================================================================== -void FGLInterface::RenderView(player_t *player, unsigned int nowtime) +void FGLInterface::RenderView(player_t *player) { - GLRenderer->RenderView(player, nowtime); + GLRenderer->RenderView(player); } //=========================================================================== diff --git a/src/gl/scene/gl_scenedrawer.h b/src/gl/scene/gl_scenedrawer.h index 6e4fa143d..9209e6dad 100644 --- a/src/gl/scene/gl_scenedrawer.h +++ b/src/gl/scene/gl_scenedrawer.h @@ -60,7 +60,7 @@ public: void CheckViewArea(vertex_t *v1, vertex_t *v2, sector_t *frontsector, sector_t *backsector); sector_t *RenderViewpoint(AActor * camera, GL_IRECT * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen); - void RenderView(player_t *player, unsigned int nowtime); + void RenderView(player_t *player); void WriteSavePic(player_t *player, FileWriter *file, int width, int height); void DrawPSprite(player_t * player, DPSprite *psp, float sx, float sy, bool hudModelStep, int OverrideShader, bool alphatexture); diff --git a/src/gl/system/gl_framebuffer.h b/src/gl/system/gl_framebuffer.h index 7d11db921..1d85562b3 100644 --- a/src/gl/system/gl_framebuffer.h +++ b/src/gl/system/gl_framebuffer.h @@ -12,7 +12,6 @@ class FHardwareTexture; class FSimpleVertexBuffer; class FGLDebug; -extern long gl_frameMS; #ifdef _WIN32 class OpenGLFrameBuffer : public Win32GLFrameBuffer { diff --git a/src/polyrenderer/poly_renderer.cpp b/src/polyrenderer/poly_renderer.cpp index 7fe9062b0..c3389bba5 100644 --- a/src/polyrenderer/poly_renderer.cpp +++ b/src/polyrenderer/poly_renderer.cpp @@ -115,7 +115,7 @@ void PolyRenderer::RenderActorView(AActor *actor, bool dontmaplines) DontMapLines = dontmaplines; - R_SetupFrame(Viewpoint, Viewwindow, actor, swrenderer::renderTime); + R_SetupFrame(Viewpoint, Viewwindow, actor); P_FindParticleSubsectors(); PO_LinkToSubsectors(); diff --git a/src/posix/cocoa/st_console.mm b/src/posix/cocoa/st_console.mm index 216e795bd..bf08c27eb 100644 --- a/src/posix/cocoa/st_console.mm +++ b/src/posix/cocoa/st_console.mm @@ -200,7 +200,7 @@ struct TimedUpdater { explicit TimedUpdater(const Function& function) { - const unsigned int currentTime = I_MSTime(); + const unsigned int currentTime = I_FPSTime(); if (currentTime - m_previousTime > interval) { diff --git a/src/r_renderer.h b/src/r_renderer.h index 0165c33b8..54952bc29 100644 --- a/src/r_renderer.h +++ b/src/r_renderer.h @@ -29,7 +29,7 @@ struct FRenderer virtual void Precache(uint8_t *texhitlist, TMap &actorhitlist) = 0; // render 3D view - virtual void RenderView(player_t *player, unsigned int nowtime) = 0; + virtual void RenderView(player_t *player) = 0; // Remap voxel palette virtual void RemapVoxels() {} diff --git a/src/r_utility.cpp b/src/r_utility.cpp index 70619d832..77e747007 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -751,7 +751,7 @@ static double QuakePower(double factor, double intensity, double offset) // //========================================================================== -void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor *actor, unsigned int renderTime) +void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor *actor) { if (actor == NULL) { @@ -982,7 +982,7 @@ void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor if (hom == 3) { - hom = ((renderTime / 128) & 1) + 1; + hom = ((screen->FrameTime / 128) & 1) + 1; } if (hom == 1) { @@ -994,7 +994,7 @@ void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor } else if (hom == 4) { - color = (renderTime / 32) & 255; + color = (screen->FrameTime / 32) & 255; } else { diff --git a/src/r_utility.h b/src/r_utility.h index 0254a114e..eb108e411 100644 --- a/src/r_utility.h +++ b/src/r_utility.h @@ -111,7 +111,7 @@ void R_ClearInterpolationPath(); void R_AddInterpolationPoint(const DVector3a &vec); void R_SetViewSize (int blocks); void R_SetFOV (FRenderViewpoint &viewpoint, DAngle fov); -void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor * camera, unsigned int renderTime); +void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor * camera); void R_SetViewAngle (FRenderViewpoint &viewpoint, const FViewWindow &viewwindow); // Called by startup code. diff --git a/src/swrenderer/drawers/r_draw.cpp b/src/swrenderer/drawers/r_draw.cpp index e48746211..c894e46ce 100644 --- a/src/swrenderer/drawers/r_draw.cpp +++ b/src/swrenderer/drawers/r_draw.cpp @@ -64,7 +64,6 @@ namespace swrenderer int fuzzoffset[FUZZTABLE + 1]; int fuzzpos; int fuzzviewheight; - unsigned int renderTime; int fuzz_random_x_offset[FUZZ_RANDOM_X_SIZE] = { diff --git a/src/swrenderer/drawers/r_draw.h b/src/swrenderer/drawers/r_draw.h index 4a31da74b..4672a4fd3 100644 --- a/src/swrenderer/drawers/r_draw.h +++ b/src/swrenderer/drawers/r_draw.h @@ -35,7 +35,6 @@ namespace swrenderer extern FDynamicColormap ShadeFakeColormap[16]; extern uint8_t identitymap[256]; extern FDynamicColormap identitycolormap; - extern unsigned int renderTime; // Constant arrays used for psprite clipping and initializing clipping. extern short zeroarray[MAXWIDTH]; diff --git a/src/swrenderer/r_swrenderer.cpp b/src/swrenderer/r_swrenderer.cpp index 69f5b2f43..19bf055a6 100644 --- a/src/swrenderer/r_swrenderer.cpp +++ b/src/swrenderer/r_swrenderer.cpp @@ -170,9 +170,8 @@ void FSoftwareRenderer::Precache(uint8_t *texhitlist, TMap & } } -void FSoftwareRenderer::RenderView(player_t *player, unsigned int nowtime) +void FSoftwareRenderer::RenderView(player_t *player) { - renderTime = nowtime; if (r_polyrenderer) { PolyRenderer::Instance()->Viewpoint = r_viewpoint; diff --git a/src/swrenderer/r_swrenderer.h b/src/swrenderer/r_swrenderer.h index 05d00ecec..19f75758f 100644 --- a/src/swrenderer/r_swrenderer.h +++ b/src/swrenderer/r_swrenderer.h @@ -13,7 +13,7 @@ struct FSoftwareRenderer : public FRenderer void Precache(uint8_t *texhitlist, TMap &actorhitlist) override; // render 3D view - void RenderView(player_t *player, unsigned int nowtime) override; + void RenderView(player_t *player) override; // Remap voxel palette void RemapVoxels() override; diff --git a/src/swrenderer/scene/r_scene.cpp b/src/swrenderer/scene/r_scene.cpp index c2c63556e..4667f25eb 100644 --- a/src/swrenderer/scene/r_scene.cpp +++ b/src/swrenderer/scene/r_scene.cpp @@ -136,7 +136,7 @@ namespace swrenderer MaskedCycles.Reset(); DrawerWaitCycles.Reset(); - R_SetupFrame(MainThread()->Viewport->viewpoint, MainThread()->Viewport->viewwindow, actor, renderTime); + R_SetupFrame(MainThread()->Viewport->viewpoint, MainThread()->Viewport->viewwindow, actor); if (APART(R_OldBlend)) NormalLight.Maps = realcolormaps.Maps; else NormalLight.Maps = realcolormaps.Maps + NUMCOLORMAPS * 256 * R_OldBlend; diff --git a/src/swrenderer/things/r_voxel.cpp b/src/swrenderer/things/r_voxel.cpp index beb7a474b..75b0a2c07 100644 --- a/src/swrenderer/things/r_voxel.cpp +++ b/src/swrenderer/things/r_voxel.cpp @@ -135,7 +135,7 @@ namespace swrenderer int voxelspin = (thing->flags & MF_DROPPED) ? voxel->DroppedSpin : voxel->PlacedSpin; if (voxelspin != 0) { - DAngle ang = double(renderTime) * voxelspin / 1000; + DAngle ang = double(screen->FrameTime) * voxelspin / 1000; vis->Angle -= ang; } diff --git a/src/v_video.cpp b/src/v_video.cpp index d47ece201..5f774a648 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -870,7 +870,7 @@ void DFrameBuffer::DrawRateStuff () // Draws frame time and cumulative fps if (vid_fps) { - uint32_t ms = I_FPSTime(); + uint32_t ms = screen->FrameTime; uint32_t howlong = ms - LastMS; if ((signed)howlong >= 0) { diff --git a/src/v_video.h b/src/v_video.h index fc4d3924d..5934a3706 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -453,6 +453,7 @@ public: // The original size of the framebuffer as selected in the video menu. int VideoWidth = 0; int VideoHeight = 0; + uint32_t FrameTime = 0; protected: void DrawRateStuff (); From 96e9eadd97d9d5d4098154f0b63ebc7e497932d2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 13 Nov 2017 00:38:04 +0100 Subject: [PATCH 16/17] - removed I_MSTime entirely after checking how the wipe code actually works. Since this calls I_WaitVBL, which resets the frame time, it was essentially just like calling a real-time timer anyway and nothing in it required a specific 0-timepoint. The same applies to the ZScript interface. All it needs is a millisecond-precise timer with no semantics attached. --- src/d_main.cpp | 4 ++-- src/dobject.cpp | 2 +- src/i_time.cpp | 27 +-------------------------- src/i_time.h | 4 +--- 4 files changed, 5 insertions(+), 32 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index e58c2f686..6afa74c33 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -945,7 +945,7 @@ void D_Display () I_FreezeTime(true); screen->WipeEndScreen (); - wipestart = I_MSTime(); + wipestart = I_FPSTime(); NetUpdate(); // send out any new accumulation do @@ -953,7 +953,7 @@ void D_Display () do { I_WaitVBL(2); - nowtime = I_MSTime(); + nowtime = I_FPSTime(); diff = (nowtime - wipestart) * 40 / 1000; // Using 35 here feels too slow. } while (diff < 1); wipestart = nowtime; diff --git a/src/dobject.cpp b/src/dobject.cpp index 17b9743f3..299486de9 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -615,7 +615,7 @@ void DObject::CheckIfSerialized () const DEFINE_ACTION_FUNCTION(DObject, MSTime) { - ACTION_RETURN_INT(I_MSTime()); + ACTION_RETURN_INT(I_FPSTime()); } void *DObject::ScriptVar(FName field, PType *type) diff --git a/src/i_time.cpp b/src/i_time.cpp index 6fe65ef3c..a8e30747a 100644 --- a/src/i_time.cpp +++ b/src/i_time.cpp @@ -80,7 +80,7 @@ void I_SetFrameTime() // Must only be called once per frame/swapbuffers. // // Caches all timing information for the current rendered frame so that any - // calls to I_FPSTime, I_MSTime, I_GetTime or I_GetTimeFrac will return + // calls to I_GetTime or I_GetTimeFrac will return // the same time. if (FreezeTime == 0) @@ -120,36 +120,11 @@ int I_WaitForTic(int prevtic) return time; } -uint64_t I_NSTime() -{ - if (FreezeTime == 0) - { - return CurrentFrameStartTime - FirstFrameStartTime; - } - else - { - if (FirstFrameStartTime == 0) - { - FirstFrameStartTime = GetClockTimeNS(); - return 0; - } - else - { - return GetClockTimeNS() - FirstFrameStartTime; - } - } -} - uint64_t I_FPSTimeNS() { return GetClockTimeNS(); } -unsigned int I_MSTime() -{ - return NSToMS(I_NSTime()); -} - unsigned int I_FPSTime() { return NSToMS(I_FPSTimeNS()); diff --git a/src/i_time.h b/src/i_time.h index 5d1514924..95f07a490 100644 --- a/src/i_time.h +++ b/src/i_time.h @@ -14,15 +14,13 @@ double I_GetTimeFrac(uint32_t *ms); int I_WaitForTic(int); // Freezes tic counting temporarily. While frozen, calls to I_GetTime() -// will always return the same value. This does not affect I_MSTime(). +// will always return the same value. // You must also not call I_WaitForTic() while freezing time, since the // tic will never arrive (unless it's the current one). void I_FreezeTime(bool frozen); // [RH] Returns millisecond-accurate time -unsigned int I_MSTime(); unsigned int I_FPSTime(); // Nanosecond-accurate time -uint64_t I_NSTime(); uint64_t I_FPSTimeNS(); From 0323f543842a17aed893c4cfc9ffd189ec353bfb Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 13 Nov 2017 00:54:32 +0100 Subject: [PATCH 17/17] - rename I_FPSTime function. - now that the frame buffer stores its render time, the 'ms' return from I_GetTimeFrac is not needed anymore, we may just as well use the globally stored value instead. The only feature this value was ever used for was texture warping. --- src/c_bind.cpp | 2 +- src/d_main.cpp | 6 +++--- src/d_net.cpp | 2 +- src/dobject.cpp | 2 +- src/gl/scene/gl_scene.cpp | 2 +- src/gl/textures/gl_material.cpp | 4 ++-- src/gl/utility/gl_clock.cpp | 8 ++++---- src/i_time.cpp | 11 ++++------- src/i_time.h | 6 +++--- src/p_glnodes.cpp | 4 ++-- src/p_setup.cpp | 4 ++-- src/posix/cocoa/st_console.mm | 2 +- src/r_utility.cpp | 2 +- src/textures/warptexture.cpp | 9 +++++---- 14 files changed, 31 insertions(+), 33 deletions(-) diff --git a/src/c_bind.cpp b/src/c_bind.cpp index cbc65868f..b1a557514 100644 --- a/src/c_bind.cpp +++ b/src/c_bind.cpp @@ -744,7 +744,7 @@ bool C_DoKey (event_t *ev, FKeyBindings *binds, FKeyBindings *doublebinds) dclick = false; // This used level.time which didn't work outside a level. - nowtime = I_FPSTime(); + nowtime = I_msTime(); if (doublebinds != NULL && int(DClickTime[ev->data1] - nowtime) > 0 && ev->type == EV_KeyDown) { // Key pressed for a double click diff --git a/src/d_main.cpp b/src/d_main.cpp index 6afa74c33..540b002b3 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -779,7 +779,7 @@ void D_Display () { - screen->FrameTime = I_FPSTime(); + screen->FrameTime = I_msTime(); TexMan.UpdateAnimations(screen->FrameTime); R_UpdateSky(screen->FrameTime); switch (gamestate) @@ -945,7 +945,7 @@ void D_Display () I_FreezeTime(true); screen->WipeEndScreen (); - wipestart = I_FPSTime(); + wipestart = I_msTime(); NetUpdate(); // send out any new accumulation do @@ -953,7 +953,7 @@ void D_Display () do { I_WaitVBL(2); - nowtime = I_FPSTime(); + nowtime = I_msTime(); diff = (nowtime - wipestart) * 40 / 1000; // Using 35 here feels too slow. } while (diff < 1); wipestart = nowtime; diff --git a/src/d_net.cpp b/src/d_net.cpp index 95765e84c..ba1262025 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -783,7 +783,7 @@ void GetPackets (void) // [RH] Get "ping" times - totally useless, since it's bound to the frequency // packets go out at. lastrecvtime[netconsole] = currrecvtime[netconsole]; - currrecvtime[netconsole] = I_FPSTime (); + currrecvtime[netconsole] = I_msTime (); // check for exiting the game if (netbuffer[0] & NCMD_EXIT) diff --git a/src/dobject.cpp b/src/dobject.cpp index 299486de9..9046d7337 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -615,7 +615,7 @@ void DObject::CheckIfSerialized () const DEFINE_ACTION_FUNCTION(DObject, MSTime) { - ACTION_RETURN_INT(I_FPSTime()); + ACTION_RETURN_INT(I_msTime()); } void *DObject::ScriptVar(FName field, PType *type) diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index c1351001d..92d378521 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -890,7 +890,7 @@ void FGLRenderer::RenderView (player_t* player) // Get this before everything else if (cl_capfps || r_NoInterpolate) r_viewpoint.TicFrac = 1.; - else r_viewpoint.TicFrac = I_GetTimeFrac (&r_viewpoint.FrameTime); + else r_viewpoint.TicFrac = I_GetTimeFrac (); P_FindParticleSubsectors (); diff --git a/src/gl/textures/gl_material.cpp b/src/gl/textures/gl_material.cpp index f45a702b9..53d22f857 100644 --- a/src/gl/textures/gl_material.cpp +++ b/src/gl/textures/gl_material.cpp @@ -320,10 +320,10 @@ const FHardwareTexture *FGLTexture::Bind(int texunit, int clampmode, int transla // need to do software warping FWarpTexture *wt = static_cast(tex); unsigned char *warpbuffer = new unsigned char[w*h*4]; - WarpBuffer((uint32_t*)warpbuffer, (const uint32_t*)buffer, w, h, wt->WidthOffsetMultiplier, wt->HeightOffsetMultiplier, r_viewpoint.FrameTime, wt->Speed, tex->bWarped); + WarpBuffer((uint32_t*)warpbuffer, (const uint32_t*)buffer, w, h, wt->WidthOffsetMultiplier, wt->HeightOffsetMultiplier, screen->FrameTime, wt->Speed, tex->bWarped); delete[] buffer; buffer = warpbuffer; - wt->GenTime = r_viewpoint.FrameTime; + wt->GenTime = screen->FrameTime; } tex->ProcessData(buffer, w, h, false); } diff --git a/src/gl/utility/gl_clock.cpp b/src/gl/utility/gl_clock.cpp index a67df0234..8ad3b1cc8 100644 --- a/src/gl/utility/gl_clock.cpp +++ b/src/gl/utility/gl_clock.cpp @@ -188,7 +188,7 @@ ADD_STAT(rendertimes) { static FString buff; static int lasttime=0; - int t=I_FPSTime(); + int t=I_msTime(); if (t-lasttime>1000) { buff.Truncate(0); @@ -226,7 +226,7 @@ void CheckBench() { // if we started the FPS counter ourselves or ran from the console // we need to wait for it to stabilize before using it. - if (waitstart > 0 && I_FPSTime() - waitstart < 5000) return; + if (waitstart > 0 && I_msTime() - waitstart < 5000) return; FString compose; @@ -257,12 +257,12 @@ CCMD(bench) if (vid_fps == 0) { vid_fps = 1; - waitstart = I_FPSTime(); + waitstart = I_msTime(); switchfps = true; } else { - if (ConsoleState == c_up) waitstart = I_FPSTime(); + if (ConsoleState == c_up) waitstart = I_msTime(); switchfps = false; } C_HideConsole (); diff --git a/src/i_time.cpp b/src/i_time.cpp index a8e30747a..050bb1ebc 100644 --- a/src/i_time.cpp +++ b/src/i_time.cpp @@ -120,14 +120,14 @@ int I_WaitForTic(int prevtic) return time; } -uint64_t I_FPSTimeNS() +uint64_t I_nsTime() { return GetClockTimeNS(); } -unsigned int I_FPSTime() +unsigned int I_msTime() { - return NSToMS(I_FPSTimeNS()); + return NSToMS(I_nsTime()); } int I_GetTime() @@ -135,15 +135,12 @@ int I_GetTime() return NSToTic(CurrentFrameStartTime - FirstFrameStartTime) + 1; } -double I_GetTimeFrac(uint32_t *ms) +double I_GetTimeFrac() { int currentTic = NSToTic(CurrentFrameStartTime - FirstFrameStartTime); uint64_t ticStartTime = FirstFrameStartTime + TicToNS(currentTic); uint64_t ticNextTime = FirstFrameStartTime + TicToNS(currentTic + 1); - if (ms) - *ms = currentTic + 1; - return (CurrentFrameStartTime - ticStartTime) / (double)(ticNextTime - ticStartTime); } diff --git a/src/i_time.h b/src/i_time.h index 95f07a490..160596969 100644 --- a/src/i_time.h +++ b/src/i_time.h @@ -8,7 +8,7 @@ void I_SetFrameTime(); // Called by D_DoomLoop, returns current time in tics. int I_GetTime(); -double I_GetTimeFrac(uint32_t *ms); +double I_GetTimeFrac(); // like I_GetTime, except it waits for a new tic before returning int I_WaitForTic(int); @@ -20,7 +20,7 @@ int I_WaitForTic(int); void I_FreezeTime(bool frozen); // [RH] Returns millisecond-accurate time -unsigned int I_FPSTime(); +unsigned int I_msTime(); // Nanosecond-accurate time -uint64_t I_FPSTimeNS(); +uint64_t I_nsTime(); diff --git a/src/p_glnodes.cpp b/src/p_glnodes.cpp index 3559887fa..bac573565 100644 --- a/src/p_glnodes.cpp +++ b/src/p_glnodes.cpp @@ -957,7 +957,7 @@ bool P_CheckNodes(MapData * map, bool rebuilt, int buildtime) // none found - we have to build new ones! unsigned int startTime, endTime; - startTime = I_FPSTime (); + startTime = I_msTime (); TArray polyspots, anchors; P_GetPolySpots (map, polyspots, anchors); FNodeBuilder::FLevel leveldata = @@ -971,7 +971,7 @@ bool P_CheckNodes(MapData * map, bool rebuilt, int buildtime) FNodeBuilder builder (leveldata, polyspots, anchors, true); builder.Extract (level); - endTime = I_FPSTime (); + endTime = I_msTime (); DPrintf (DMSG_NOTIFY, "BSP generation took %.3f sec (%u segs)\n", (endTime - startTime) * 0.001, level.segs.Size()); buildtime = endTime - startTime; } diff --git a/src/p_setup.cpp b/src/p_setup.cpp index fb2f1cdb7..02522d3df 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -3938,7 +3938,7 @@ void P_SetupLevel (const char *lumpname, int position) { BuildGLNodes = RequireGLNodes || multiplayer || demoplayback || demorecording || genglnodes; - startTime = I_FPSTime (); + startTime = I_msTime (); TArray polyspots, anchors; P_GetPolySpots (map, polyspots, anchors); FNodeBuilder::FLevel leveldata = @@ -3954,7 +3954,7 @@ void P_SetupLevel (const char *lumpname, int position) // if the different machines' am_textured setting differs. FNodeBuilder builder (leveldata, polyspots, anchors, BuildGLNodes); builder.Extract (level); - endTime = I_FPSTime (); + endTime = I_msTime (); DPrintf (DMSG_NOTIFY, "BSP generation took %.3f sec (%d segs)\n", (endTime - startTime) * 0.001, level.segs.Size()); oldvertextable = builder.GetOldVertexTable(); reloop = true; diff --git a/src/posix/cocoa/st_console.mm b/src/posix/cocoa/st_console.mm index bf08c27eb..dd876c378 100644 --- a/src/posix/cocoa/st_console.mm +++ b/src/posix/cocoa/st_console.mm @@ -200,7 +200,7 @@ struct TimedUpdater { explicit TimedUpdater(const Function& function) { - const unsigned int currentTime = I_FPSTime(); + const unsigned int currentTime = I_msTime(); if (currentTime - m_previousTime > interval) { diff --git a/src/r_utility.cpp b/src/r_utility.cpp index 77e747007..fc3e963c7 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -831,7 +831,7 @@ void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor iview->otic = nowtic; } - viewpoint.TicFrac = I_GetTimeFrac (&viewpoint.FrameTime); + viewpoint.TicFrac = I_GetTimeFrac (); if (cl_capfps || r_NoInterpolate) { viewpoint.TicFrac = 1.; diff --git a/src/textures/warptexture.cpp b/src/textures/warptexture.cpp index 1de8624fe..43a215a2b 100644 --- a/src/textures/warptexture.cpp +++ b/src/textures/warptexture.cpp @@ -40,6 +40,7 @@ #include "textures/textures.h" #include "warpbuffer.h" #include "v_palette.h" +#include "v_video.h" FWarpTexture::FWarpTexture (FTexture *source, int warptype) @@ -80,12 +81,12 @@ void FWarpTexture::Unload () bool FWarpTexture::CheckModified () { - return r_viewpoint.FrameTime != GenTime; + return screen->FrameTime != GenTime; } const uint8_t *FWarpTexture::GetPixels () { - uint32_t time = r_viewpoint.FrameTime; + uint32_t time = screen->FrameTime; if (Pixels == NULL || time != GenTime) { @@ -96,7 +97,7 @@ const uint8_t *FWarpTexture::GetPixels () const uint32_t *FWarpTexture::GetPixelsBgra() { - uint32_t time = r_viewpoint.FrameTime; + uint32_t time = screen->FrameTime; if (Pixels == NULL || time != GenTime) MakeTexture(time); @@ -118,7 +119,7 @@ const uint32_t *FWarpTexture::GetPixelsBgra() const uint8_t *FWarpTexture::GetColumn (unsigned int column, const Span **spans_out) { - uint32_t time = r_viewpoint.FrameTime; + uint32_t time =screen->FrameTime; if (Pixels == NULL || time != GenTime) {