|
| 1 | +use criterion::{black_box, criterion_group, criterion_main, Criterion}; |
| 2 | + |
| 3 | +use iced_native::{widget, Renderer}; |
| 4 | + |
| 5 | +use iced_bench::{glow::GlowBench, render_widget, wgpu::WgpuBench, Bench}; |
| 6 | + |
| 7 | +static LOREM_IPSUM: &str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; |
| 8 | + |
| 9 | +fn image(size: u32) -> iced_native::image::Handle { |
| 10 | + let mut bytes = Vec::with_capacity(size as usize * size as usize * 4); |
| 11 | + for _y in 0..size { |
| 12 | + for _x in 0..size { |
| 13 | + let r = rand::random(); |
| 14 | + let g = rand::random(); |
| 15 | + let b = rand::random(); |
| 16 | + bytes.extend_from_slice(&[r, g, b, 255]); |
| 17 | + } |
| 18 | + } |
| 19 | + iced_native::image::Handle::from_pixels(size, size, bytes) |
| 20 | +} |
| 21 | + |
| 22 | +fn text_primitive< |
| 23 | + R: iced_native::Renderer<Theme = iced::Theme> + iced_native::text::Renderer, |
| 24 | +>( |
| 25 | + renderer: &R, |
| 26 | +) -> iced_graphics::Primitive { |
| 27 | + iced_graphics::Primitive::Text { |
| 28 | + content: LOREM_IPSUM.to_string(), |
| 29 | + bounds: iced::Rectangle::with_size(iced::Size::new(1024.0, 1024.0)), |
| 30 | + color: iced_native::Color::BLACK, |
| 31 | + size: f32::from(renderer.default_size()), |
| 32 | + font: Default::default(), |
| 33 | + horizontal_alignment: iced_native::alignment::Horizontal::Left, |
| 34 | + vertical_alignment: iced_native::alignment::Vertical::Top, |
| 35 | + } |
| 36 | +} |
| 37 | + |
| 38 | +fn text_widget< |
| 39 | + R: iced_native::Renderer<Theme = iced::Theme> + iced_native::text::Renderer, |
| 40 | +>() -> widget::Text<'static, R> { |
| 41 | + widget::helpers::text(LOREM_IPSUM) |
| 42 | +} |
| 43 | + |
| 44 | +fn iter_render< |
| 45 | + B: Bench, |
| 46 | + F: FnMut(&mut iced_graphics::Renderer<B::Backend, iced::Theme>), |
| 47 | +>( |
| 48 | + b: &mut criterion::Bencher, |
| 49 | + bench: &mut B, |
| 50 | + mut draw_cb: F, |
| 51 | +) { |
| 52 | + b.iter(|| { |
| 53 | + bench.renderer().clear(); |
| 54 | + let state = bench.clear(); |
| 55 | + draw_cb(bench.renderer()); |
| 56 | + bench.present(state); |
| 57 | + }) |
| 58 | +} |
| 59 | + |
| 60 | +fn bench_function< |
| 61 | + B: Bench, |
| 62 | + F: FnMut(&mut iced_graphics::Renderer<B::Backend, iced::Theme>), |
| 63 | +>( |
| 64 | + c: &mut Criterion, |
| 65 | + bench: &mut B, |
| 66 | + id: &str, |
| 67 | + mut draw_cb: F, |
| 68 | +) { |
| 69 | + c.bench_function(&format!("{} {}", B::BACKEND_NAME, id), |b| { |
| 70 | + iter_render(b, bench, |backend| draw_cb(backend)); |
| 71 | + }); |
| 72 | + |
| 73 | + // Write output to file, so there's a way to see that generated |
| 74 | + // image is correct. |
| 75 | + let dir = std::path::Path::new(env!("CARGO_TARGET_TMPDIR")) |
| 76 | + .join(format!("bench-renderers/{}", B::BACKEND_NAME)); |
| 77 | + std::fs::create_dir_all(&dir).unwrap(); |
| 78 | + bench |
| 79 | + .read_pixels() |
| 80 | + .save(&dir.join(&format!("{}.png", id))) |
| 81 | + .unwrap(); |
| 82 | +} |
| 83 | + |
| 84 | +fn generic_benchmark<B: Bench>(c: &mut Criterion, bench: &mut B) |
| 85 | +where |
| 86 | + B::Backend: iced_graphics::backend::Text, |
| 87 | +{ |
| 88 | + bench_function(c, bench, "draw no primitive", |_renderer| {}); |
| 89 | + bench_function(c, bench, "draw quad primitive", |renderer| { |
| 90 | + renderer.draw_primitive(black_box(iced_graphics::Primitive::Quad { |
| 91 | + bounds: iced::Rectangle::with_size(iced::Size::new(256.0, 256.0)), |
| 92 | + background: iced_native::Background::Color( |
| 93 | + iced_native::Color::BLACK, |
| 94 | + ), |
| 95 | + border_radius: 0., |
| 96 | + border_width: 0., |
| 97 | + border_color: Default::default(), |
| 98 | + })); |
| 99 | + }); |
| 100 | + bench_function(c, bench, "draw text primitive", |renderer| { |
| 101 | + renderer.draw_primitive(black_box(text_primitive(renderer))); |
| 102 | + }); |
| 103 | + let widget = text_widget(); |
| 104 | + bench_function(c, bench, "render text", |renderer| { |
| 105 | + render_widget(&widget, renderer); |
| 106 | + }); |
| 107 | + let handle = image(1024); |
| 108 | + let bounds = iced::Rectangle::with_size(iced::Size::new(1024.0, 1024.0)); |
| 109 | + bench_function(c, bench, "draw image primitive", |renderer| { |
| 110 | + renderer.draw_primitive(iced_graphics::Primitive::Image { |
| 111 | + handle: handle.clone(), |
| 112 | + bounds, |
| 113 | + }); |
| 114 | + }); |
| 115 | +} |
| 116 | + |
| 117 | +fn glow_benchmark(c: &mut Criterion) { |
| 118 | + let mut bench = GlowBench::new(1024, 1024); |
| 119 | + |
| 120 | + generic_benchmark(c, &mut bench); |
| 121 | +} |
| 122 | + |
| 123 | +fn wgpu_benchmark(c: &mut Criterion) { |
| 124 | + let mut bench = WgpuBench::new(1024, 1024); |
| 125 | + |
| 126 | + generic_benchmark(c, &mut bench); |
| 127 | + |
| 128 | + let widget = widget::helpers::image(image(1024)); |
| 129 | + bench_function(c, &mut bench, "render image", |renderer| { |
| 130 | + render_widget(&widget, renderer); |
| 131 | + }); |
| 132 | +} |
| 133 | + |
| 134 | +criterion_group!(benches, glow_benchmark, wgpu_benchmark); |
| 135 | +criterion_main!(benches); |
0 commit comments