void CPhysicsSystem::PhysicsSimulate() { VPROF_BUDGET( "CPhysicsSystem::PhysicsSimulate", VPROF_BUDGETGROUP_PHYSICS ); float frametime = gpGlobals->frametime; if ( physenv ) { tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s %d", __FUNCTION__, physenv->GetActiveObjectCount() ); g_Collisions.BufferTouchEvents( true ); #ifdef _DEBUG physenv->DebugCheckContacts(); #endif physenv->Simulate( frametime * cl_phys_timescale.GetFloat() ); int activeCount = physenv->GetActiveObjectCount(); IPhysicsObject **pActiveList = NULL; if ( activeCount ) { pActiveList = (IPhysicsObject **)stackalloc( sizeof(IPhysicsObject *)*activeCount ); physenv->GetActiveObjects( pActiveList ); for ( int i = 0; i < activeCount; i++ ) { C_BaseEntity *pEntity = reinterpret_cast<C_BaseEntity *>(pActiveList[i]->GetGameData()); if ( pEntity ) { if ( pEntity->CollisionProp()->DoesVPhysicsInvalidateSurroundingBox() ) { pEntity->CollisionProp()->MarkSurroundingBoundsDirty(); } pEntity->VPhysicsUpdate( pActiveList[i] ); } } } g_Collisions.BufferTouchEvents( false ); g_Collisions.FrameUpdate(); } physicssound::PlayImpactSounds( m_impactSounds ); }
//----------------------------------------------------------------------------- // Purpose: Render current view into specified rectangle // Input : *rect - is computed by CVideoMode_Common::GetClientViewRect() //----------------------------------------------------------------------------- void CViewRender::Render( vrect_t *rect ) { Assert(s_DbgSetupOrigin == m_View.origin); Assert(s_DbgSetupAngles == m_View.angles); VPROF_BUDGET( "CViewRender::Render", "CViewRender::Render" ); tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ ); vrect_t vr = *rect; // Stub out the material system if necessary. CMatStubHandler matStub; engine->EngineStats_BeginFrame(); // Assume normal vis m_bForceNoVis = false; C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); // Set for console commands, etc. render->SetMainView ( m_View.origin, m_View.angles ); for( StereoEye_t eEye = GetFirstEye(); eEye <= GetLastEye(); eEye = (StereoEye_t)(eEye+1) ) { CViewSetup &view = GetView( eEye ); #if 0 && defined( CSTRIKE_DLL ) const bool bPlayingBackReplay = g_pEngineClientReplay && g_pEngineClientReplay->IsPlayingReplayDemo(); if ( pPlayer && !bPlayingBackReplay ) { C_BasePlayer *pViewTarget = pPlayer; if ( pPlayer->IsObserver() && pPlayer->GetObserverMode() == OBS_MODE_IN_EYE ) { pViewTarget = dynamic_cast<C_BasePlayer*>( pPlayer->GetObserverTarget() ); } if ( pViewTarget ) { float targetFOV = (float)pViewTarget->m_iFOV; if ( targetFOV == 0 ) { // FOV of 0 means use the default FOV targetFOV = g_pGameRules->DefaultFOV(); } float deltaFOV = view.fov - m_flLastFOV; float FOVDirection = targetFOV - pViewTarget->m_iFOVStart; // Clamp FOV changes to stop FOV oscillation if ( ( deltaFOV < 0.0f && FOVDirection > 0.0f ) || ( deltaFOV > 0.0f && FOVDirection < 0.0f ) ) { view.fov = m_flLastFOV; } // Catch case where FOV overshoots its target FOV if ( ( view.fov < targetFOV && FOVDirection <= 0.0f ) || ( view.fov > targetFOV && FOVDirection >= 0.0f ) ) { view.fov = targetFOV; } m_flLastFOV = view.fov; } } #endif static ConVarRef sv_restrict_aspect_ratio_fov( "sv_restrict_aspect_ratio_fov" ); float aspectRatio = engine->GetScreenAspectRatio() * 0.75f; // / (4/3) float limitedAspectRatio = aspectRatio; if ( ( sv_restrict_aspect_ratio_fov.GetInt() > 0 && engine->IsWindowedMode() && gpGlobals->maxClients > 1 ) || sv_restrict_aspect_ratio_fov.GetInt() == 2 ) { limitedAspectRatio = MIN( aspectRatio, 1.85f * 0.75f ); // cap out the FOV advantage at a 1.85:1 ratio (about the widest any legit user should be) } view.fov = ScaleFOVByWidthRatio( view.fov, limitedAspectRatio ); view.fovViewmodel = ScaleFOVByWidthRatio( view.fovViewmodel, aspectRatio ); // Let the client mode hook stuff. g_pClientMode->PreRender(&view); g_pClientMode->AdjustEngineViewport( vr.x, vr.y, vr.width, vr.height ); ToolFramework_AdjustEngineViewport( vr.x, vr.y, vr.width, vr.height ); float flViewportScale = mat_viewportscale.GetFloat(); view.m_nUnscaledX = vr.x; view.m_nUnscaledY = vr.y; view.m_nUnscaledWidth = vr.width; view.m_nUnscaledHeight = vr.height; switch( eEye ) { case STEREO_EYE_MONO: { #if 0 // Good test mode for debugging viewports that are not full-size. view.width = vr.width * flViewportScale * 0.75f; view.height = vr.height * flViewportScale * 0.75f; view.x = vr.x + view.width * 0.10f; view.y = vr.y + view.height * 0.20f; #else view.x = vr.x * flViewportScale; view.y = vr.y * flViewportScale; view.width = vr.width * flViewportScale; view.height = vr.height * flViewportScale; #endif float engineAspectRatio = engine->GetScreenAspectRatio(); view.m_flAspectRatio = ( engineAspectRatio > 0.0f ) ? engineAspectRatio : ( (float)view.width / (float)view.height ); } break; case STEREO_EYE_RIGHT: case STEREO_EYE_LEFT: { g_pSourceVR->GetViewportBounds( (ISourceVirtualReality::VREye)(eEye - 1 ), &view.x, &view.y, &view.width, &view.height ); view.m_nUnscaledWidth = view.width; view.m_nUnscaledHeight = view.height; view.m_nUnscaledX = view.x; view.m_nUnscaledY = view.y; } break; default: Assert ( false ); break; } // if we still don't have an aspect ratio, compute it from the view size if( view.m_flAspectRatio <= 0.f ) view.m_flAspectRatio = (float)view.width / (float)view.height; int nClearFlags = VIEW_CLEAR_DEPTH | VIEW_CLEAR_STENCIL; if( gl_clear_randomcolor.GetBool() ) { CMatRenderContextPtr pRenderContext( materials ); pRenderContext->ClearColor3ub( rand()%256, rand()%256, rand()%256 ); pRenderContext->ClearBuffers( true, false, false ); pRenderContext->Release(); } else if ( gl_clear.GetBool() ) { nClearFlags |= VIEW_CLEAR_COLOR; } else if ( IsPosix() ) { MaterialAdapterInfo_t adapterInfo; materials->GetDisplayAdapterInfo( materials->GetCurrentAdapter(), adapterInfo ); // On Posix, on ATI, we always clear color if we're antialiasing if ( adapterInfo.m_VendorID == 0x1002 ) { if ( g_pMaterialSystem->GetCurrentConfigForVideoCard().m_nAASamples > 0 ) { nClearFlags |= VIEW_CLEAR_COLOR; } } } // Determine if we should draw view model ( client mode override ) bool drawViewModel = g_pClientMode->ShouldDrawViewModel(); if ( cl_leveloverview.GetFloat() > 0 ) { SetUpOverView(); nClearFlags |= VIEW_CLEAR_COLOR; drawViewModel = false; } // Apply any player specific overrides if ( pPlayer ) { // Override view model if necessary if ( !pPlayer->m_Local.m_bDrawViewmodel ) { drawViewModel = false; } } int flags = 0; if( eEye == STEREO_EYE_MONO || eEye == STEREO_EYE_LEFT || ( g_ClientVirtualReality.ShouldRenderHUDInWorld() ) ) { flags = RENDERVIEW_DRAWHUD; } if ( drawViewModel ) { flags |= RENDERVIEW_DRAWVIEWMODEL; } if( eEye == STEREO_EYE_RIGHT ) { // we should use the monitor view from the left eye for both eyes flags |= RENDERVIEW_SUPPRESSMONITORRENDERING; } RenderView( view, nClearFlags, flags ); if ( UseVR() ) { bool bDoUndistort = ! engine->IsTakingScreenshot(); if ( bDoUndistort ) { g_ClientVirtualReality.PostProcessFrame( eEye ); } // logic here all cloned from code in viewrender.cpp around RenderHUDQuad: // figure out if we really want to draw the HUD based on freeze cam bool bInFreezeCam = ( pPlayer && pPlayer->GetObserverMode() == OBS_MODE_FREEZECAM ); // draw the HUD after the view model so its "I'm closer" depth queues work right. if( !bInFreezeCam && g_ClientVirtualReality.ShouldRenderHUDInWorld() ) { // TODO - a bit of a shonky test - basically trying to catch the main menu, the briefing screen, the loadout screen, etc. bool bTranslucent = !g_pMatSystemSurface->IsCursorVisible(); g_ClientVirtualReality.OverlayHUDQuadWithUndistort( view, bDoUndistort, g_pClientMode->ShouldBlackoutAroundHUD(), bTranslucent ); } } } // TODO: should these be inside or outside the stereo eye stuff? g_pClientMode->PostRender(); engine->EngineStats_EndFrame(); #if !defined( _X360 ) // Stop stubbing the material system so we can see the budget panel matStub.End(); #endif // Draw all of the UI stuff "fullscreen" // (this is not health, ammo, etc. Nor is it pre-game briefing interface stuff - this is the stuff that appears when you hit Esc in-game) // In stereo mode this is rendered inside of RenderView so it goes into the render target if( !g_ClientVirtualReality.ShouldRenderHUDInWorld() ) { CViewSetup view2d; view2d.x = rect->x; view2d.y = rect->y; view2d.width = rect->width; view2d.height = rect->height; render->Push2DView( view2d, 0, NULL, GetFrustum() ); render->VGui_Paint( PAINT_UIPANELS | PAINT_CURSOR ); render->PopView( GetFrustum() ); } }
void PixelVisibility_EndScene() { tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ ); g_PixelVisibilitySystem.EndScene(); }
//---------------------------------------------------------------------------------------------------------------------- // tool_replay_mode //---------------------------------------------------------------------------------------------------------------------- static bool tool_replay_mode() { VOGL_FUNC_TRACER dynamic_string trace_filename(g_command_line_params().get_value_as_string_or_empty("", 1)); if (trace_filename.is_empty()) { vogl_error_printf("No trace file specified!\n"); return false; } dynamic_string actual_trace_filename; vogl_unique_ptr<vogl_trace_file_reader> pTrace_reader( vogl_open_trace_file( trace_filename, actual_trace_filename, g_command_line_params().get_value_as_string_or_empty("loose_file_path").get_ptr() ) ); if (!pTrace_reader.get()) { vogl_error_printf("File not found, or unable to determine file type of trace file \"%s\"\n", trace_filename.get_ptr()); return false; } vogl_printf("Reading trace file %s\n", actual_trace_filename.get_ptr()); vogl_gl_replayer replayer; vogl_replay_window window; #if defined(PLATFORM_WINDOWS) // We need to get proc addresses for windows late. replayer.set_proc_address_helper(vogl_get_proc_address_helper, false); #endif uint replayer_flags = get_replayer_flags_from_command_line_params(); // TODO: This will create a window with default attributes, which seems fine for the majority of traces. // Unfortunately, some GL call streams *don't* want an alpha channel, or depth, or stencil etc. in the default framebuffer so this may become a problem. // Also, this design only supports a single window, which is going to be a problem with multiple window traces. if (!window.open(g_command_line_params().get_value_as_int("width", 0, 1024, 1, 65535), g_command_line_params().get_value_as_int("height", 0, 768, 1, 65535), g_command_line_params().get_value_as_int("msaa", 0, 0, 0, 65535))) { vogl_error_printf("Failed initializing replay window\n"); return false; } if (!replayer.init(replayer_flags, &window, pTrace_reader->get_sof_packet(), pTrace_reader->get_multi_blob_manager())) { vogl_error_printf("Failed initializing GL replayer\n"); return false; } // Disable all glGetError() calls in vogl_utils.cpp. vogl_disable_gl_get_error(); // Bool win_mapped = false; vogl_gl_state_snapshot *pSnapshot = NULL; int64_t snapshot_loop_start_frame = -1; int64_t snapshot_loop_end_frame = -1; vogl::hash_map<SDL_Keycode> keys_pressed, keys_down; int loop_frame = g_command_line_params().get_value_as_int("loop_frame", 0, -1); int loop_len = math::maximum<int>(g_command_line_params().get_value_as_int("loop_len", 0, 1), 1); int loop_count = math::maximum<int>(g_command_line_params().get_value_as_int("loop_count", 0, cINT32_MAX), 1); bool endless_mode = g_command_line_params().get_value_as_bool("endless"); timer tm; tm.start(); for (;;) { tmZone(TELEMETRY_LEVEL0, TMZF_NONE, "Main Loop"); SDL_Event wnd_event; while (SDL_PollEvent(&wnd_event)) { switch (wnd_event.type) { case SDL_KEYDOWN: { keys_down.insert(wnd_event.key.keysym.sym); keys_pressed.insert(wnd_event.key.keysym.sym); break; } case SDL_KEYUP: { keys_down.erase(wnd_event.key.keysym.sym); break; } case SDL_WINDOWEVENT: { switch(wnd_event.window.event) { case SDL_WINDOWEVENT_FOCUS_GAINED: case SDL_WINDOWEVENT_FOCUS_LOST: keys_down.reset(); break; case SDL_WINDOWEVENT_CLOSE: vogl_message_printf("Window told to close, exiting.\n"); goto normal_exit; break; default: break; }; break; } default: // TODO: Handle these somehow? break; }; } if (replayer.get_at_frame_boundary()) { if ((!pSnapshot) && (loop_frame != -1) && (static_cast<int64_t>(replayer.get_frame_index()) == loop_frame)) { vogl_debug_printf("Capturing replayer state at start of frame %u\n", replayer.get_frame_index()); pSnapshot = replayer.snapshot_state(); if (pSnapshot) { vogl_printf("Snapshot succeeded\n"); snapshot_loop_start_frame = pTrace_reader->get_cur_frame(); snapshot_loop_end_frame = pTrace_reader->get_cur_frame() + loop_len; vogl_debug_printf("Loop start: %" PRIi64 " Loop end: %" PRIi64 "\n", snapshot_loop_start_frame, snapshot_loop_end_frame); } else { vogl_error_printf("Snapshot failed!\n"); loop_frame = -1; } } } vogl_gl_replayer::status_t status = replayer.process_pending_window_resize(); if (status == vogl_gl_replayer::cStatusOK) { for (;;) { status = replayer.process_pending_packets(); if (status == vogl_gl_replayer::cStatusOK) { status = replayer.process_next_packet(*pTrace_reader); } if ((status == vogl_gl_replayer::cStatusNextFrame) || (status == vogl_gl_replayer::cStatusResizeWindow) || (status == vogl_gl_replayer::cStatusAtEOF) || (status == vogl_gl_replayer::cStatusHardFailure)) { break; } } } if (status == vogl_gl_replayer::cStatusHardFailure) break; if (status == vogl_gl_replayer::cStatusAtEOF) { vogl_message_printf("At trace EOF, frame index %u\n", replayer.get_frame_index()); } if (replayer.get_at_frame_boundary() && pSnapshot && (loop_count > 0) && ((pTrace_reader->get_cur_frame() == snapshot_loop_end_frame) || (status == vogl_gl_replayer::cStatusAtEOF))) { status = replayer.begin_applying_snapshot(pSnapshot, false); if ((status != vogl_gl_replayer::cStatusOK) && (status != vogl_gl_replayer::cStatusResizeWindow)) goto error_exit; pTrace_reader->seek_to_frame(static_cast<uint>(snapshot_loop_start_frame)); vogl_debug_printf("Applying snapshot and seeking back to frame %" PRIi64 "\n", snapshot_loop_start_frame); loop_count--; } else { bool print_progress = (status == vogl_gl_replayer::cStatusAtEOF) || ((replayer.get_at_frame_boundary()) && ((replayer.get_frame_index() % 100) == 0)); if (print_progress) { if (pTrace_reader->get_type() == cBINARY_TRACE_FILE_READER) { vogl_binary_trace_file_reader &binary_trace_reader = *static_cast<vogl_binary_trace_file_reader *>(pTrace_reader.get()); vogl_printf("Replay now at frame index %u, trace file offet %" PRIu64 ", GL call counter %" PRIu64 ", %3.2f%% percent complete\n", replayer.get_frame_index(), binary_trace_reader.get_cur_file_ofs(), replayer.get_last_parsed_call_counter(), binary_trace_reader.get_trace_file_size() ? (binary_trace_reader.get_cur_file_ofs() * 100.0f) / binary_trace_reader.get_trace_file_size() : 0); } } if (status == vogl_gl_replayer::cStatusAtEOF) { if (!endless_mode) { double time_since_start = tm.get_elapsed_secs(); vogl_printf("%u total swaps, %.3f secs, %3.3f avg fps\n", replayer.get_total_swaps(), time_since_start, replayer.get_frame_index() / time_since_start); break; } vogl_printf("Resetting state and rewinding back to frame 0\n"); replayer.reset_state(); if (!pTrace_reader->seek_to_frame(0)) { vogl_error_printf("Failed rewinding trace reader!\n"); goto error_exit; } } } telemetry_tick(); } normal_exit: return true; error_exit: return false; }
//---------------------------------------------------------------------------------------------------------------------- // tool_replay_mode //---------------------------------------------------------------------------------------------------------------------- static bool tool_replay_mode() { VOGL_FUNC_TRACER dynamic_string trace_filename(g_command_line_params().get_value_as_string_or_empty("", 1)); if (trace_filename.is_empty()) { vogl_error_printf("%s: No trace file specified!\n", VOGL_FUNCTION_INFO_CSTR); return false; } dynamic_string actual_trace_filename; vogl_unique_ptr<vogl_trace_file_reader> pTrace_reader(vogl_open_trace_file( trace_filename, actual_trace_filename, g_command_line_params().get_value_as_string_or_empty("loose_file_path").get_ptr())); if (!pTrace_reader.get()) { vogl_error_printf("%s: File not found, or unable to determine file type of trace file \"%s\"\n", VOGL_FUNCTION_INFO_CSTR, trace_filename.get_ptr()); return false; } vogl_printf("Reading trace file %s\n", actual_trace_filename.get_ptr()); vogl_gl_replayer replayer; vogl_replay_window window; uint replayer_flags = get_replayer_flags_from_command_line_params(); // TODO: This will create a window with default attributes, which seems fine for the majority of traces. // Unfortunately, some GL call streams *don't* want an alpha channel, or depth, or stencil etc. in the default framebuffer so this may become a problem. // Also, this design only supports a single window, which is going to be a problem with multiple window traces. if (!window.open(g_command_line_params().get_value_as_int("width", 0, 1024, 1, 65535), g_command_line_params().get_value_as_int("height", 0, 768, 1, 65535), g_command_line_params().get_value_as_int("msaa", 0, 0, 0, 65535))) { vogl_error_printf("%s: Failed initializing replay window\n", VOGL_FUNCTION_INFO_CSTR); return false; } if (!replayer.init(replayer_flags, &window, pTrace_reader->get_sof_packet(), pTrace_reader->get_multi_blob_manager())) { vogl_error_printf("%s: Failed initializing GL replayer\n", VOGL_FUNCTION_INFO_CSTR); return false; } // Disable all glGetError() calls in vogl_utils.cpp. vogl_disable_gl_get_error(); XSelectInput(window.get_display(), window.get_xwindow(), EnterWindowMask | LeaveWindowMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ExposureMask | FocusChangeMask | KeyPressMask | KeyReleaseMask | PropertyChangeMask | StructureNotifyMask | KeymapStateMask); Atom wmDeleteMessage = XInternAtom(window.get_display(), "WM_DELETE_WINDOW", False); XSetWMProtocols(window.get_display(), window.get_xwindow(), &wmDeleteMessage, 1); // Bool win_mapped = false; vogl_gl_state_snapshot *pSnapshot = NULL; int64_t snapshot_loop_start_frame = -1; int64_t snapshot_loop_end_frame = -1; vogl::hash_map<uint64_t> keys_pressed, keys_down; int loop_frame = g_command_line_params().get_value_as_int("loop_frame", 0, -1); int loop_len = math::maximum<int>(g_command_line_params().get_value_as_int("loop_len", 0, 1), 1); int loop_count = math::maximum<int>(g_command_line_params().get_value_as_int("loop_count", 0, cINT32_MAX), 1); bool endless_mode = g_command_line_params().get_value_as_bool("endless"); timer tm; tm.start(); for (;;) { tmZone(TELEMETRY_LEVEL0, TMZF_NONE, "Main Loop"); while (X11_Pending(window.get_display())) { XEvent newEvent; // Watch for new X eventsn XNextEvent(window.get_display(), &newEvent); switch (newEvent.type) { case KeyPress: { KeySym xsym = XLookupKeysym(&newEvent.xkey, 0); //printf("KeyPress 0%04llX %" PRIu64 "\n", (uint64_t)xsym, (uint64_t)xsym); keys_down.insert(xsym); keys_pressed.insert(xsym); break; } case KeyRelease: { KeySym xsym = XLookupKeysym(&newEvent.xkey, 0); //printf("KeyRelease 0x%04llX %" PRIu64 "\n", (uint64_t)xsym, (uint64_t)xsym); keys_down.erase(xsym); break; } case FocusIn: case FocusOut: { //printf("FocusIn/FocusOut\n"); keys_down.reset(); break; } case MappingNotify: { //XRefreshKeyboardMapping(&newEvent); break; } case UnmapNotify: { // printf("UnmapNotify\n"); // win_mapped = false; keys_down.reset(); break; } case MapNotify: { // printf("MapNotify\n"); // win_mapped = true; keys_down.reset(); if (!replayer.update_window_dimensions()) goto error_exit; break; } case ConfigureNotify: { if (!replayer.update_window_dimensions()) goto error_exit; break; } case DestroyNotify: { vogl_message_printf("Exiting\n"); goto normal_exit; } case ClientMessage: { if (newEvent.xclient.data.l[0] == (int)wmDeleteMessage) { vogl_message_printf("Exiting\n"); goto normal_exit; } break; } default: break; } } if (replayer.get_at_frame_boundary()) { if ((!pSnapshot) && (loop_frame != -1) && (static_cast<int64_t>(replayer.get_frame_index()) == loop_frame)) { vogl_debug_printf("%s: Capturing replayer state at start of frame %u\n", VOGL_FUNCTION_INFO_CSTR, replayer.get_frame_index()); pSnapshot = replayer.snapshot_state(); if (pSnapshot) { vogl_printf("Snapshot succeeded\n"); snapshot_loop_start_frame = pTrace_reader->get_cur_frame(); snapshot_loop_end_frame = pTrace_reader->get_cur_frame() + loop_len; vogl_debug_printf("%s: Loop start: %" PRIi64 " Loop end: %" PRIi64 "\n", VOGL_FUNCTION_INFO_CSTR, snapshot_loop_start_frame, snapshot_loop_end_frame); } else { vogl_error_printf("Snapshot failed!\n"); loop_frame = -1; } } } vogl_gl_replayer::status_t status = replayer.process_pending_window_resize(); if (status == vogl_gl_replayer::cStatusOK) { for (;;) { status = replayer.process_next_packet(*pTrace_reader); if ((status == vogl_gl_replayer::cStatusNextFrame) || (status == vogl_gl_replayer::cStatusResizeWindow) || (status == vogl_gl_replayer::cStatusAtEOF) || (status == vogl_gl_replayer::cStatusHardFailure)) { break; } } } if (status == vogl_gl_replayer::cStatusHardFailure) break; if (status == vogl_gl_replayer::cStatusAtEOF) { vogl_message_printf("%s: At trace EOF, frame index %u\n", VOGL_FUNCTION_INFO_CSTR, replayer.get_frame_index()); } if (replayer.get_at_frame_boundary() && pSnapshot && (loop_count > 0) && ((pTrace_reader->get_cur_frame() == snapshot_loop_end_frame) || (status == vogl_gl_replayer::cStatusAtEOF))) { status = replayer.begin_applying_snapshot(pSnapshot, false); if ((status != vogl_gl_replayer::cStatusOK) && (status != vogl_gl_replayer::cStatusResizeWindow)) goto error_exit; pTrace_reader->seek_to_frame(static_cast<uint>(snapshot_loop_start_frame)); vogl_debug_printf("%s: Applying snapshot and seeking back to frame %" PRIi64 "\n", VOGL_FUNCTION_INFO_CSTR, snapshot_loop_start_frame); loop_count--; } else { bool print_progress = (status == vogl_gl_replayer::cStatusAtEOF) || ((replayer.get_at_frame_boundary()) && ((replayer.get_frame_index() % 100) == 0)); if (print_progress) { if (pTrace_reader->get_type() == cBINARY_TRACE_FILE_READER) { vogl_binary_trace_file_reader &binary_trace_reader = *static_cast<vogl_binary_trace_file_reader *>(pTrace_reader.get()); vogl_printf("Replay now at frame index %u, trace file offet %" PRIu64 ", GL call counter %" PRIu64 ", %3.2f%% percent complete\n", replayer.get_frame_index(), binary_trace_reader.get_cur_file_ofs(), replayer.get_last_parsed_call_counter(), binary_trace_reader.get_trace_file_size() ? (binary_trace_reader.get_cur_file_ofs() * 100.0f) / binary_trace_reader.get_trace_file_size() : 0); } } if (status == vogl_gl_replayer::cStatusAtEOF) { if (!endless_mode) { double time_since_start = tm.get_elapsed_secs(); vogl_printf("%u total swaps, %.3f secs, %3.3f avg fps\n", replayer.get_total_swaps(), time_since_start, replayer.get_frame_index() / time_since_start); break; } vogl_printf("Resetting state and rewinding back to frame 0\n"); replayer.reset_state(); if (!pTrace_reader->seek_to_frame(0)) { vogl_error_printf("%s: Failed rewinding trace reader!\n", VOGL_FUNCTION_INFO_CSTR); goto error_exit; } } } telemetry_tick(); } normal_exit: return true; error_exit: return false; }