From ca8fb7457b426aa7e75b9c0df5ac7f7d8518a945 Mon Sep 17 00:00:00 2001 From: myT Date: Wed, 27 Dec 2017 05:43:28 +0100 Subject: [PATCH] reduced CPU usage in the client --- changelog.txt | 2 ++ code/client/cl_scrn.cpp | 7 ++++++ code/linux/linux_shared.cpp | 33 +++++++++++++++++++++++++ code/linux/sdl_core.cpp | 6 +++++ code/qcommon/common.cpp | 49 ++++++++++++++++++++++++++++++++----- code/qcommon/qcommon.h | 8 ++++++ code/win32/win_glimp.cpp | 6 +++++ code/win32/win_shared.cpp | 44 +++++++++++++++++++++++++++++++++ 8 files changed, 149 insertions(+), 6 deletions(-) diff --git a/changelog.txt b/changelog.txt index 6f6d596..3d6ed76 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,8 @@ DD Mmm 17 - 1.49 +chg: reduced CPU usage in the client + add: console color customization cvars con_colBG (default: "101013F6") - console and help panel background con_colBorder (default: "4778B2FF") - the console and help panel borders diff --git a/code/client/cl_scrn.cpp b/code/client/cl_scrn.cpp index b71963e..5ae7a0a 100644 --- a/code/client/cl_scrn.cpp +++ b/code/client/cl_scrn.cpp @@ -394,10 +394,16 @@ static void SCR_PerformanceCounters() void SCR_UpdateScreen() { static int recursive = 0; + static int lastRenderTime = 0; if ( !scr_initialized ) return; +#ifndef DEDICATED + if ( !CL_VideoRecording() && Sys_IsMinimized() && Sys_Milliseconds() - lastRenderTime < 1000 ) + return; +#endif + // there are several cases where this IS called twice in one frame // easiest example is: conn to a server, kill the server if ( ++recursive > 2 ) { @@ -427,5 +433,6 @@ void SCR_UpdateScreen() } recursive = 0; + lastRenderTime = Sys_Milliseconds(); } diff --git a/code/linux/linux_shared.cpp b/code/linux/linux_shared.cpp index 2ef3691..68d25de 100644 --- a/code/linux/linux_shared.cpp +++ b/code/linux/linux_shared.cpp @@ -40,6 +40,39 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define MEM_THRESHOLD 96*1024*1024 + +static void LIN_MicroSleep( int us ) +{ + timespec req, rem; + req.tv_sec = us / 1000000; + req.tv_nsec = (us % 1000000) * 1000; + while (clock_nanosleep(CLOCK_REALTIME, 0, &req, &rem) == EINTR) { + req = rem; + } +} + + +void Sys_Sleep( int ms ) +{ + LIN_MicroSleep(ms * 1000); +} + + +void Sys_MicroSleep( int us ) +{ + LIN_MicroSleep(us); +} + + +int64_t Sys_Microseconds() +{ + timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + + return (int64_t)ts.tv_sec * 1000000 + (int64_t)ts.tv_nsec / 1000; +} + + qboolean Sys_LowPhysicalMemory() { return qfalse; // FIXME diff --git a/code/linux/sdl_core.cpp b/code/linux/sdl_core.cpp index 591e573..160bba7 100644 --- a/code/linux/sdl_core.cpp +++ b/code/linux/sdl_core.cpp @@ -595,3 +595,9 @@ void Sys_MatchAlert( sysMatchAlertEvent_t event ) else if (event == SMAE_MATCH_END) Lin_MatchEndAlert(); } + + +qbool Sys_IsMinimized() +{ + return (glimp.window != NULL) && (SDL_GetWindowFlags(glimp.window) & SDL_WINDOW_MINIMIZED) != 0; +} diff --git a/code/qcommon/common.cpp b/code/qcommon/common.cpp index c21bffb..5aedb7f 100644 --- a/code/qcommon/common.cpp +++ b/code/qcommon/common.cpp @@ -26,6 +26,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "common_help.h" #include +#ifndef INT64_MIN +# define INT64_MIN 0x8000000000000000LL +#endif + #if (_MSC_VER >= 1400) // Visual C++ 2005 or later #define MSVC_CPUID 1 #include @@ -2445,19 +2449,52 @@ void Com_Frame() minMsec = 1000 / com_maxfps->integer; #ifndef DEDICATED + qbool preciseCap = qtrue; // let's not limit the download speed by sleeping too much qbool CL_MapDownload_Active(); // in client.h if ( CL_MapDownload_Active() ) - minMsec = 1; + minMsec = 4; + else if ( Sys_IsMinimized() ) { + minMsec = 20; + preciseCap = qfalse; + } +#else + const qbool preciseCap = qfalse; #endif + // decide when we should stop sleeping + static int64_t targetTimeUS = INT64_MIN; + const int64_t frameDurationUS = 1000000 / com_maxfps->integer; + if ( Sys_Microseconds() > targetTimeUS + 3 * frameDurationUS ) + targetTimeUS = Sys_Microseconds() + frameDurationUS; + else + targetTimeUS += frameDurationUS; + + // sleep if needed + int runEventLoop = 0; + if ( preciseCap ) { + for ( ;; ) { + runEventLoop ^= 1; + const int64_t remainingUS = targetTimeUS - Sys_Microseconds(); + if ( remainingUS > 3000 && runEventLoop ) + Com_EventLoop(); + else if ( remainingUS > 1000 ) + Sys_Sleep( 1 ); + else if ( remainingUS > 50 ) + Sys_MicroSleep( 50 ); + else + break; + } + } else { + while ( targetTimeUS - Sys_Microseconds() > 1000 ) { + Sys_Sleep(1); + } + } + static int lastTime = 0; - int msec; - do { - com_frameTime = Com_EventLoop(); - msec = com_frameTime - lastTime; - } while ( msec < minMsec ); lastTime = com_frameTime; + com_frameTime = Com_EventLoop(); + int msec = com_frameTime - lastTime; Cbuf_Execute(); diff --git a/code/qcommon/qcommon.h b/code/qcommon/qcommon.h index 4de384f..2ae3c1d 100644 --- a/code/qcommon/qcommon.h +++ b/code/qcommon/qcommon.h @@ -1122,6 +1122,14 @@ int Sys_GetUptimeSeconds( qbool parent ); // negative if not available void Sys_LoadHistory(); void Sys_SaveHistory(); +void Sys_Sleep( int ms ); +void Sys_MicroSleep( int us ); +int64_t Sys_Microseconds(); + +#ifndef DEDICATED +qbool Sys_IsMinimized(); +#endif + // huffman.cpp - id's original code // used for out-of-band (OOB) datagrams with dynamically created trees void DynHuff_Compress( msg_t* buf, int offset ); diff --git a/code/win32/win_glimp.cpp b/code/win32/win_glimp.cpp index bf8b8ac..13c8940 100644 --- a/code/win32/win_glimp.cpp +++ b/code/win32/win_glimp.cpp @@ -697,6 +697,12 @@ void Sys_GL_Shutdown() } +qbool Sys_IsMinimized() +{ + return ( g_wv.hWnd != NULL ) && !!IsIconic( g_wv.hWnd ); +} + + void WIN_UpdateResolution( int width, int height ) { glInfo.winWidth = width; diff --git a/code/win32/win_shared.cpp b/code/win32/win_shared.cpp index d71f133..5da61b6 100644 --- a/code/win32/win_shared.cpp +++ b/code/win32/win_shared.cpp @@ -36,6 +36,50 @@ int Sys_Milliseconds() } +void Sys_Sleep( int ms ) +{ + if (ms >= 1) + Sleep(ms); +} + +void Sys_MicroSleep( int us ) +{ + if (us <= 0) + return; + + LARGE_INTEGER frequency; + LARGE_INTEGER endTime; + QueryPerformanceCounter(&endTime); + QueryPerformanceFrequency(&frequency); + endTime.QuadPart += ((LONGLONG)us * frequency.QuadPart) / 1000000LL; + + LARGE_INTEGER currentTime; + do { + SwitchToThread(); + QueryPerformanceCounter(¤tTime); + } while (currentTime.QuadPart < endTime.QuadPart); +} + + +int64_t Sys_Microseconds() +{ + static qbool initialized = qfalse; + static LARGE_INTEGER start; + static LARGE_INTEGER freq; + + if (!initialized) { + initialized = qtrue; + QueryPerformanceFrequency(&freq); + QueryPerformanceCounter(&start); + } + + LARGE_INTEGER now; + QueryPerformanceCounter(&now); + + return ((now.QuadPart - start.QuadPart) * 1000000LL) / freq.QuadPart; +} + + const char* Sys_DefaultHomePath() { return NULL;