Repository: godotengine/godot
File: main/main.cpp (C++)

Code before:
		ERR_FAIL_COND(!_start_success);
	}

#ifdef DEBUG_ENABLED
	if (input) {
		input->flush_frame_parsed_events();
	}
#endif

	for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
		TextServerManager::get_singleton()->get_interface(i)->cleanup();
	}

	if (movie_writer) {
		movie_writer->end();
	}

	ResourceLoader::clear_thread_load_tasks();

	ResourceLoader::remove_custom_loaders();
	ResourceSaver::remove_custom_savers();
	PropertyListHelper::clear_base_helpers();

	// Flush before uninitializing the scene, but delete the MessageQueue as late as possible.
	message_queue->flush();

	OS::get_singleton()->delete_main_loop();

	OS::get_singleton()->_cmdline.clear();
	OS::get_singleton()->_user_args.clear();
	OS::get_singleton()->_execpath = "";
	OS::get_singleton()->_local_clipboard = "";

	ResourceLoader::clear_translation_remaps();
	ResourceLoader::clear_path_remaps();

	WorkerThreadPool::get_singleton()->exit_languages_threads();

	ScriptServer::finish_languages();

	// Sync pending commands that may have been queued from a different thread during ScriptServer finalization
	RenderingServer::get_singleton()->sync();

	//clear global shader variables before scene and other graphics stuff are deinitialized.
	rendering_server->global_shader_parameters_clear();

#ifndef XR_DISABLED
	if (xr_server) {
		// Now that we're unregistering properly in plugins we need to keep access to xr_server for a little longer
		// We do however unset our primary interface
		xr_server->set_primary_interface(Ref<XRInterface>());

Review comment (suggestion):
Can't add this to the right place, but adding this will be useful to see how much time the main iteration sleeps:

```
	GodotProfileZoneGrouped(_profile_zone, "OS::add_frame_delay");
	OS::get_singleton()->add_frame_delay(DisplayServer::get_singleton()->window_can_draw());

```

Code after:
			} else if (print_fps || GLOBAL_GET("debug/settings/stdout/print_fps")) {
				print_line(vformat("Project FPS: %d (%s mspf)", frames, rtos(1000.0 / frames).pad_decimals(2)));
			}
		} else {
			hide_print_fps_attempts--;
		}

		Engine::get_singleton()->_fps = frames;
		performance->set_process_time(USEC_TO_SEC(process_max));
		performance->set_physics_process_time(USEC_TO_SEC(physics_process_max));
		performance->set_navigation_process_time(USEC_TO_SEC(navigation_process_max));
		process_max = 0;
		physics_process_max = 0;
		navigation_process_max = 0;

		frame %= 1000000;
		frames = 0;
	}

	iterating--;

	if (movie_writer) {
		GodotProfileZoneGrouped(_profile_zone, "movie_writer->add_frame");
		movie_writer->add_frame();
	}

#ifdef TOOLS_ENABLED
	bool quit_after_timeout = false;
#endif
	if ((quit_after > 0) && (Engine::get_singleton()->_process_frames >= quit_after)) {
#ifdef TOOLS_ENABLED
		quit_after_timeout = true;
#endif
		exit = true;
	}

#ifdef TOOLS_ENABLED
	if (wait_for_import && EditorFileSystem::get_singleton() && EditorFileSystem::get_singleton()->doing_first_scan()) {
		exit = false;
	}
#endif

	if (fixed_fps != -1) {
		return exit;
	}

	SceneTree *scene_tree = SceneTree::get_singleton();
	bool wake_for_events = scene_tree && scene_tree->is_accessibility_enabled();

	GodotProfileZoneGrouped(_profile_zone, "OS::add_frame_delay");
	OS::get_singleton()->add_frame_delay(DisplayServer::get_singleton()->window_can_draw(), wake_for_events);