summaryrefslogtreecommitdiffstats
path: root/benches/wgpu.rs
diff options
context:
space:
mode:
Diffstat (limited to 'benches/wgpu.rs')
-rw-r--r--benches/wgpu.rs228
1 files changed, 228 insertions, 0 deletions
diff --git a/benches/wgpu.rs b/benches/wgpu.rs
new file mode 100644
index 00000000..0e407253
--- /dev/null
+++ b/benches/wgpu.rs
@@ -0,0 +1,228 @@
+#![allow(missing_docs)]
+use criterion::{criterion_group, criterion_main, Bencher, Criterion};
+
+use iced::alignment;
+use iced::mouse;
+use iced::widget::{canvas, scrollable, stack, text};
+use iced::{
+ Color, Element, Font, Length, Pixels, Point, Rectangle, Size, Theme,
+};
+use iced_wgpu::Renderer;
+
+criterion_main!(benches);
+criterion_group!(benches, wgpu_benchmark);
+
+#[allow(unused_results)]
+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));
+ });
+
+ c.bench_function("wgpu - layered text (light)", |b| {
+ benchmark(b, |_| layered_text(10));
+ });
+ c.bench_function("wgpu - layered text (heavy)", |b| {
+ benchmark(b, |_| layered_text(1_000));
+ });
+
+ c.bench_function("wgpu - dynamic text (light)", |b| {
+ benchmark(b, |i| dynamic_text(1_000, i));
+ });
+ c.bench_function("wgpu - dynamic text (heavy)", |b| {
+ benchmark(b, |i| dynamic_text(100_000, i));
+ });
+}
+
+fn benchmark<'a>(
+ bencher: &mut Bencher<'_>,
+ view: impl Fn(usize) -> 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 mut engine = iced_wgpu::Engine::new(
+ &adapter,
+ &device,
+ &queue,
+ format,
+ Some(Antialiasing::MSAAx4),
+ );
+
+ let mut renderer =
+ Renderer::new(&device, &engine, 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 i = 0;
+ let mut cache = Some(runtime::user_interface::Cache::default());
+
+ bencher.iter(|| {
+ let mut user_interface = runtime::UserInterface::build(
+ view(i),
+ viewport.logical_size(),
+ cache.take().unwrap(),
+ &mut renderer,
+ );
+
+ let _ = user_interface.draw(
+ &mut renderer,
+ &Theme::Dark,
+ &core::renderer::Style {
+ text_color: Color::WHITE,
+ },
+ mouse::Cursor::Unavailable,
+ );
+
+ cache = Some(user_interface.into_cache());
+
+ let mut encoder =
+ device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
+ label: None,
+ });
+
+ renderer.present::<&str>(
+ &mut engine,
+ &device,
+ &queue,
+ &mut encoder,
+ Some(Color::BLACK),
+ format,
+ &texture_view,
+ &viewport,
+ &[],
+ );
+
+ let submission = engine.submit(&queue, encoder);
+ let _ = device.poll(wgpu::Maintain::WaitForSubmissionIndex(submission));
+
+ i += 1;
+ });
+}
+
+fn scene<'a, Message: 'a>(n: usize) -> Element<'a, Message, Theme, Renderer> {
+ 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,
+ });
+ }
+ })]
+ }
+ }
+
+ canvas(Scene { n })
+ .width(Length::Fill)
+ .height(Length::Fill)
+ .into()
+}
+
+fn layered_text<'a, Message: 'a>(
+ n: usize,
+) -> Element<'a, Message, Theme, Renderer> {
+ stack((0..n).map(|i| text(format!("I am paragraph {i}!")).into()))
+ .width(Length::Fill)
+ .height(Length::Fill)
+ .into()
+}
+
+fn dynamic_text<'a, Message: 'a>(
+ n: usize,
+ i: usize,
+) -> Element<'a, Message, Theme, Renderer> {
+ const LOREM_IPSUM: &str = include_str!("ipsum.txt");
+
+ scrollable(
+ text(format!(
+ "{}... Iteration {i}",
+ std::iter::repeat(LOREM_IPSUM.chars())
+ .flatten()
+ .take(n)
+ .collect::<String>(),
+ ))
+ .size(10),
+ )
+ .into()
+}