diff options
author | 2024-04-07 08:11:42 +0200 | |
---|---|---|
committer | 2024-04-07 11:49:42 +0200 | |
commit | a865b380026ce8c26b818e8e94ea14cb930865a3 (patch) | |
tree | 61021e6c7952c160ec97f7f250b4c9c1feacb173 /benches | |
parent | 63042354fc51884098f88e240f73e689295df31c (diff) | |
download | iced-a865b380026ce8c26b818e8e94ea14cb930865a3.tar.gz iced-a865b380026ce8c26b818e8e94ea14cb930865a3.tar.bz2 iced-a865b380026ce8c26b818e8e94ea14cb930865a3.zip |
Add a simple `wgpu` benchmark using `criterion`
Diffstat (limited to 'benches')
-rw-r--r-- | benches/wgpu.rs | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/benches/wgpu.rs b/benches/wgpu.rs new file mode 100644 index 00000000..617be16d --- /dev/null +++ b/benches/wgpu.rs @@ -0,0 +1,185 @@ +use criterion::{criterion_group, criterion_main, Bencher, Criterion}; + +use iced::alignment; +use iced::mouse; +use iced::widget::{canvas, text}; +use iced::{ + Color, Element, Font, Length, Pixels, Point, Rectangle, Size, Theme, +}; +use iced_wgpu::Renderer; + +criterion_main!(benches); +criterion_group!(benches, wgpu_benchmark); + +pub fn wgpu_benchmark(c: &mut Criterion) { + c.bench_function("wgpu — canvas (light)", |b| benchmark(b, scene(10))); + c.bench_function("wgpu — canvas (heavy)", |b| benchmark(b, scene(1_000))); +} + +fn benchmark<'a>( + bencher: &mut Bencher<'_>, + widget: Element<'a, (), Theme, Renderer>, +) { + use iced_futures::futures::executor; + use iced_wgpu::graphics; + use iced_wgpu::graphics::Antialiasing; + use iced_wgpu::wgpu; + use iced_winit::core; + use iced_winit::runtime; + + let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { + backends: wgpu::Backends::all(), + ..Default::default() + }); + + let adapter = executor::block_on(instance.request_adapter( + &wgpu::RequestAdapterOptions { + power_preference: wgpu::PowerPreference::HighPerformance, + compatible_surface: None, + force_fallback_adapter: false, + }, + )) + .expect("request adapter"); + + let (device, queue) = executor::block_on(adapter.request_device( + &wgpu::DeviceDescriptor { + label: None, + required_features: wgpu::Features::empty(), + required_limits: wgpu::Limits::default(), + }, + None, + )) + .expect("request device"); + + let format = wgpu::TextureFormat::Bgra8UnormSrgb; + + let backend = iced_wgpu::Backend::new( + &adapter, + &device, + &queue, + iced_wgpu::Settings { + present_mode: wgpu::PresentMode::Immediate, + internal_backend: wgpu::Backends::all(), + default_font: Font::DEFAULT, + default_text_size: Pixels::from(16), + antialiasing: Some(Antialiasing::MSAAx4), + }, + format, + ); + + let mut renderer = Renderer::new(backend, Font::DEFAULT, Pixels::from(16)); + + let viewport = + graphics::Viewport::with_physical_size(Size::new(3840, 2160), 2.0); + + let texture = device.create_texture(&wgpu::TextureDescriptor { + label: None, + size: wgpu::Extent3d { + width: 3840, + height: 2160, + depth_or_array_layers: 1, + }, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format, + usage: wgpu::TextureUsages::RENDER_ATTACHMENT, + view_formats: &[], + }); + + let texture_view = + texture.create_view(&wgpu::TextureViewDescriptor::default()); + + let mut user_interface = runtime::UserInterface::build( + widget, + viewport.logical_size(), + runtime::user_interface::Cache::default(), + &mut renderer, + ); + + bencher.iter(|| { + user_interface.draw( + &mut renderer, + &Theme::Dark, + &core::renderer::Style { + text_color: Color::WHITE, + }, + mouse::Cursor::Unavailable, + ); + + let mut encoder = + device.create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: None, + }); + + renderer.with_primitives(|backend, primitives| { + backend.present::<&str>( + &device, + &queue, + &mut encoder, + Some(Color::BLACK), + format, + &texture_view, + primitives, + &viewport, + &[], + ); + + let submission = queue.submit(Some(encoder.finish())); + backend.recall(); + + let _ = + device.poll(wgpu::Maintain::WaitForSubmissionIndex(submission)); + }); + }); +} + +fn scene<'a, Message: 'a, Theme: 'a>( + n: usize, +) -> Element<'a, Message, Theme, Renderer> { + canvas(Scene { n }) + .width(Length::Fill) + .height(Length::Fill) + .into() +} + +struct Scene { + n: usize, +} + +impl<Message, Theme> canvas::Program<Message, Theme, Renderer> for Scene { + type State = canvas::Cache<Renderer>; + + fn draw( + &self, + cache: &Self::State, + renderer: &Renderer, + _theme: &Theme, + bounds: Rectangle, + _cursor: mouse::Cursor, + ) -> Vec<canvas::Geometry<Renderer>> { + vec![cache.draw(renderer, bounds.size(), |frame| { + for i in 0..self.n { + frame.fill_rectangle( + Point::new(0.0, i as f32), + Size::new(10.0, 10.0), + Color::WHITE, + ); + } + + for i in 0..self.n { + frame.fill_text(canvas::Text { + content: i.to_string(), + position: Point::new(0.0, i as f32), + color: Color::BLACK, + size: Pixels::from(16), + line_height: text::LineHeight::default(), + font: Font::DEFAULT, + horizontal_alignment: alignment::Horizontal::Left, + vertical_alignment: alignment::Vertical::Top, + shaping: text::Shaping::Basic, + }); + } + })] + } +} |