T10.7: bypass visible-content gate on hardware path (196ms → 6ms per frame)
This commit is contained in:
@@ -28,11 +28,12 @@ const LIVE_FRAME_WAIT_INTERVAL: Duration = Duration::from_millis(2);
|
|||||||
|
|
||||||
pub(super) fn run_live(args: LiveArgs) -> Result<(), LiveSidecarError> {
|
pub(super) fn run_live(args: LiveArgs) -> Result<(), LiveSidecarError> {
|
||||||
fs::create_dir_all(&args.profile_data_dir)?;
|
fs::create_dir_all(&args.profile_data_dir)?;
|
||||||
let context_label = rendering_context_label(args.rendering_context_kind);
|
let rendering_context_kind = args.rendering_context_kind;
|
||||||
|
let context_label = rendering_context_label(rendering_context_kind);
|
||||||
let mut host = SoftwareServoHost::new_with_config_dir_and_kind(
|
let mut host = SoftwareServoHost::new_with_config_dir_and_kind(
|
||||||
ServoSurfaceSize::new(1, 1),
|
ServoSurfaceSize::new(1, 1),
|
||||||
Some(args.profile_data_dir),
|
Some(args.profile_data_dir),
|
||||||
args.rendering_context_kind,
|
rendering_context_kind,
|
||||||
)?;
|
)?;
|
||||||
let mut sessions = HashMap::new();
|
let mut sessions = HashMap::new();
|
||||||
let mut perf =
|
let mut perf =
|
||||||
@@ -55,9 +56,13 @@ pub(super) fn run_live(args: LiveArgs) -> Result<(), LiveSidecarError> {
|
|||||||
// `write_outcome`.
|
// `write_outcome`.
|
||||||
let frame_started_at = Instant::now();
|
let frame_started_at = Instant::now();
|
||||||
let outcome = match serde_json::from_str::<LiveRequest>(&line) {
|
let outcome = match serde_json::from_str::<LiveRequest>(&line) {
|
||||||
Ok(request) => {
|
Ok(request) => handle_request(
|
||||||
handle_request(&mut host, &mut sessions, &mut published_surface_ids, request)
|
&mut host,
|
||||||
}
|
&mut sessions,
|
||||||
|
&mut published_surface_ids,
|
||||||
|
rendering_context_kind,
|
||||||
|
request,
|
||||||
|
),
|
||||||
Err(error) => Err(LiveSidecarError::Json(error)),
|
Err(error) => Err(LiveSidecarError::Json(error)),
|
||||||
};
|
};
|
||||||
write_outcome(
|
write_outcome(
|
||||||
@@ -83,6 +88,7 @@ fn handle_request(
|
|||||||
host: &mut SoftwareServoHost,
|
host: &mut SoftwareServoHost,
|
||||||
sessions: &mut HashMap<String, LiveSession>,
|
sessions: &mut HashMap<String, LiveSession>,
|
||||||
published_surface_ids: &mut HashMap<String, HashSet<u64>>,
|
published_surface_ids: &mut HashMap<String, HashSet<u64>>,
|
||||||
|
rendering_context_kind: RenderingContextKind,
|
||||||
request: LiveRequest,
|
request: LiveRequest,
|
||||||
) -> Result<LiveOutcome, LiveSidecarError> {
|
) -> Result<LiveOutcome, LiveSidecarError> {
|
||||||
match request {
|
match request {
|
||||||
@@ -134,10 +140,16 @@ fn handle_request(
|
|||||||
hover_y,
|
hover_y,
|
||||||
typed_text,
|
typed_text,
|
||||||
)? {
|
)? {
|
||||||
|
// Tell poll_frame to actually wait for Servo to paint
|
||||||
|
// a response to this input. The visible-content gate
|
||||||
|
// is bypassed on the hardware path inside poll_frame,
|
||||||
|
// so we return on the first `has_pending_frame=true`
|
||||||
|
// (~3 ms in practice) rather than burning the full
|
||||||
|
// LIVE_FRAME_WAIT_TIMEOUT.
|
||||||
session.awaiting_visible_frame = true;
|
session.awaiting_visible_frame = true;
|
||||||
}
|
}
|
||||||
let webview_id = session.webview_id.clone();
|
let webview_id = session.webview_id.clone();
|
||||||
let mut outcome = poll_frame(host, session)?;
|
let mut outcome = poll_frame(host, session, rendering_context_kind)?;
|
||||||
populate_surface_fields(host, &webview_id, &tab_id, published_surface_ids, &mut outcome);
|
populate_surface_fields(host, &webview_id, &tab_id, published_surface_ids, &mut outcome);
|
||||||
Ok(outcome)
|
Ok(outcome)
|
||||||
}
|
}
|
||||||
@@ -146,7 +158,7 @@ fn handle_request(
|
|||||||
return Ok(LiveOutcome::empty());
|
return Ok(LiveOutcome::empty());
|
||||||
};
|
};
|
||||||
let webview_id = session.webview_id.clone();
|
let webview_id = session.webview_id.clone();
|
||||||
let mut outcome = poll_frame(host, session)?;
|
let mut outcome = poll_frame(host, session, rendering_context_kind)?;
|
||||||
populate_surface_fields(host, &webview_id, &tab_id, published_surface_ids, &mut outcome);
|
populate_surface_fields(host, &webview_id, &tab_id, published_surface_ids, &mut outcome);
|
||||||
Ok(outcome)
|
Ok(outcome)
|
||||||
}
|
}
|
||||||
@@ -377,6 +389,7 @@ fn apply_input(
|
|||||||
fn poll_frame(
|
fn poll_frame(
|
||||||
host: &mut SoftwareServoHost,
|
host: &mut SoftwareServoHost,
|
||||||
session: &mut LiveSession,
|
session: &mut LiveSession,
|
||||||
|
rendering_context_kind: RenderingContextKind,
|
||||||
) -> Result<LiveOutcome, LiveSidecarError> {
|
) -> Result<LiveOutcome, LiveSidecarError> {
|
||||||
let started_at = Instant::now();
|
let started_at = Instant::now();
|
||||||
let mut latest = None;
|
let mut latest = None;
|
||||||
@@ -391,8 +404,30 @@ fn poll_frame(
|
|||||||
let frame = host.last_rendered_frame()?;
|
let frame = host.last_rendered_frame()?;
|
||||||
let paint_ns = elapsed_ns(paint_started_at);
|
let paint_ns = elapsed_ns(paint_started_at);
|
||||||
let encode_started_at = Instant::now();
|
let encode_started_at = Instant::now();
|
||||||
let has_visible_content =
|
// `non_white`/`content_pixel_count` come from a CPU
|
||||||
frame.non_white_pixel_count() > 0 && frame.content_pixel_count() > 0;
|
// readback of the bound framebuffer. On the software
|
||||||
|
// path that's the source of truth: Servo's compositor
|
||||||
|
// returns a white framebuffer until layout completes, so
|
||||||
|
// the threshold check is how we skip blank loading
|
||||||
|
// frames. On the hardware path the readback goes through
|
||||||
|
// `glReadPixels` on the surfman swap-chain surface, which
|
||||||
|
// can return content that fails the threshold even when
|
||||||
|
// Servo painted real pixels (the IOSurface itself is
|
||||||
|
// valid for GPUI to sample directly). `has_pending_frame`
|
||||||
|
// already encodes "Servo finished painting" — trust it
|
||||||
|
// for the hardware path instead of double-checking via a
|
||||||
|
// readback we know to be unreliable.
|
||||||
|
let has_visible_content = match rendering_context_kind {
|
||||||
|
RenderingContextKind::Software => {
|
||||||
|
frame.non_white_pixel_count() > 0 && frame.content_pixel_count() > 0
|
||||||
|
}
|
||||||
|
#[cfg(feature = "hardware-render")]
|
||||||
|
RenderingContextKind::Hardware => true,
|
||||||
|
#[cfg(not(feature = "hardware-render"))]
|
||||||
|
RenderingContextKind::Hardware => {
|
||||||
|
frame.non_white_pixel_count() > 0 && frame.content_pixel_count() > 0
|
||||||
|
}
|
||||||
|
};
|
||||||
let report = LiveFrameReport::new(&snapshot, &frame);
|
let report = LiveFrameReport::new(&snapshot, &frame);
|
||||||
let encode_ns = elapsed_ns(encode_started_at);
|
let encode_ns = elapsed_ns(encode_started_at);
|
||||||
let timings = PartialFrameTimings { paint_ns, encode_ns };
|
let timings = PartialFrameTimings { paint_ns, encode_ns };
|
||||||
|
|||||||
Reference in New Issue
Block a user