From 28401cd674eaaf04ed5a642587af93f45bd48da0 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 10 Nov 2017 22:26:59 +0100 Subject: [PATCH 01/29] - 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/29] - 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/29] - 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/29] - 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/29] - 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/29] - 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/29] - 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/29] - 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/29] - 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/29] - 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/29] - 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/29] - 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/29] - 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/29] - 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/29] - 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/29] - 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/29] - 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) { From 763222b571de1d48ebae50d96ff57d14e954e984 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Tue, 14 Nov 2017 15:52:54 -0500 Subject: [PATCH 18/29] - fixed: high uptime was causing overloads in uint32_t and float structures (float losing loss of precision) - this caused any computer online for more than a few days to experience jankiness with internal animations such as rotations and shader timers. Unfortunately, this sounds the death knell for 32-bit platforms, since uint64_t is now required in time-critical structures, which will hurt performance tremendeously, but 64-bit systems will be unaffected. --- src/gl/models/gl_models.cpp | 10 +++++----- src/gl/renderer/gl_renderstate.cpp | 6 +++++- src/gl/scene/gl_scene.cpp | 4 ++-- src/i_time.cpp | 6 +++--- src/i_time.h | 2 +- src/v_video.h | 2 +- 6 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/gl/models/gl_models.cpp b/src/gl/models/gl_models.cpp index 541a4c36c..963518a99 100644 --- a/src/gl/models/gl_models.cpp +++ b/src/gl/models/gl_models.cpp @@ -53,9 +53,9 @@ #include "gl/renderer/gl_renderstate.h" #include "gl/shaders/gl_shader.h" -static inline float GetTimeFloat() +static inline double GetTimeFloat() { - return (float)screen->FrameTime * (float)TICRATE / 1000.0f; + return (double)screen->FrameTime * (double)TICRATE / 1000.; } CVAR(Bool, gl_interpolate_model_frames, true, CVAR_ARCHIVE) @@ -890,7 +890,7 @@ void gl_RenderFrameModels( const FSpriteModelFrame *smf, // [BB] In case the tic counter is frozen we have to leave ticFraction at zero. if ( ConsoleState == c_up && menuactive != MENU_On && !(level.flags2 & LEVEL2_FROZEN) ) { - float time = GetTimeFloat(); + double time = GetTimeFloat(); ticFraction = (time - static_cast(time)); } inter = static_cast(curState->Tics - curTics - ticFraction)/static_cast(curState->Tics); @@ -999,8 +999,8 @@ void gl_RenderModel(GLSprite * spr) if( smf->flags & MDL_ROTATING ) { - const float time = smf->rotationSpeed*GetTimeFloat()/200.f; - rotateOffset = float((time - xs_FloorToInt(time)) *360.f ); + const double time = smf->rotationSpeed*GetTimeFloat()/200.; + rotateOffset = double((time - xs_FloorToInt(time)) *360. ); } // Added MDL_USEACTORPITCH and MDL_USEACTORROLL flags processing. diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp index 1427e2350..5385e4ae3 100644 --- a/src/gl/renderer/gl_renderstate.cpp +++ b/src/gl/renderer/gl_renderstate.cpp @@ -118,6 +118,10 @@ void FRenderState::Reset() bool FRenderState::ApplyShader() { + static int firstFrame = 0; + if (firstFrame == 0) + firstFrame = screen->FrameTime; + static const float nulvec[] = { 0.f, 0.f, 0.f, 0.f }; if (mSpecialEffect > EFF_NONE) { @@ -161,7 +165,7 @@ bool FRenderState::ApplyShader() activeShader->muInterpolationFactor.Set(mInterpolationFactor); activeShader->muClipHeight.Set(mClipHeight); activeShader->muClipHeightDirection.Set(mClipHeightDirection); - activeShader->muTimer.Set(screen->FrameTime * mShaderTimer / 1000.f); + activeShader->muTimer.Set((double)(screen->FrameTime - firstFrame) * 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 92d378521..329ac6484 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -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(screen->FrameTime * level.skyspeed1, 1024.f) * 90.f/256.f; - GLRenderer->mSky2Pos = (float)fmod(screen->FrameTime * level.skyspeed2, 1024.f) * 90.f/256.f; + GLRenderer->mSky1Pos = (double)fmod(screen->FrameTime * level.skyspeed1, 1024.f) * 90./256.; + GLRenderer->mSky2Pos = (double)fmod(screen->FrameTime * level.skyspeed2, 1024.f) * 90./256.; diff --git a/src/i_time.cpp b/src/i_time.cpp index 050bb1ebc..4be0a8b82 100644 --- a/src/i_time.cpp +++ b/src/i_time.cpp @@ -60,9 +60,9 @@ static uint64_t MSToNS(unsigned int ms) return static_cast(ms) * 1'000'000; } -static uint32_t NSToMS(uint64_t ns) +static uint64_t NSToMS(uint64_t ns) { - return static_cast(ns / 1'000'000); + return static_cast(ns / 1'000'000); } static int NSToTic(uint64_t ns) @@ -125,7 +125,7 @@ uint64_t I_nsTime() return GetClockTimeNS(); } -unsigned int I_msTime() +uint64_t I_msTime() { return NSToMS(I_nsTime()); } diff --git a/src/i_time.h b/src/i_time.h index 160596969..33907ded2 100644 --- a/src/i_time.h +++ b/src/i_time.h @@ -20,7 +20,7 @@ int I_WaitForTic(int); void I_FreezeTime(bool frozen); // [RH] Returns millisecond-accurate time -unsigned int I_msTime(); +uint64_t I_msTime(); // Nanosecond-accurate time uint64_t I_nsTime(); diff --git a/src/v_video.h b/src/v_video.h index 5934a3706..4fae94198 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -453,7 +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; + uint64_t FrameTime = 0; protected: void DrawRateStuff (); From d2bc24737b49f01a668dbaea79c88ee7cc8c495a Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Tue, 14 Nov 2017 22:46:28 -0500 Subject: [PATCH 19/29] - put in timer resets for the shader system, so that they can continue being passed as floats --- src/gl/renderer/gl_renderstate.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp index 5385e4ae3..609e80005 100644 --- a/src/gl/renderer/gl_renderstate.cpp +++ b/src/gl/renderer/gl_renderstate.cpp @@ -118,8 +118,10 @@ void FRenderState::Reset() bool FRenderState::ApplyShader() { - static int firstFrame = 0; - if (firstFrame == 0) + static uint64_t firstFrame = 0; + // if firstFrame is not yet initialized, initialize it to current time + // if we're going to overflow a float (after ~4.6 hours, or 24 bits), re-init to regain precision + if ((firstFrame == 0) || (screen->FrameTime - firstFrame >= 1<<24)) firstFrame = screen->FrameTime; static const float nulvec[] = { 0.f, 0.f, 0.f, 0.f }; From ab32cb4c885605354c111ee573c4165945111cfd Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Wed, 15 Nov 2017 11:06:21 -0500 Subject: [PATCH 20/29] - track level start time for the shader system, reset the shaders. --- src/g_level.h | 2 +- src/g_levellocals.h | 2 ++ src/gl/renderer/gl_renderstate.cpp | 3 ++- src/p_setup.cpp | 2 ++ 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/g_level.h b/src/g_level.h index 2df5af946..e7305e9da 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -362,7 +362,7 @@ struct level_info_t int outsidefogdensity; int skyfog; float pixelstretch; - + // Redirection: If any player is carrying the specified item, then // you go to the RedirectMap instead of this one. FName RedirectType; diff --git a/src/g_levellocals.h b/src/g_levellocals.h index b7f4f9aa3..505d797b6 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -67,6 +67,8 @@ struct FLevelLocals FString F1Pic; EMapType maptype; + uint64_t ShaderStartTime = 0; // tell the shader system when we started the level (forces a timer restart) + TArray vertexes; TArray sectors; TArray linebuffer; // contains the line lists for the sectors. diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp index 609e80005..fe4af882f 100644 --- a/src/gl/renderer/gl_renderstate.cpp +++ b/src/gl/renderer/gl_renderstate.cpp @@ -37,6 +37,7 @@ #include "gl/renderer/gl_colormap.h" #include "gl/dynlights//gl_lightbuffer.h" #include "gl/renderer/gl_renderbuffers.h" +#include "g_levellocals.h" void gl_SetTextureMode(int type); @@ -121,7 +122,7 @@ bool FRenderState::ApplyShader() static uint64_t firstFrame = 0; // if firstFrame is not yet initialized, initialize it to current time // if we're going to overflow a float (after ~4.6 hours, or 24 bits), re-init to regain precision - if ((firstFrame == 0) || (screen->FrameTime - firstFrame >= 1<<24)) + if ((firstFrame == 0) || (screen->FrameTime - firstFrame >= 1<<24) || level.ShaderStartTime > firstFrame) firstFrame = screen->FrameTime; static const float nulvec[] = { 0.f, 0.f, 0.f, 0.f }; diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 02522d3df..336d4452e 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -3627,6 +3627,8 @@ void P_SetupLevel (const char *lumpname, int position) bool buildmap; const int *oldvertextable = NULL; + level.ShaderStartTime = I_msTime(); // indicate to the shader system that the level just started + // This is motivated as follows: bool RequireGLNodes = Renderer->RequireGLNodes() || am_textured; From 16fa0cba214b3b12faad22a055be4b00506fbb5f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 15 Nov 2017 18:02:41 +0100 Subject: [PATCH 21/29] - fixed comparison. The timer reset must also occur when the values are equal, meaning they got set during the same millisecond. --- src/gl/renderer/gl_renderstate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp index fe4af882f..c37ccbb99 100644 --- a/src/gl/renderer/gl_renderstate.cpp +++ b/src/gl/renderer/gl_renderstate.cpp @@ -122,7 +122,7 @@ bool FRenderState::ApplyShader() static uint64_t firstFrame = 0; // if firstFrame is not yet initialized, initialize it to current time // if we're going to overflow a float (after ~4.6 hours, or 24 bits), re-init to regain precision - if ((firstFrame == 0) || (screen->FrameTime - firstFrame >= 1<<24) || level.ShaderStartTime > firstFrame) + if ((firstFrame == 0) || (screen->FrameTime - firstFrame >= 1<<24) || level.ShaderStartTime >= firstFrame) firstFrame = screen->FrameTime; static const float nulvec[] = { 0.f, 0.f, 0.f, 0.f }; From 909daadd75c186a67158b420ac54d63e8c0ea58d Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Wed, 15 Nov 2017 20:33:08 -0500 Subject: [PATCH 22/29] - update more millisecond-storing data structures to u/int64_t to fix possible rollover bugs --- src/d_main.cpp | 4 ++-- src/d_net.cpp | 6 +++--- src/dobject.cpp | 2 +- src/gl/utility/gl_clock.cpp | 6 +++--- src/p_glnodes.cpp | 4 ++-- src/p_setup.cpp | 4 ++-- src/r_sky.cpp | 2 +- src/r_sky.h | 2 +- src/textures/animations.cpp | 4 ++-- src/textures/textures.h | 12 ++++++------ src/textures/warpbuffer.h | 2 +- src/textures/warptexture.cpp | 8 ++++---- src/v_video.cpp | 11 ++++++----- src/v_video.h | 4 ++-- 14 files changed, 36 insertions(+), 35 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 540b002b3..4e1655747 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -938,7 +938,7 @@ void D_Display () else { // wipe update - unsigned int wipestart, nowtime, diff; + uint64_t wipestart, nowtime, diff; bool done; GSnd->SetSfxPaused(true, 1); @@ -1053,10 +1053,10 @@ void D_DoomLoop () } else { + I_StartTic (); TryRunTics (); // will run at least one tic } // Update display, next frame, with current state. - I_StartTic (); D_Display (); if (wantToRestart) { diff --git a/src/d_net.cpp b/src/d_net.cpp index ba1262025..e8711bda5 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -113,9 +113,9 @@ bool remoteresend[MAXNETNODES]; // set when local needs tics int resendto[MAXNETNODES]; // set when remote needs tics int resendcount[MAXNETNODES]; -unsigned int lastrecvtime[MAXPLAYERS]; // [RH] Used for pings -unsigned int currrecvtime[MAXPLAYERS]; -unsigned int lastglobalrecvtime; // Identify the last time a packet was received. +uint64_t lastrecvtime[MAXPLAYERS]; // [RH] Used for pings +uint64_t currrecvtime[MAXPLAYERS]; +uint64_t lastglobalrecvtime; // Identify the last time a packet was received. bool hadlate; int netdelay[MAXNETNODES][BACKUPTICS]; // Used for storing network delay times. int lastaverage; diff --git a/src/dobject.cpp b/src/dobject.cpp index 9046d7337..df8bb1acb 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((uint32_t)I_msTime()); } void *DObject::ScriptVar(FName field, PType *type) diff --git a/src/gl/utility/gl_clock.cpp b/src/gl/utility/gl_clock.cpp index 8ad3b1cc8..df96fb6b8 100644 --- a/src/gl/utility/gl_clock.cpp +++ b/src/gl/utility/gl_clock.cpp @@ -187,8 +187,8 @@ static void AppendLightStats(FString &out) ADD_STAT(rendertimes) { static FString buff; - static int lasttime=0; - int t=I_msTime(); + static int64_t lasttime=0; + int64_t t=I_msTime(); if (t-lasttime>1000) { buff.Truncate(0); @@ -217,7 +217,7 @@ void AppendMissingTextureStats(FString &out); static int printstats; static bool switchfps; -static unsigned int waitstart; +static uint64_t waitstart; EXTERN_CVAR(Bool, vid_fps) void CheckBench() diff --git a/src/p_glnodes.cpp b/src/p_glnodes.cpp index bac573565..e1510145e 100644 --- a/src/p_glnodes.cpp +++ b/src/p_glnodes.cpp @@ -955,7 +955,7 @@ bool P_CheckNodes(MapData * map, bool rebuilt, int buildtime) if (!loaded) { // none found - we have to build new ones! - unsigned int startTime, endTime; + uint64_t startTime, endTime; startTime = I_msTime (); TArray polyspots, anchors; @@ -973,7 +973,7 @@ bool P_CheckNodes(MapData * map, bool rebuilt, int buildtime) builder.Extract (level); endTime = I_msTime (); DPrintf (DMSG_NOTIFY, "BSP generation took %.3f sec (%u segs)\n", (endTime - startTime) * 0.001, level.segs.Size()); - buildtime = endTime - startTime; + buildtime = (int32_t)(endTime - startTime); } } diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 336d4452e..dfa7ecb26 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -3933,7 +3933,7 @@ void P_SetupLevel (const char *lumpname, int position) } else reloop = true; - unsigned int startTime=0, endTime=0; + uint64_t startTime=0, endTime=0; bool BuildGLNodes; if (ForceNodeBuild) @@ -3990,7 +3990,7 @@ void P_SetupLevel (const char *lumpname, int position) // If the original nodes being loaded are not GL nodes they will be kept around for // use in P_PointInSubsector to avoid problems with maps that depend on the specific // nodes they were built with (P:AR E1M3 is a good example for a map where this is the case.) - reloop |= P_CheckNodes(map, BuildGLNodes, endTime - startTime); + reloop |= P_CheckNodes(map, BuildGLNodes, (uint32_t)(endTime - startTime)); hasglnodes = true; } else diff --git a/src/r_sky.cpp b/src/r_sky.cpp index eb31e2064..cc84f9fbb 100644 --- a/src/r_sky.cpp +++ b/src/r_sky.cpp @@ -165,7 +165,7 @@ void R_InitSkyMap () // //========================================================================== -void R_UpdateSky (uint32_t mstime) +void R_UpdateSky (uint64_t mstime) { // Scroll the sky double ms = (double)mstime * FRACUNIT; diff --git a/src/r_sky.h b/src/r_sky.h index 39ac77f27..e186ad3ae 100644 --- a/src/r_sky.h +++ b/src/r_sky.h @@ -44,6 +44,6 @@ extern int freelookviewheight; // Called whenever the sky changes. void R_InitSkyMap (); -void R_UpdateSky (uint32_t mstime); +void R_UpdateSky (uint64_t mstime); #endif //__R_SKY_H__ diff --git a/src/textures/animations.cpp b/src/textures/animations.cpp index 7b2aab98b..a9fa4c1bf 100644 --- a/src/textures/animations.cpp +++ b/src/textures/animations.cpp @@ -876,7 +876,7 @@ FDoorAnimation *FTextureManager::FindAnimatedDoor (FTextureID picnum) // //========================================================================== -void FAnimDef::SetSwitchTime (uint32_t mstime) +void FAnimDef::SetSwitchTime (uint64_t mstime) { int speedframe = bDiscrete ? CurFrame : 0; @@ -917,7 +917,7 @@ void FTextureManager::SetTranslation (FTextureID fromtexnum, FTextureID totexnum // //========================================================================== -void FTextureManager::UpdateAnimations (uint32_t mstime) +void FTextureManager::UpdateAnimations (uint64_t mstime) { for (unsigned int j = 0; j < mAnimations.Size(); ++j) { diff --git a/src/textures/textures.h b/src/textures/textures.h index 96bd8d3ca..539d38c43 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -90,7 +90,7 @@ struct FAnimDef uint16_t CurFrame; uint8_t AnimType; bool bDiscrete; // taken out of AnimType to have better control - uint32_t SwitchTime; // Time to advance to next frame + uint64_t SwitchTime; // Time to advance to next frame struct FAnimFrame { uint32_t SpeedMin; // Speeds are in ms, not tics @@ -106,7 +106,7 @@ struct FAnimDef ANIM_Random }; - void SetSwitchTime (uint32_t mstime); + void SetSwitchTime (uint64_t mstime); }; struct FSwitchDef @@ -505,7 +505,7 @@ public: int NumTextures () const { return (int)Textures.Size(); } - void UpdateAnimations (uint32_t mstime); + void UpdateAnimations (uint64_t mstime); int GuesstimateNumTextures (); FSwitchDef *FindSwitch (FTextureID texture); @@ -604,8 +604,8 @@ public: void SetSpeed(float fac) { Speed = fac; } FTexture *GetRedirect(bool wantwarped); - uint32_t GenTime; - uint32_t GenTimeBgra; + uint64_t GenTime; + uint64_t GenTimeBgra; float Speed; int WidthOffsetMultiplier, HeightOffsetMultiplier; // [mxd] protected: @@ -613,7 +613,7 @@ protected: uint8_t *Pixels; Span **Spans; - virtual void MakeTexture (uint32_t time); + virtual void MakeTexture (uint64_t time); int NextPo2 (int v); // [mxd] void SetupMultipliers (int width, int height); // [mxd] }; diff --git a/src/textures/warpbuffer.h b/src/textures/warpbuffer.h index 668c40aeb..62b0db13d 100644 --- a/src/textures/warpbuffer.h +++ b/src/textures/warpbuffer.h @@ -35,7 +35,7 @@ #include "textures/textures.h" template -void WarpBuffer(TYPE *Pixels, const TYPE *source, int width, int height, int xmul, int ymul, unsigned time, float Speed, int warptype) +void WarpBuffer(TYPE *Pixels, const TYPE *source, int width, int height, int xmul, int ymul, uint64_t time, float Speed, int warptype) { int ymask = height - 1; int x, y; diff --git a/src/textures/warptexture.cpp b/src/textures/warptexture.cpp index 43a215a2b..2e073c186 100644 --- a/src/textures/warptexture.cpp +++ b/src/textures/warptexture.cpp @@ -86,7 +86,7 @@ bool FWarpTexture::CheckModified () const uint8_t *FWarpTexture::GetPixels () { - uint32_t time = screen->FrameTime; + uint64_t time = screen->FrameTime; if (Pixels == NULL || time != GenTime) { @@ -97,7 +97,7 @@ const uint8_t *FWarpTexture::GetPixels () const uint32_t *FWarpTexture::GetPixelsBgra() { - uint32_t time = screen->FrameTime; + uint64_t time = screen->FrameTime; if (Pixels == NULL || time != GenTime) MakeTexture(time); @@ -119,7 +119,7 @@ const uint32_t *FWarpTexture::GetPixelsBgra() const uint8_t *FWarpTexture::GetColumn (unsigned int column, const Span **spans_out) { - uint32_t time =screen->FrameTime; + uint64_t time =screen->FrameTime; if (Pixels == NULL || time != GenTime) { @@ -148,7 +148,7 @@ const uint8_t *FWarpTexture::GetColumn (unsigned int column, const Span **spans_ } -void FWarpTexture::MakeTexture(uint32_t time) +void FWarpTexture::MakeTexture(uint64_t time) { const uint8_t *otherpix = SourcePic->GetPixels(); diff --git a/src/v_video.cpp b/src/v_video.cpp index 5f774a648..01ae8b428 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -870,8 +870,8 @@ void DFrameBuffer::DrawRateStuff () // Draws frame time and cumulative fps if (vid_fps) { - uint32_t ms = screen->FrameTime; - uint32_t howlong = ms - LastMS; + uint64_t ms = screen->FrameTime; + uint64_t howlong = ms - LastMS; if ((signed)howlong >= 0) { char fpsbuff[40]; @@ -888,7 +888,7 @@ void DFrameBuffer::DrawRateStuff () DTA_VirtualHeight, screen->GetHeight() / textScale, DTA_KeepRatio, true, TAG_DONE); - uint32_t thisSec = ms/1000; + uint32_t thisSec = (uint32_t)(ms/1000); if (LastSec < thisSec) { LastCount = FrameCount / (thisSec - LastSec); @@ -903,8 +903,8 @@ void DFrameBuffer::DrawRateStuff () // draws little dots on the bottom of the screen if (ticker) { - int i = I_GetTime(); - int tics = i - LastTic; + int64_t i = I_GetTime(); + int64_t tics = i - LastTic; uint8_t *buffer = GetBuffer(); LastTic = i; @@ -931,6 +931,7 @@ void DFrameBuffer::DrawRateStuff () } else { + int i; for (i = 0; i < tics*2; i += 2) Clear(i, Height-1, i+1, Height, 255, 0); for ( ; i < 20*2; i += 2) Clear(i, Height-1, i+1, Height, 0, 0); } diff --git a/src/v_video.h b/src/v_video.h index 4fae94198..1cbf565af 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -442,7 +442,7 @@ public: virtual void ScaleCoordsFromWindow(int16_t &x, int16_t &y) {} - uint32_t GetLastFPS() const { return LastCount; } + uint64_t GetLastFPS() const { return LastCount; } #ifdef _WIN32 virtual void PaletteChanged () = 0; @@ -463,7 +463,7 @@ protected: DFrameBuffer () {} private: - uint32_t LastMS, LastSec, FrameCount, LastCount, LastTic; + uint64_t LastMS, LastSec, FrameCount, LastCount, LastTic; bool isIn2D = false; }; From e418663a263c441763d38f7a1f72206a85a53bb3 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Wed, 15 Nov 2017 22:20:55 -0500 Subject: [PATCH 23/29] - fixed: Reverted an accident in a previous commit where I_StartTic() was moved inappropriately. The new location fixed a mouse stutter, however, it causes net desyncs so it cannot be used here. --- src/d_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 4e1655747..be097ac98 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1053,10 +1053,10 @@ void D_DoomLoop () } else { - I_StartTic (); TryRunTics (); // will run at least one tic } // Update display, next frame, with current state. + I_StartTic (); D_Display (); if (wantToRestart) { From 16e6fbf5bff037d3b2bb48938cf1d88ad0f68932 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Thu, 23 Nov 2017 21:12:50 -0500 Subject: [PATCH 24/29] - commit fix - todo: need to re-double/floatify the model timers again --- 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 70c4da18d..f05bd7d3c 100644 --- a/src/gl/models/gl_models.cpp +++ b/src/gl/models/gl_models.cpp @@ -384,7 +384,7 @@ void FGLModelRenderer::DrawElements(int primitiveType, int numIndices, int eleme float FGLModelRenderer::GetTimeFloat() { - return (float)I_MSTime() * (float)TICRATE / 1000.0f; + return (float)I_msTime() * (float)TICRATE / 1000.0f; } ///////////////////////////////////////////////////////////////////////////// From 1f00810f40f882fd3e0736b03323f3d53bb99fcf Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Thu, 23 Nov 2017 21:27:16 -0500 Subject: [PATCH 25/29] - re-doubled the model rotation code --- src/gl/models/gl_models.cpp | 6 +++--- src/gl/models/gl_models.h | 4 ++-- src/polyrenderer/scene/poly_model.cpp | 2 +- src/polyrenderer/scene/poly_model.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/gl/models/gl_models.cpp b/src/gl/models/gl_models.cpp index f05bd7d3c..989b6d6ab 100644 --- a/src/gl/models/gl_models.cpp +++ b/src/gl/models/gl_models.cpp @@ -102,7 +102,7 @@ void FModelRenderer::RenderModel(float x, float y, float z, FSpriteModelFrame *s if (smf->flags & MDL_ROTATING) { - const float time = smf->rotationSpeed*GetTimeFloat() / 200.f; + const double time = smf->rotationSpeed*GetTimeFloat() / 200.f; rotateOffset = float((time - xs_FloorToInt(time)) *360.f); } @@ -225,7 +225,7 @@ void FModelRenderer::RenderFrameModels(const FSpriteModelFrame *smf, // [BB] In case the tic counter is frozen we have to leave ticFraction at zero. if (ConsoleState == c_up && menuactive != MENU_On && !(level.flags2 & LEVEL2_FROZEN)) { - float time = GetTimeFloat(); + double time = GetTimeFloat(); ticFraction = (time - static_cast(time)); } inter = static_cast(curState->Tics - curTics - ticFraction) / static_cast(curState->Tics); @@ -382,7 +382,7 @@ void FGLModelRenderer::DrawElements(int primitiveType, int numIndices, int eleme glDrawElements(primitiveType, numIndices, elementType, (void*)(intptr_t)offset); } -float FGLModelRenderer::GetTimeFloat() +double FGLModelRenderer::GetTimeFloat() { return (float)I_msTime() * (float)TICRATE / 1000.0f; } diff --git a/src/gl/models/gl_models.h b/src/gl/models/gl_models.h index 84e331e31..cc41466db 100644 --- a/src/gl/models/gl_models.h +++ b/src/gl/models/gl_models.h @@ -71,7 +71,7 @@ public: virtual void DrawArrays(int primitiveType, int start, int count) = 0; virtual void DrawElements(int primitiveType, int numIndices, int elementType, size_t offset) = 0; - virtual float GetTimeFloat() = 0; + virtual double GetTimeFloat() = 0; private: void RenderFrameModels(const FSpriteModelFrame *smf, const FState *curState, const int curTics, const PClass *ti, Matrix3x4 *normaltransform, int translation); @@ -92,7 +92,7 @@ public: void SetMaterial(FTexture *skin, int clampmode, int translation) override; void DrawArrays(int primitiveType, int start, int count) override; void DrawElements(int primitiveType, int numIndices, int elementType, size_t offset) override; - float GetTimeFloat() override; + double GetTimeFloat() override; }; class FModel diff --git a/src/polyrenderer/scene/poly_model.cpp b/src/polyrenderer/scene/poly_model.cpp index 88064ce97..f9d7b4887 100644 --- a/src/polyrenderer/scene/poly_model.cpp +++ b/src/polyrenderer/scene/poly_model.cpp @@ -175,7 +175,7 @@ void PolyModelRenderer::DrawElements(int primitiveType, int numIndices, int elem args.DrawElements(Thread, VertexBuffer, IndexBuffer + offset / sizeof(unsigned int), numIndices); } -float PolyModelRenderer::GetTimeFloat() +double PolyModelRenderer::GetTimeFloat() { return 0.0f; // (float)gl_frameMS * (float)TICRATE / 1000.0f; } diff --git a/src/polyrenderer/scene/poly_model.h b/src/polyrenderer/scene/poly_model.h index 8585be44c..d80bed45f 100644 --- a/src/polyrenderer/scene/poly_model.h +++ b/src/polyrenderer/scene/poly_model.h @@ -46,7 +46,7 @@ public: void SetMaterial(FTexture *skin, int clampmode, int translation) override; void DrawArrays(int primitiveType, int start, int count) override; void DrawElements(int primitiveType, int numIndices, int elementType, size_t offset) override; - float GetTimeFloat() override; + double GetTimeFloat() override; PolyRenderThread *Thread = nullptr; const TriMatrix &WorldToClip; From 3842071b23e793875681554e62d77a42588ad78c Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Wed, 15 Nov 2017 22:28:18 -0500 Subject: [PATCH 26/29] - implemented i_timescale to control the flow of time. --- src/i_time.cpp | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/i_time.cpp b/src/i_time.cpp index 4be0a8b82..0d5d96760 100644 --- a/src/i_time.cpp +++ b/src/i_time.cpp @@ -38,6 +38,8 @@ #include #include "i_time.h" #include "doomdef.h" +#include "c_cvars.h" +#include "doomstat.h" //========================================================================== // @@ -49,10 +51,30 @@ static uint64_t FirstFrameStartTime; static uint64_t CurrentFrameStartTime; static uint64_t FreezeTime; +static double TimeScale = 1.0; + +CUSTOM_CVAR(Float, i_timescale, 1.0f, CVAR_NOINITCALL) +{ + if (netgame && self != 1.0f) + { + Printf("Time scale cannot be changed in net games.\n"); + self = 1.0f; + } + else + { + I_FreezeTime(true); + float clampValue = (self < 0.05) ? 0.05 : self; + if (self != clampValue) + self = clampValue; + TimeScale = self; + I_FreezeTime(false); + } +} + static uint64_t GetClockTimeNS() { using namespace std::chrono; - return (uint64_t)duration_cast(steady_clock::now().time_since_epoch()).count(); + return (uint64_t)duration_cast(steady_clock::now().time_since_epoch()).count() * TimeScale; } static uint64_t MSToNS(unsigned int ms) From 5181e3ebb2edb250b908b27ccc497daf5dd13a15 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Thu, 23 Nov 2017 22:04:42 -0500 Subject: [PATCH 27/29] - rewound time from 2917 to 2017. At least, at this point, we know ZDoom's future is secure. --- 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 0d5d96760..71c7a8655 100644 --- a/src/i_time.cpp +++ b/src/i_time.cpp @@ -3,8 +3,8 @@ ** Implements the timer ** **--------------------------------------------------------------------------- -** Copyright 1998-2916 Randy Heit -** Copyright 2917 Magnus Norddahl +** Copyright 1998-2016 Randy Heit +** Copyright 2017 Magnus Norddahl ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without From 297f00aa4ba0cefc2218dc67217dcc45f335e423 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Thu, 23 Nov 2017 22:37:07 -0500 Subject: [PATCH 28/29] - fix model rotation some more - a couple compiler warning fixes --- src/gl/models/gl_models.cpp | 6 +++--- src/i_time.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gl/models/gl_models.cpp b/src/gl/models/gl_models.cpp index 989b6d6ab..d170dce01 100644 --- a/src/gl/models/gl_models.cpp +++ b/src/gl/models/gl_models.cpp @@ -76,7 +76,7 @@ void FModelRenderer::RenderModel(float x, float y, float z, FSpriteModelFrame *s float scaleFactorZ = actor->Scale.Y * smf->zscale; float pitch = 0; float roll = 0; - float rotateOffset = 0; + double rotateOffset = 0; float angle = actor->Angles.Yaw.Degrees; // [BB] Workaround for the missing pitch information. @@ -102,8 +102,8 @@ void FModelRenderer::RenderModel(float x, float y, float z, FSpriteModelFrame *s if (smf->flags & MDL_ROTATING) { - const double time = smf->rotationSpeed*GetTimeFloat() / 200.f; - rotateOffset = float((time - xs_FloorToInt(time)) *360.f); + const double time = smf->rotationSpeed*GetTimeFloat() / 200.; + rotateOffset = double((time - xs_FloorToInt(time)) *360.); } // Added MDL_USEACTORPITCH and MDL_USEACTORROLL flags processing. diff --git a/src/i_time.cpp b/src/i_time.cpp index 71c7a8655..2aada4861 100644 --- a/src/i_time.cpp +++ b/src/i_time.cpp @@ -63,7 +63,7 @@ CUSTOM_CVAR(Float, i_timescale, 1.0f, CVAR_NOINITCALL) else { I_FreezeTime(true); - float clampValue = (self < 0.05) ? 0.05 : self; + float clampValue = (self < 0.05) ? 0.05f : self; if (self != clampValue) self = clampValue; TimeScale = self; @@ -74,7 +74,7 @@ CUSTOM_CVAR(Float, i_timescale, 1.0f, CVAR_NOINITCALL) static uint64_t GetClockTimeNS() { using namespace std::chrono; - return (uint64_t)duration_cast(steady_clock::now().time_since_epoch()).count() * TimeScale; + return (uint64_t)((duration_cast(steady_clock::now().time_since_epoch()).count()) * TimeScale); } static uint64_t MSToNS(unsigned int ms) From c80c2ba635d0cc560f3f468cfb93b4ba11e3b559 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Fri, 24 Nov 2017 14:38:55 -0500 Subject: [PATCH 29/29] - added 100% CPU fix provided by Leonard2: https://forum.zdoom.org/viewtopic.php?p=1028500#p1028500 --- 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 2aada4861..516ecfad1 100644 --- a/src/i_time.cpp +++ b/src/i_time.cpp @@ -132,7 +132,7 @@ int I_WaitForTic(int 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; + uint64_t sleepTime = NSToMS(FirstFrameStartTime + TicToNS(prevtic + 1) - I_nsTime()); if (sleepTime > 2) std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime - 2)); @@ -154,7 +154,7 @@ uint64_t I_msTime() int I_GetTime() { - return NSToTic(CurrentFrameStartTime - FirstFrameStartTime) + 1; + return NSToTic(CurrentFrameStartTime - FirstFrameStartTime); } double I_GetTimeFrac()