From b5ef2c5bdef6b1df4d76962399aae35ba81b9dab Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld Date: Tue, 22 Nov 2022 18:20:20 +0100 Subject: [PATCH] kms: Use recent average frame_time for delay --- src/backend/kms/mod.rs | 28 +++++-------- src/backend/render/mod.rs | 13 ++---- src/backend/winit.rs | 2 + src/backend/x11.rs | 2 + src/state.rs | 64 ++++++++++++++++++------------ src/wayland/handlers/screencopy.rs | 4 -- 6 files changed, 55 insertions(+), 58 deletions(-) diff --git a/src/backend/kms/mod.rs b/src/backend/kms/mod.rs index 4b9d37ee..6652b632 100644 --- a/src/backend/kms/mod.rs +++ b/src/backend/kms/mod.rs @@ -1,13 +1,10 @@ // SPDX-License-Identifier: GPL-3.0-only -#[cfg(feature = "debug")] -use crate::state::Fps; - use crate::{ backend::render, config::OutputConfig, shell::Shell, - state::{BackendData, ClientState, Common, Data}, + state::{BackendData, ClientState, Common, Data, Fps}, utils::prelude::*, wayland::{ handlers::screencopy::{PendingScreencopyBuffers, UserdataExt}, @@ -69,6 +66,8 @@ use session_fd::*; use socket::*; use super::render::{CursorMode, GlMultiRenderer}; +// for now we assume we need at least 3ms +const MIN_RENDER_TIME: Duration = Duration::from_millis(3); pub struct KmsState { devices: HashMap, @@ -107,7 +106,6 @@ pub struct Surface { pending: bool, dirty: bool, render_timer_token: Option, - #[cfg(feature = "debug")] fps: Fps, } @@ -381,7 +379,7 @@ impl State { let dispatcher = Dispatcher::new(drm, move |event, metadata, data: &mut Data| match event { DrmEvent::VBlank(crtc) => { - let rescheduled_output = + let rescheduled = if let Some(device) = data.state.backend.kms().devices.get_mut(&drm_node) { if let Some(surface) = device.surfaces.get_mut(&crtc) { #[cfg(feature = "debug")] @@ -427,7 +425,9 @@ impl State { } surface.pending = false; - surface.dirty.then(|| surface.output.clone()) + surface.dirty.then(|| { + (surface.output.clone(), surface.fps.avg_rendertime(5)) + }) } Some(Err(err)) => { slog_scope::warn!("Failed to submit frame: {}", err); @@ -442,7 +442,7 @@ impl State { None }; - if let Some(output) = rescheduled_output { + if let Some((output, avg_rendertime)) = rescheduled { let mut scheduled_sessions = data.state.workspace_session_for_output(&output); if let Some(sessions) = output.user_data().get::() @@ -452,15 +452,7 @@ impl State { .extend(sessions.borrow_mut().drain(..)); } - let output_refresh = match output.current_mode() { - Some(mode) => mode.refresh, - None => return, - }; - // TODO: Record rendering times and use sliding window to estimate duration for next render - let repaint_delay = Duration::from_secs_f64( - ((1000.0 / output_refresh as f64) * 0.6).max(0.003), // for now we assume we need at least 3ms - ); - + let repaint_delay = std::cmp::max(avg_rendertime, MIN_RENDER_TIME); if let Err(err) = data.state.backend.kms().schedule_render( &data.state.common.event_loop_handle, &output, @@ -781,7 +773,6 @@ impl Device { pending: false, dirty: false, render_timer_token: None, - #[cfg(feature = "debug")] fps: Fps::new(renderer.as_mut()), }; self.surfaces.insert(crtc, data); @@ -861,7 +852,6 @@ impl Surface { &self.output, CursorMode::All, screencopy.map(|sessions| (buffer, sessions)), - #[cfg(feature = "debug")] Some(&mut self.fps), ) { Ok((damage, states)) => { diff --git a/src/backend/render/mod.rs b/src/backend/render/mod.rs index 709bca1b..58793018 100644 --- a/src/backend/render/mod.rs +++ b/src/backend/render/mod.rs @@ -1,10 +1,10 @@ // SPDX-License-Identifier: GPL-3.0-only #[cfg(feature = "debug")] -use crate::{debug::fps_ui, state::Fps, utils::prelude::*}; +use crate::{debug::fps_ui, utils::prelude::*}; use crate::{ shell::{layout::floating::SeatMoveGrabState, CosmicMappedRenderElement}, - state::Common, + state::{Common, Fps}, wayland::{ handlers::{data_device::get_dnd_icon, screencopy::render_session}, protocols::{ @@ -134,7 +134,7 @@ pub fn render_output( output: &Output, cursor_mode: CursorMode, screencopy: Option<(Source, &[(ScreencopySession, BufferParams)])>, - #[cfg(feature = "debug")] fps: Option<&mut Fps>, + fps: Option<&mut Fps>, ) -> Result<(Option>>, RenderElementStates), RenderError> where R: Renderer @@ -165,7 +165,6 @@ where &handle, cursor_mode, screencopy, - #[cfg(feature = "debug")] fps, ) } @@ -181,7 +180,7 @@ pub fn render_workspace( handle: &WorkspaceHandle, mut cursor_mode: CursorMode, screencopy: Option<(Source, &[(ScreencopySession, BufferParams)])>, - #[cfg(feature = "debug")] mut fps: Option<&mut Fps>, + mut fps: Option<&mut Fps>, ) -> Result<(Option>>, RenderElementStates), RenderError> where R: Renderer @@ -200,7 +199,6 @@ where CosmicMappedRenderElement: RenderElement, Source: Clone, { - #[cfg(feature = "debug")] if let Some(ref mut fps) = fps { fps.start(); } @@ -255,7 +253,6 @@ where .map(Into::into), ); - #[cfg(feature = "debug")] if let Some(fps) = fps.as_mut() { fps.elements(); } @@ -263,7 +260,6 @@ where renderer.bind(target).map_err(RenderError::Rendering)?; let res = damage_tracker.render_output(renderer, age, &elements, CLEAR_COLOR, None); - #[cfg(feature = "debug")] if let Some(fps) = fps.as_mut() { fps.render(); } @@ -311,7 +307,6 @@ where } } } - #[cfg(feature = "debug")] if let Some(fps) = fps.as_mut() { fps.screencopy(); } diff --git a/src/backend/winit.rs b/src/backend/winit.rs index b8bf4cb1..0e4a259b 100644 --- a/src/backend/winit.rs +++ b/src/backend/winit.rs @@ -65,6 +65,8 @@ impl WinitState { } else { None }, + #[cfg(not(feature = "debug"))] + None, #[cfg(feature = "debug")] Some(&mut self.fps), ) { diff --git a/src/backend/x11.rs b/src/backend/x11.rs index a993418b..6d54691e 100644 --- a/src/backend/x11.rs +++ b/src/backend/x11.rs @@ -213,6 +213,8 @@ impl Surface { } else { None }, + #[cfg(not(feature = "debug"))] + None, #[cfg(feature = "debug")] Some(&mut self.fps), ) { diff --git a/src/state.rs b/src/state.rs index a1a7d6a4..9deee434 100644 --- a/src/state.rs +++ b/src/state.rs @@ -14,12 +14,13 @@ use crate::{ }, }; use cosmic_protocols::screencopy::v1::server::zcosmic_screencopy_manager_v1::CursorMode; -#[cfg(feature = "debug")] -use smithay::backend::renderer::glow::GlowRenderer; use smithay::{ backend::{ drm::DrmNode, - renderer::element::{default_primary_scanout_output_compare, RenderElementStates}, + renderer::{ + element::{default_primary_scanout_output_compare, RenderElementStates}, + glow::GlowRenderer, + }, }, desktop::utils::{ surface_presentation_feedback_flags_from_states, surface_primary_scanout_output, @@ -35,7 +36,7 @@ use smithay::{ Display, DisplayHandle, }, }, - utils::{Clock, Monotonic, Rectangle}, + utils::{Clock, Monotonic}, wayland::{ compositor::CompositorState, data_device::DataDeviceState, dmabuf::DmabufState, keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitState, output::OutputManagerState, @@ -45,7 +46,6 @@ use smithay::{ }; use std::{cell::RefCell, ffi::OsString, time::Duration}; -#[cfg(feature = "debug")] use std::{collections::VecDeque, time::Instant}; pub struct ClientState { @@ -432,14 +432,13 @@ pub struct Egui { pub active: bool, } -#[cfg(feature = "debug")] pub struct Fps { + #[cfg(feature = "debug")] pub state: smithay_egui::EguiState, pending_frame: Option, pub frames: VecDeque, } -#[cfg(feature = "debug")] #[derive(Debug)] struct PendingFrame { start: Instant, @@ -449,7 +448,6 @@ struct PendingFrame { duration_displayed: Option, } -#[cfg(feature = "debug")] #[derive(Debug)] pub struct Frame { pub start: Instant, @@ -459,8 +457,11 @@ pub struct Frame { pub duration_displayed: Duration, } -#[cfg(feature = "debug")] impl Frame { + fn render_time(&self) -> Duration { + self.duration_elements + self.duration_render + } + fn frame_time(&self) -> Duration { self.duration_elements + self.duration_render @@ -475,7 +476,6 @@ impl Frame { } } -#[cfg(feature = "debug")] impl From for Frame { fn from(pending: PendingFrame) -> Self { Frame { @@ -488,7 +488,6 @@ impl From for Frame { } } -#[cfg(feature = "debug")] impl Fps { const WINDOW_SIZE: usize = 360; @@ -582,6 +581,15 @@ impl Fps { self.frames.iter().map(|f| f.frame_time()).sum::() / (self.frames.len() as u32) } + pub fn avg_rendertime(&self, window: usize) -> Duration { + self.frames + .iter() + .take(window) + .map(|f| f.render_time()) + .sum::() + / window as u32 + } + pub fn avg_fps(&self) -> f64 { if self.frames.is_empty() { return 0.0; @@ -597,33 +605,38 @@ impl Fps { } } +#[cfg(feature = "debug")] static INTEL_LOGO: &'static [u8] = include_bytes!("../resources/icons/intel.svg"); +#[cfg(feature = "debug")] static AMD_LOGO: &'static [u8] = include_bytes!("../resources/icons/amd.svg"); +#[cfg(feature = "debug")] static NVIDIA_LOGO: &'static [u8] = include_bytes!("../resources/icons/nvidia.svg"); -#[cfg(feature = "debug")] impl Fps { - pub fn new(renderer: &mut GlowRenderer) -> Fps { + pub fn new(_renderer: &mut GlowRenderer) -> Fps { + #[cfg(feature = "debug")] let state = { - let state = - smithay_egui::EguiState::new(Rectangle::from_loc_and_size((0, 0), (400, 800))); + let state = smithay_egui::EguiState::new(smithay::utils::Rectangle::from_loc_and_size( + (0, 0), + (400, 800), + )); let mut visuals: egui::style::Visuals = Default::default(); visuals.window_shadow.extrusion = 0.0; state.context().set_visuals(visuals); state + .load_svg(_renderer, String::from("intel"), INTEL_LOGO) + .unwrap(); + state + .load_svg(_renderer, String::from("amd"), AMD_LOGO) + .unwrap(); + state + .load_svg(_renderer, String::from("nvidia"), NVIDIA_LOGO) + .unwrap(); + state }; - state - .load_svg(renderer, String::from("intel"), INTEL_LOGO) - .unwrap(); - state - .load_svg(renderer, String::from("amd"), AMD_LOGO) - .unwrap(); - state - .load_svg(renderer, String::from("nvidia"), NVIDIA_LOGO) - .unwrap(); - Fps { + #[cfg(feature = "debug")] state, pending_frame: None, frames: VecDeque::with_capacity(Fps::WINDOW_SIZE + 1), @@ -631,7 +644,6 @@ impl Fps { } } -#[cfg(feature = "debug")] pub fn avg_fps<'a>(iter: impl Iterator) -> f64 { let sum_secs = iter.map(|d| d.as_secs_f64()).sum::(); 1.0 / (sum_secs / Fps::WINDOW_SIZE as f64) diff --git a/src/wayland/handlers/screencopy.rs b/src/wayland/handlers/screencopy.rs index ba065160..d16d65dd 100644 --- a/src/wayland/handlers/screencopy.rs +++ b/src/wayland/handlers/screencopy.rs @@ -619,7 +619,6 @@ pub fn render_output_to_buffer( &output, cursor_mode, None, - #[cfg(feature = "debug")] None, ) } else { @@ -636,7 +635,6 @@ pub fn render_output_to_buffer( &output, cursor_mode, None, - #[cfg(feature = "debug")] None, ) } @@ -700,7 +698,6 @@ pub fn render_workspace_to_buffer( handle, cursor_mode, None, - #[cfg(feature = "debug")] None, ) } else { @@ -718,7 +715,6 @@ pub fn render_workspace_to_buffer( handle, cursor_mode, None, - #[cfg(feature = "debug")] None, ) }