/* ===================== idRenderSystemLocal::SwapCommandBuffers_FinishRendering ===================== */ void idRenderSystemLocal::SwapCommandBuffers_FinishRendering( uint64 * frontEndMicroSec, uint64 * backEndMicroSec, uint64 * shadowMicroSec, uint64 * gpuMicroSec ) { SCOPED_PROFILE_EVENT( "SwapCommandBuffers" ); if ( gpuMicroSec != NULL ) { *gpuMicroSec = 0; // until shown otherwise } if ( !R_IsInitialized() ) { return; } // After coming back from an autoswap, we won't have anything to render if ( frameData->cmdHead->next != NULL ) { // wait for our fence to hit, which means the swap has actually happened // We must do this before clearing any resources the GPU may be using void GL_BlockingSwapBuffers(); GL_BlockingSwapBuffers(); } // read back the start and end timer queries from the previous frame if ( glConfig.timerQueryAvailable ) { uint64 drawingTimeNanoseconds = 0; if ( tr.timerQueryId != 0 ) { qglGetQueryObjectui64vEXT( tr.timerQueryId, GL_QUERY_RESULT, &drawingTimeNanoseconds ); } if ( gpuMicroSec != NULL ) { *gpuMicroSec = drawingTimeNanoseconds / 1000; } } //------------------------------ // save out timing information if ( frontEndMicroSec != NULL ) { *frontEndMicroSec = pc.frontEndMicroSec; } if ( backEndMicroSec != NULL ) { *backEndMicroSec = backEnd.pc.totalMicroSec; } if ( shadowMicroSec != NULL ) { *shadowMicroSec = backEnd.pc.shadowMicroSec; } // print any other statistics and clear all of them R_PerformanceCounters(); // check for dynamic changes that require some initialization R_CheckCvars(); // check for errors GL_CheckErrors(); }
/* ============= EndFrame Returns the number of msec spent in the back end ============= */ void idRenderSystemLocal::EndFrame( int *frontEndMsec, int *backEndMsec, bool swapFrontBack ) { emptyCommand_t *cmd; if ( !glConfig.isInitialized ) { return; } // close any gui drawing guiModel->EmitFullScreen(); guiModel->Clear(); // save out timing information if ( frontEndMsec ) { *frontEndMsec = pc.frontEndMsec; } if ( backEndMsec ) { *backEndMsec = backEnd.pc.msec; } // print any other statistics and clear all of them R_PerformanceCounters(); // check for dynamic changes that require some initialization R_CheckCvars(); // check for errors GL_CheckErrors(); // add the swapbuffers command if(swapFrontBack) { cmd = (emptyCommand_t *)R_GetCommandBuffer( sizeof( *cmd ) ); cmd->commandId = RC_SWAP_BUFFERS; } // start the back end up again with the new command list R_IssueRenderCommands(); // use the other buffers next frame, because another CPU // may still be rendering into the current buffers R_ToggleSmpFrame(); // we can now release the vertexes used this frame vertexCache.EndFrame(); if ( session->writeDemo ) { session->writeDemo->WriteInt( DS_RENDER ); session->writeDemo->WriteInt( DC_END_FRAME ); if ( r_showDemo.GetBool() ) { common->Printf( "write DC_END_FRAME\n" ); } } }