diff --git a/neo/framework/common_frame.cpp b/neo/framework/common_frame.cpp index 36a3a5ec..ea41996a 100644 --- a/neo/framework/common_frame.cpp +++ b/neo/framework/common_frame.cpp @@ -670,84 +670,89 @@ void idCommonLocal::Frame() // How many game frames to run int numGameFrames = 0; - for( ;; ) { - const int thisFrameTime = Sys_Milliseconds(); - static int lastFrameTime = thisFrameTime; // initialized only the first time - const int deltaMilliseconds = thisFrameTime - lastFrameTime; - lastFrameTime = thisFrameTime; - // if there was a large gap in time since the last frame, or the frame - // rate is very very low, limit the number of frames we will run - const int clampedDeltaMilliseconds = Min( deltaMilliseconds, com_deltaTimeClamp.GetInteger() ); - - gameTimeResidual += clampedDeltaMilliseconds * timescale.GetFloat(); - - // don't run any frames when paused - // jpcy: the game is paused when playing a demo, but playDemo should wait like the game does - // SRS - don't wait if window not in focus and playDemo itself paused - if( pauseGame && ( !( readDemo && !timeDemo ) || session->IsSystemUIShowing() || com_pause.GetInteger() ) ) - { - gameFrame++; - gameTimeResidual = 0; - break; - } - - // debug cvar to force multiple game tics - if( com_fixedTic.GetInteger() > 0 ) - { - numGameFrames = com_fixedTic.GetInteger(); - gameFrame += numGameFrames; - gameTimeResidual = 0; - break; - } - - if( syncNextGameFrame ) - { - // don't sleep at all - syncNextGameFrame = false; - gameFrame++; - numGameFrames++; - gameTimeResidual = 0; - break; - } + OPTICK_EVENT( "Wait for Frame" ) for( ;; ) { - // How much time to wait before running the next frame, - // based on com_engineHz - const int frameDelay = FRAME_TO_MSEC( gameFrame + 1 ) - FRAME_TO_MSEC( gameFrame ); - if( gameTimeResidual < frameDelay ) + const int thisFrameTime = Sys_Milliseconds(); + static int lastFrameTime = thisFrameTime; // initialized only the first time + const int deltaMilliseconds = thisFrameTime - lastFrameTime; + lastFrameTime = thisFrameTime; + + // if there was a large gap in time since the last frame, or the frame + // rate is very very low, limit the number of frames we will run + const int clampedDeltaMilliseconds = Min( deltaMilliseconds, com_deltaTimeClamp.GetInteger() ); + + gameTimeResidual += clampedDeltaMilliseconds * timescale.GetFloat(); + + // don't run any frames when paused + // jpcy: the game is paused when playing a demo, but playDemo should wait like the game does + // SRS - don't wait if window not in focus and playDemo itself paused + if( pauseGame && ( !( readDemo && !timeDemo ) || session->IsSystemUIShowing() || com_pause.GetInteger() ) ) { + gameFrame++; + gameTimeResidual = 0; break; } - gameTimeResidual -= frameDelay; - gameFrame++; - numGameFrames++; - // if there is enough residual left, we may run additional frames - } - if( numGameFrames > 0 ) - { - // ready to actually run them - break; - } + // debug cvar to force multiple game tics + if( com_fixedTic.GetInteger() > 0 ) + { + numGameFrames = com_fixedTic.GetInteger(); + gameFrame += numGameFrames; + gameTimeResidual = 0; + break; + } - // if we are vsyncing, we always want to run at least one game - // frame and never sleep, which might happen due to scheduling issues - // if we were just looking at real time. - if( com_noSleep.GetBool() ) - { - numGameFrames = 1; - gameFrame += numGameFrames; - gameTimeResidual = 0; - break; - } + if( syncNextGameFrame ) + { + // don't sleep at all + syncNextGameFrame = false; + gameFrame++; + numGameFrames++; + gameTimeResidual = 0; + break; + } - // not enough time has passed to run a frame, as might happen if - // we don't have vsync on, or the monitor is running at 120hz while - // com_engineHz is 60, so sleep a bit and check again - Sys_Sleep( 0 ); + for( ;; ) + { + // How much time to wait before running the next frame, + // based on com_engineHz + const int frameDelay = FRAME_TO_MSEC( gameFrame + 1 ) - FRAME_TO_MSEC( gameFrame ); + if( gameTimeResidual < frameDelay ) + { + break; + } + gameTimeResidual -= frameDelay; + gameFrame++; + numGameFrames++; + // if there is enough residual left, we may run additional frames + } + + if( numGameFrames > 0 ) + { + // ready to actually run them + break; + } + + // if we are vsyncing, we always want to run at least one game + // frame and never sleep, which might happen due to scheduling issues + // if we were just looking at real time. + if( com_noSleep.GetBool() ) + { + numGameFrames = 1; + gameFrame += numGameFrames; + gameTimeResidual = 0; + break; + } + + // not enough time has passed to run a frame, as might happen if + // we don't have vsync on, or the monitor is running at 120hz while + // com_engineHz is 60, so sleep a bit and check again + Sys_Sleep( 0 ); + } } // jpcy: playDemo uses the game frame wait logic, but shouldn't run any game frames diff --git a/neo/renderer/NVRHI/RenderBackend_NVRHI.cpp b/neo/renderer/NVRHI/RenderBackend_NVRHI.cpp index f985b942..192de6be 100644 --- a/neo/renderer/NVRHI/RenderBackend_NVRHI.cpp +++ b/neo/renderer/NVRHI/RenderBackend_NVRHI.cpp @@ -1547,6 +1547,8 @@ idRenderBackend::GL_StartFrame */ void idRenderBackend::GL_StartFrame() { + OPTICK_EVENT( "StartFrame" ); + // fetch GPU timer queries of last frame renderLog.FetchGPUTimers( pc ); @@ -1569,6 +1571,8 @@ idRenderBackend::GL_EndFrame */ void idRenderBackend::GL_EndFrame() { + OPTICK_EVENT( "EndFrame" ); + if( deviceManager->GetGraphicsAPI() == nvrhi::GraphicsAPI::VULKAN ) { tr.SetReadyToPresent(); @@ -1596,6 +1600,8 @@ We want to exit this with the GPU idle, right at vsync */ void idRenderBackend::GL_BlockingSwapBuffers() { + OPTICK_EVENT( "BlockingSwapBuffers" ); + // Make sure that all frames have finished rendering deviceManager->GetDevice()->waitForIdle(); diff --git a/neo/renderer/RenderBackend.cpp b/neo/renderer/RenderBackend.cpp index 6ac3a674..7b20c146 100644 --- a/neo/renderer/RenderBackend.cpp +++ b/neo/renderer/RenderBackend.cpp @@ -6456,6 +6456,8 @@ smp extensions, or asyncronously by another thread. */ void idRenderBackend::ExecuteBackEndCommands( const emptyCommand_t* cmds ) { + SCOPED_PROFILE_EVENT( "ExecuteBackEndCommands" ); + // r_debugRenderToTexture int c_draw3d = 0; int c_draw2d = 0; @@ -7072,6 +7074,8 @@ is 0, so the stereoEye parameter is not always the same as that. */ void idRenderBackend::DrawView( const void* data, const int stereoEye ) { + SCOPED_PROFILE_EVENT( "Backend_DrawView" ); + const drawSurfsCommand_t* cmd = ( const drawSurfsCommand_t* )data; viewDef = cmd->viewDef; diff --git a/neo/renderer/RenderSystem.cpp b/neo/renderer/RenderSystem.cpp index ed6c66f7..3fc3b98b 100644 --- a/neo/renderer/RenderSystem.cpp +++ b/neo/renderer/RenderSystem.cpp @@ -658,7 +658,7 @@ void idRenderSystemLocal::SwapCommandBuffers_FinishRendering( performanceCounters_t* pc ) { - SCOPED_PROFILE_EVENT( "SwapCommandBuffers" ); + SCOPED_PROFILE_EVENT( "SwapCommandBuffers_FinishRendering" ); if( gpuMicroSec != NULL ) { @@ -870,6 +870,8 @@ idRenderSystemLocal::SwapCommandBuffers_FinishCommandBuffers */ const emptyCommand_t* idRenderSystemLocal::SwapCommandBuffers_FinishCommandBuffers() { + OPTICK_EVENT( "SwapCommandBuffers_FinishCommandBuffers" ); + if( !IsInitialized() ) { return NULL;