Gate readiness on stable viewport frames
Some checks failed
CI / rust-skia (Rust only) (push) Has been cancelled
CI / required (push) Has been cancelled

This commit is contained in:
2026-08-23 13:48:06 +02:00
parent 33d1cf6827
commit 42f0c62b6b
2 changed files with 43 additions and 34 deletions

View File

@@ -343,6 +343,7 @@ async fn run_live(
{
live.vision.set_generation(status.generation);
record_session_observation(&live.observability, &event);
print_ready(&live, status.generation);
return Ok::<(), CliError>(());
}
Some(
@@ -529,32 +530,7 @@ async fn run_live(
status.agent_ready,
);
if status.agent_ready {
let world = live
.world_loop
.as_ref()
.and_then(metacrate_game_loop::LoopHandle::latest_world);
let world_sequence = world.as_ref().map_or(0, |world| world.sequence);
let primitives = world
.as_ref()
.map_or(0, |world| world.value.primitives.len());
let avatars = world.as_ref().map_or(0, |world| world.value.avatars.len());
let dropped_world_events = live
.world_loop
.as_ref()
.map_or(0, metacrate_game_loop::LoopHandle::dropped_world_events);
let frames = live
.vision
.viewport_stats()
.map_or(0, |stats| stats.completed_frames);
println!(
"READY generation={} world_sequence={} world_primitives={} world_avatars={} dropped_world_events={} viewport_frames={} viewport_target_fps=10",
status.generation,
world_sequence,
primitives,
avatars,
dropped_world_events,
frames
);
print_ready(&live, status.generation);
}
}
}
@@ -689,13 +665,20 @@ async fn prepare_live_framework(
generation,
libremetaverse_types::compat::CancellationToken::default(),
);
let mut stable_after_frame = 0;
let mut observed_missed_deadlines = 0;
loop {
if live
.vision
.viewport_stats()
.is_some_and(|stats| stats.completed_frames >= 2 && stats.render_errors == 0)
{
return;
if let Some(stats) = live.vision.viewport_stats() {
if stats.missed_frame_deadlines != observed_missed_deadlines {
observed_missed_deadlines = stats.missed_frame_deadlines;
stable_after_frame = stats.completed_frames;
}
if stats.completed_frames.saturating_sub(stable_after_frame) >= 2
&& stats.render_errors == 0
&& stats.last_render <= metacrate_game_loop::DEFAULT_VIEWPORT_FRAME_INTERVAL
{
return;
}
}
tokio::time::sleep(Duration::from_millis(20)).await;
}
@@ -705,7 +688,7 @@ async fn prepare_live_framework(
readiness.mark_ready(generation);
let stats = live.vision.viewport_stats().unwrap_or_default();
println!(
"INITIALIZED generation={} viewport_frames={} last_render_ms={} missed_deadlines={} world_state=stable",
"INITIALIZED generation={} viewport_frames={} last_render_ms={} warmup_missed_deadlines={} world_state=stable viewport_state=stable",
generation,
stats.completed_frames,
stats.last_render.as_millis(),
@@ -714,6 +697,30 @@ async fn prepare_live_framework(
Ok(())
}
#[cfg(feature = "live-grid")]
fn print_ready(live: &LiveInteractions, generation: u64) {
let world = live
.world_loop
.as_ref()
.and_then(metacrate_game_loop::LoopHandle::latest_world);
let world_sequence = world.as_ref().map_or(0, |world| world.sequence);
let primitives = world
.as_ref()
.map_or(0, |world| world.value.primitives.len());
let avatars = world.as_ref().map_or(0, |world| world.value.avatars.len());
let dropped_world_events = live
.world_loop
.as_ref()
.map_or(0, metacrate_game_loop::LoopHandle::dropped_world_events);
let frames = live
.vision
.viewport_stats()
.map_or(0, |stats| stats.completed_frames);
println!(
"READY generation={generation} world_sequence={world_sequence} world_primitives={primitives} world_avatars={avatars} dropped_world_events={dropped_world_events} viewport_frames={frames} viewport_target_fps=10"
);
}
#[cfg(feature = "live-grid")]
struct LiveInteractions {
interaction: metacrate_grid_agent::InteractionHandle,

View File

@@ -40,7 +40,9 @@ INITIALIZING generation=N waiting_for=world_state,viewport target_fps=10
The framework gate opens only after the region-scoped world state exists, the
first scene/assets have converged, and at least two complete viewport frames
have been published without render errors. The terminal then emits
have been published after the last missed deadline, within the frame budget,
and without render errors. One-time warm-up misses are reported separately and
do not contaminate the post-`READY` stability window. The terminal then emits
`INITIALIZED ...` followed by one unambiguous `READY ...` line when the session
and agent services are released. The default readiness allowance is two
minutes; the measured scene convergence window was about 30.05 seconds.