Add `Context::cumulative_frame_nr` (#7278)

This commit is contained in:
Emil Ernerfeldt 2025-06-30 13:29:56 +02:00 committed by GitHub
parent d770cd53a6
commit 8ba42f322d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 83 additions and 28 deletions

View File

@ -339,6 +339,15 @@ impl RepaintCause {
/// Per-viewport state related to repaint scheduling. /// Per-viewport state related to repaint scheduling.
struct ViewportRepaintInfo { struct ViewportRepaintInfo {
/// Monotonically increasing counter. /// Monotonically increasing counter.
///
/// Incremented at the end of [`Context::run`].
/// This can be smaller than [`Self::cumulative_pass_nr`],
/// but never larger.
cumulative_frame_nr: u64,
/// Monotonically increasing counter, counting the number of passes.
/// This can be larger than [`Self::cumulative_frame_nr`],
/// but never smaller.
cumulative_pass_nr: u64, cumulative_pass_nr: u64,
/// The duration which the backend will poll for new events /// The duration which the backend will poll for new events
@ -369,6 +378,7 @@ struct ViewportRepaintInfo {
impl Default for ViewportRepaintInfo { impl Default for ViewportRepaintInfo {
fn default() -> Self { fn default() -> Self {
Self { Self {
cumulative_frame_nr: 0,
cumulative_pass_nr: 0, cumulative_pass_nr: 0,
// We haven't scheduled a repaint yet. // We haven't scheduled a repaint yet.
@ -864,6 +874,7 @@ impl Context {
} else { } else {
viewport.num_multipass_in_row = 0; viewport.num_multipass_in_row = 0;
} }
viewport.repaint.cumulative_frame_nr += 1;
}); });
output output
@ -1536,6 +1547,28 @@ impl Context {
} }
} }
/// The total number of completed frames.
///
/// Starts at zero, and is incremented once at the end of each call to [`Self::run`].
///
/// This is always smaller or equal to [`Self::cumulative_pass_nr`].
pub fn cumulative_frame_nr(&self) -> u64 {
self.cumulative_frame_nr_for(self.viewport_id())
}
/// The total number of completed frames.
///
/// Starts at zero, and is incremented once at the end of each call to [`Self::run`].
///
/// This is always smaller or equal to [`Self::cumulative_pass_nr_for`].
pub fn cumulative_frame_nr_for(&self, id: ViewportId) -> u64 {
self.read(|ctx| {
ctx.viewports
.get(&id)
.map_or(0, |v| v.repaint.cumulative_frame_nr)
})
}
/// The total number of completed passes (usually there is one pass per rendered frame). /// The total number of completed passes (usually there is one pass per rendered frame).
/// ///
/// Starts at zero, and is incremented for each completed pass inside of [`Self::run`] (usually once). /// Starts at zero, and is incremented for each completed pass inside of [`Self::run`] (usually once).
@ -2998,36 +3031,54 @@ impl Context {
pub fn inspection_ui(&self, ui: &mut Ui) { pub fn inspection_ui(&self, ui: &mut Ui) {
use crate::containers::CollapsingHeader; use crate::containers::CollapsingHeader;
ui.label(format!("Is using pointer: {}", self.is_using_pointer())) crate::Grid::new("egui-inspection-grid")
.on_hover_text( .num_columns(2)
"Is egui currently using the pointer actively (e.g. dragging a slider)?", .striped(true)
); .show(ui, |ui| {
ui.label(format!("Wants pointer input: {}", self.wants_pointer_input())) ui.label("Total ui frames:");
.on_hover_text("Is egui currently interested in the location of the pointer (either because it is in use, or because it is hovering over a window)."); ui.monospace(ui.ctx().cumulative_frame_nr().to_string());
ui.label(format!( ui.end_row();
"Wants keyboard input: {}",
self.wants_keyboard_input()
))
.on_hover_text("Is egui currently listening for text input?");
ui.label(format!(
"Keyboard focus widget: {}",
self.memory(|m| m.focused())
.as_ref()
.map(Id::short_debug_format)
.unwrap_or_default()
))
.on_hover_text("Is egui currently listening for text input?");
let pointer_pos = self ui.label("Total ui passes:");
.pointer_hover_pos() ui.monospace(ui.ctx().cumulative_pass_nr().to_string());
.map_or_else(String::new, |pos| format!("{pos:?}")); ui.end_row();
ui.label(format!("Pointer pos: {pointer_pos}"));
let top_layer = self ui.label("Is using pointer")
.pointer_hover_pos() .on_hover_text("Is egui currently using the pointer actively (e.g. dragging a slider)?");
.and_then(|pos| self.layer_id_at(pos)) ui.monospace(self.is_using_pointer().to_string());
.map_or_else(String::new, |layer| layer.short_debug_format()); ui.end_row();
ui.label(format!("Top layer under mouse: {top_layer}"));
ui.label("Wants pointer input")
.on_hover_text("Is egui currently interested in the location of the pointer (either because it is in use, or because it is hovering over a window).");
ui.monospace(self.wants_pointer_input().to_string());
ui.end_row();
ui.label("Wants keyboard input").on_hover_text("Is egui currently listening for text input?");
ui.monospace(self.wants_keyboard_input().to_string());
ui.end_row();
ui.label("Keyboard focus widget").on_hover_text("Is egui currently listening for text input?");
ui.monospace(self.memory(|m| m.focused())
.as_ref()
.map(Id::short_debug_format)
.unwrap_or_default());
ui.end_row();
let pointer_pos = self
.pointer_hover_pos()
.map_or_else(String::new, |pos| format!("{pos:?}"));
ui.label("Pointer pos");
ui.monospace(pointer_pos);
ui.end_row();
let top_layer = self
.pointer_hover_pos()
.and_then(|pos| self.layer_id_at(pos))
.map_or_else(String::new, |layer| layer.short_debug_format());
ui.label("Top layer under mouse");
ui.monospace(top_layer);
ui.end_row();
});
ui.add_space(16.0); ui.add_space(16.0);

View File

@ -146,6 +146,10 @@ impl BackendPanel {
// builds to keep the noise down in the official demo. // builds to keep the noise down in the official demo.
if cfg!(debug_assertions) { if cfg!(debug_assertions) {
ui.collapsing("More…", |ui| { ui.collapsing("More…", |ui| {
ui.horizontal(|ui| {
ui.label("Total ui frames:");
ui.monospace(ui.ctx().cumulative_frame_nr().to_string());
});
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.label("Total ui passes:"); ui.label("Total ui passes:");
ui.monospace(ui.ctx().cumulative_pass_nr().to_string()); ui.monospace(ui.ctx().cumulative_pass_nr().to_string());