From 09e0a4c5c8c8972d984fad876151964c0db47d72 Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Mon, 27 Sep 2021 17:56:45 -0400 Subject: [PATCH] Fix Frame time calculation to properly handle CPU/GPU parallelism --- neo/framework/Console.cpp | 11 ++++++----- neo/framework/common_frame.cpp | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/neo/framework/Console.cpp b/neo/framework/Console.cpp index fe937505..c17d4d35 100644 --- a/neo/framework/Console.cpp +++ b/neo/framework/Console.cpp @@ -290,14 +290,15 @@ float idConsoleLocal::DrawFPS( float y ) const uint64 rendererGPUInteractionsTime = commonLocal.GetRendererGpuInteractionsMicroseconds(); const uint64 rendererGPUShaderPassesTime = commonLocal.GetRendererGpuShaderPassMicroseconds(); const uint64 rendererGPUPostProcessingTime = commonLocal.GetRendererGpuPostProcessingMicroseconds(); - const int maxTime = 1000 / com_engineHz_latched * 1000; + const int maxTime = int( 1000 / com_engineHz_latched ) * 1000; + // SRS - Calculate time waiting for GPU to sync at the start of a frame (com_smp = 1 or 0) and at the end of a frame (com_smp = -1) + const uint64 rendererSyncTime_StartFrame = commonLocal.mainFrameTiming.finishSyncTime - commonLocal.mainFrameTiming.startSyncTime; + const uint64 rendererSyncTime_EndFrame = commonLocal.mainFrameTiming.finishSyncTime_EndFrame - commonLocal.mainFrameTiming.startRenderTime; + // SRS - Total CPU and Frame time calculations depend on whether game is operating in smp mode or not const uint64 totalCPUTime = ( com_smp.GetInteger() > 0 && com_editors == 0 ? std::max( gameThreadTotalTime, rendererBackEndTime ) : gameThreadTotalTime + rendererBackEndTime ); - // SRS - Calculate rendererSyncTime depending on smp mode and use to determine whether a frame loss has occurred - const uint64 rendererSyncTime = ( com_smp.GetInteger() >= 0 ? commonLocal.mainFrameTiming.finishSyncTime - commonLocal.mainFrameTiming.startSyncTime : commonLocal.mainFrameTiming.finishSyncTime_EndFrame - commonLocal.mainFrameTiming.finishRenderTime ); - const uint64 frameLossTime = ( rendererSyncTime < maxTime || rendererGPUTime > maxTime ? 0 : maxTime ); - const uint64 totalFrameTime = totalCPUTime + rendererGPUTime + frameLossTime; + const uint64 totalFrameTime = ( com_smp.GetInteger() > 0 && com_editors == 0 ? std::max( gameThreadTotalTime, rendererSyncTime_EndFrame ) : gameThreadTotalTime + rendererSyncTime_EndFrame ) + rendererSyncTime_StartFrame; #if 1 diff --git a/neo/framework/common_frame.cpp b/neo/framework/common_frame.cpp index b46ab9b2..aeddf302 100644 --- a/neo/framework/common_frame.cpp +++ b/neo/framework/common_frame.cpp @@ -897,9 +897,9 @@ void idCommonLocal::Frame() { // RB: this is the same as Doom 3 renderSystem->EndFrame() renderSystem->SwapCommandBuffers_FinishRendering( &time_frontend, &time_backend, &time_shadows, &time_gpu, &stats_backend, &stats_frontend ); - // SRS - Use finishSyncTime_EndFrame to record timing after sync for com_smp = -1, used in idConsoleLocal::DrawFPS() for calculating rendererSyncTime - frameTiming.finishSyncTime_EndFrame = Sys_Microseconds(); } + // SRS - Use finishSyncTime_EndFrame to record timing after sync for com_smp = -1, and just before gameThread.WaitForThread() for com_smp = 1 + frameTiming.finishSyncTime_EndFrame = Sys_Microseconds(); // make sure the game / draw thread has completed // This may block if the game is taking longer than the render back end