Doom3 execution unrolled by Fabien Sanglard
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
Sys_SetPhysicalWorkMemory( 192 << 20, 1024 << 20 ); //Min = 201,326,592 Max = 1,073,741,824
Sys_GetCurrentMemoryStatus( exeLaunchMemoryStats );
Sys_CreateConsole();
SetErrorMode( SEM_FAILCRITICALERRORS );
for ( int i = 0; i < MAX_CRITICAL_SECTIONS; i++ ) {
InitializeCriticalSection( &win32.criticalSections[i] );
}
Sys_Milliseconds();
common->Init( 0, NULL, lpCmdLine )
{
idLib::Init();
ParseCommandLine( argc, argv );
cmdSystem->Init(); // init console command system
cvarSystem->Init(); // init CVar system
idCVar::RegisterStaticVars(); // register all static CVars
idKeyInput::Init(); // initialize key input/binding, done early so bind command exists
console->Init(); // init the console so we can take prints
Sys_Init(); // get architecture info
Sys_InitNetworking(); // initialize networking
if ( !idAsyncNetwork::serverDedicated.GetInteger() && Sys_AlreadyRunning() )
Sys_Quit();
InitSIMD(); // initialize processor specific SIMD implementation
InitCommands(); // init commands
InitGame(); // game specific initialization
ClearCommandLine();
com_fullyInitialized = true;
}
Sys_StartAsyncThread();
{
// Create a thread that will block on hTimer in order to run at 60Hz (every 16 milliseconds).
// The Thread calls common->Async over and over for Sound mixing and input generation.
while ( 1 )
{
usleep( 16666 );
common->Async();
Sys_TriggerEvent( TRIGGER_EVENT_ONE );
pthread_testcancel();
}
}
Sys_ShowConsole
// main game loop
while( 1 )
{
Win_Frame(); //Show or hide the console
// Called repeatedly as the foreground thread for rendering and game logic.
common->Frame() // All of Doom3 beef is here.
{
Sys_GenerateEvents(); // pump all the events
WriteConfiguration(); // write config file if anything changed
eventLoop->RunEventLoop();
com_frameTime = com_ticNumber * USERCMD_MSEC;
idAsyncNetwork::RunFrame();
session->Frame()
{
Sys_GrabMouseCursor
while( 1 ) {
latchedTicNumber = com_ticNumber;
if ( latchedTicNumber >= minTic ) {
break;
}
Sys_WaitForEvent( TRIGGER_EVENT_ONE );
}
GuiFrameEvents
for ( i = 0 ; i < gameTicsToRun ; i++ )
RunGameTic()
{
//From this point execution jumps in the GameX86.dll address space.
game->RunFrame( &cmd );
{
GetLocalPlayer
ComputeSlowMsec
random.RandomInt
ServerProcessEntityNetworkEventQueue
UpdateGravity
SetupPlayerPVS
SortActiveEntityList
timer_think.Start
// let entities think
for( ent = activeEntities.Next(); ent != NULL; ent = ent->activeNode.Next() )
ent->GetPhysics()->UpdateTime( time );
// remove any entities that have stopped thinking
for( ent = activeEntities.Next(); ent != NULL; ent = next_ent )
if ( !ent->thinkFlags )
ent->activeNode.Remove();
timer_think.Stop();
idEvent::ServiceEvents();
idEvent::ServiceFastEvents();
}
}
}
session->UpdateScreen( false ); // normal, in-sequence screen update
{
renderSystem->BeginFrame( renderSystem->GetScreenWidth(), renderSystem->GetScreenHeight() );
// Doesn't actually communicate with the GPU
// but generate Doom cmd for later.
// DOOM3 FRONTEND
- idGame::Draw
- idPlayerView::RenderPlayerView
- idPlayerView::SingleView
- idRenderWorld::RenderScene
| - build params
| - ::R_RenderView(params)
| {
| R_SetViewMatrix //Setup the modelview Matrix (GL_MODELVIEW)
| R_SetupViewFrustum //Setup the perspective projection Matrix (GL_PROJECTION). Set Zfar to MAX_WORLD_SIZE (256*1024), this is adjusted in R_ConstrainViewFrustum
| R_SetupProjection
|
| // Populate:
| // - tr.viewDef->viewLights
| // - tr.viewDef->viewEntitys
| static_cast(parms->renderWorld)->FindViewLightsAndEntities();
| PointInArea
| BuildConnectedAreas //Just follow the graph or portal interconnection in order to mark all area potentially visible (mark tr.viewDef->connectedAreas array)
| FlowViewThroughPortals
| FloodViewThroughArea_r
| {
| AddAreaRefs
| {
| AddAreaEntityRefs( areaNum, ps ); //Use tr.viewDef->connectedAreas. Even if an entity is not in light IT MUST be rendered because
//It may be in front of a lighted area (silhouette effect).
| AddAreaLightRefs( areaNum, ps );
| }
| }
|
| R_ConstrainViewFrustum // Adjust Z Far in order to gain precision (ZFar = MAX_WORLD_SIZE from R_SetupViewFrustum) (constrain the view frustum to the view lights and entities).
|
| // make sure that interactions exist for all light / entity combinations
| // that are visible
| // add any pre-generated light shadows, and calculate the light shader values
| R_AddLightSurfaces();
|
| // adds ambient surfaces and create any necessary interaction surfaces to add to the light
| // lists. Removes lights from the viewLights list if they are completely turned off, or completely off screen.
| R_AddModelSurfaces();
|
| // any viewLight that didn't have visible surfaces can have it's shadows removed
| R_RemoveUnecessaryViewLights();
|
| // sort all the ambient surfaces for translucency ordering using C qsort. Would have been faster to use C++ template for inlining.
| R_SortDrawSurfs();
|
| R_GenerateSubViews // Generate GUI elements on surfaces.
|
| R_AddDrawViewCmd // Send everything to the backend
| }
|
- idPlayer::DrawHUD
// All commands are picked up here and GPU is actually instructed to
// render stuff.
renderSystem->EndFrame
{
R_IssueRenderCommands
RB_ExecuteBackEndCommands
RB_DrawView
RB_ShowOverdraw
RB_STD_DrawView
{
RB_BeginDrawingView // clear the z buffer, set the projection matrix, etc
RB_DetermineLightScale
RB_STD_FillDepthBuffer // fill the depth buffer and clear color buffer to black except on
_DrawInteractions
{
5 GPU specific path
R10 (GeForce256)
R20 (geForce3)
R200 (Radeon 8500)
ARB
ARB2
}
// disable stencil shadow test
qglStencilFunc( GL_ALWAYS, 128, 255 );
RB_STD_LightScale
RB_STD_DrawShaderPasses //draw any non-light dependent shading passes
RB_STD_FogAllLights
RB_STD_DrawShaderPasses
}
}
}
}
}
}