Skip to main content

clear_screen/
clear_screen.rs

1//! Fase 1 de Llimphi: ventana gris plomo a la frecuencia máxima del display.
2//!
3//! Corre con: `cargo run -p llimphi-hal --example clear_screen --release`.
4//!
5//! Imprime fps por stderr cada segundo. En un panel de 144 Hz con AutoVsync
6//! debe estabilizarse cerca de 144; en uno de 60 Hz, cerca de 60.
7
8use std::sync::Arc;
9use std::time::Instant;
10
11use llimphi_hal::winit::application::ApplicationHandler;
12use llimphi_hal::winit::dpi::LogicalSize;
13use llimphi_hal::winit::event::WindowEvent;
14use llimphi_hal::winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
15use llimphi_hal::winit::window::{Window, WindowAttributes, WindowId};
16use llimphi_hal::{wgpu, Hal, Surface, WinitSurface};
17
18const LEAD_GRAY: wgpu::Color = wgpu::Color {
19    r: 0.235,
20    g: 0.239,
21    b: 0.247,
22    a: 1.0,
23};
24
25struct State {
26    window: Arc<Window>,
27    hal: Hal,
28    surface: WinitSurface,
29}
30
31struct App {
32    state: Option<State>,
33    frames: u64,
34    last_report: Instant,
35}
36
37impl ApplicationHandler for App {
38    fn resumed(&mut self, event_loop: &ActiveEventLoop) {
39        if self.state.is_some() {
40            return;
41        }
42        let window = event_loop
43            .create_window(
44                WindowAttributes::default()
45                    .with_title("llimphi · clear_screen")
46                    .with_inner_size(LogicalSize::new(960u32, 540u32)),
47            )
48            .expect("create window");
49        let window = Arc::new(window);
50        let hal = pollster::block_on(Hal::new(None)).expect("hal");
51        let surface = WinitSurface::new(&hal, window.clone()).expect("surface");
52        window.request_redraw();
53        self.state = Some(State {
54            window,
55            hal,
56            surface,
57        });
58    }
59
60    fn window_event(
61        &mut self,
62        event_loop: &ActiveEventLoop,
63        _id: WindowId,
64        event: WindowEvent,
65    ) {
66        let Some(state) = self.state.as_mut() else {
67            return;
68        };
69        match event {
70            WindowEvent::CloseRequested => event_loop.exit(),
71            WindowEvent::Resized(size) => {
72                state.surface.resize(size.width, size.height);
73                state.window.request_redraw();
74            }
75            WindowEvent::RedrawRequested => {
76                let frame = match state.surface.acquire() {
77                    Ok(f) => f,
78                    Err(_) => {
79                        let (w, h) = state.surface.size();
80                        state.surface.resize(w, h);
81                        state.window.request_redraw();
82                        return;
83                    }
84                };
85                let mut encoder =
86                    state
87                        .hal
88                        .device
89                        .create_command_encoder(&wgpu::CommandEncoderDescriptor {
90                            label: Some("clear_screen-encoder"),
91                        });
92                {
93                    let _pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
94                        label: Some("clear_screen-pass"),
95                        color_attachments: &[Some(wgpu::RenderPassColorAttachment {
96                            view: frame.view(),
97                            resolve_target: None,
98                            depth_slice: None,
99                            ops: wgpu::Operations {
100                                load: wgpu::LoadOp::Clear(LEAD_GRAY),
101                                store: wgpu::StoreOp::Store,
102                            },
103                        })],
104                        depth_stencil_attachment: None,
105                        timestamp_writes: None,
106                        occlusion_query_set: None,
107                    });
108                }
109                state.hal.queue.submit(std::iter::once(encoder.finish()));
110                state.surface.present(frame, &state.hal);
111
112                self.frames += 1;
113                let elapsed = self.last_report.elapsed();
114                if elapsed.as_secs() >= 1 {
115                    let fps = self.frames as f64 / elapsed.as_secs_f64();
116                    eprintln!("llimphi · clear_screen — {fps:.1} fps");
117                    self.frames = 0;
118                    self.last_report = Instant::now();
119                }
120                state.window.request_redraw();
121            }
122            _ => {}
123        }
124    }
125}
126
127fn main() {
128    let event_loop = EventLoop::new().expect("event loop");
129    event_loop.set_control_flow(ControlFlow::Poll);
130    let mut app = App {
131        state: None,
132        frames: 0,
133        last_report: Instant::now(),
134    };
135    event_loop.run_app(&mut app).expect("run app");
136}