Skip to content

Commit 105b8bd

Browse files
authored
Merge pull request #2382 from iced-rs/wgpu/better-architecture
Improved architecture for `iced_wgpu` and `iced_tiny_skia`
2 parents ee105e3 + dbbbadf commit 105b8bd

67 files changed

Lines changed: 4848 additions & 4158 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.cargo/config.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
[alias]
2-
lint = "clippy --workspace --no-deps -- -D warnings"
2+
lint = "clippy --workspace --benches --all-features --no-deps -- -D warnings"

.github/workflows/check.yml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,6 @@
11
name: Check
22
on: [push, pull_request]
33
jobs:
4-
widget:
5-
runs-on: ubuntu-latest
6-
steps:
7-
- uses: hecrj/setup-rust-action@v2
8-
- uses: actions/checkout@master
9-
- name: Check standalone `iced_widget` crate
10-
run: cargo check --package iced_widget --features image,svg,canvas
11-
124
wasm:
135
runs-on: ubuntu-latest
146
env:
@@ -27,3 +19,11 @@ jobs:
2719
run: cargo build --package todos --target wasm32-unknown-unknown
2820
- name: Check compilation of `integration` example
2921
run: cargo build --package integration --target wasm32-unknown-unknown
22+
23+
widget:
24+
runs-on: ubuntu-latest
25+
steps:
26+
- uses: hecrj/setup-rust-action@v2
27+
- uses: actions/checkout@master
28+
- name: Check standalone `iced_widget` crate
29+
run: cargo check --package iced_widget --features image,svg,canvas

benches/wgpu.rs

Lines changed: 22 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,15 @@ use iced_wgpu::Renderer;
1212
criterion_main!(benches);
1313
criterion_group!(benches, wgpu_benchmark);
1414

15+
#[allow(unused_results)]
1516
pub fn wgpu_benchmark(c: &mut Criterion) {
16-
let _ = c
17-
.bench_function("wgpu — canvas (light)", |b| benchmark(b, scene(10)));
18-
19-
let _ = c.bench_function("wgpu — canvas (heavy)", |b| {
20-
benchmark(b, scene(1_000))
21-
});
17+
c.bench_function("wgpu — canvas (light)", |b| benchmark(b, scene(10)));
18+
c.bench_function("wgpu — canvas (heavy)", |b| benchmark(b, scene(1_000)));
2219
}
2320

24-
fn benchmark<'a>(
21+
fn benchmark(
2522
bencher: &mut Bencher<'_>,
26-
widget: Element<'a, (), Theme, Renderer>,
23+
widget: Element<'_, (), Theme, Renderer>,
2724
) {
2825
use iced_futures::futures::executor;
2926
use iced_wgpu::graphics;
@@ -58,21 +55,15 @@ fn benchmark<'a>(
5855

5956
let format = wgpu::TextureFormat::Bgra8UnormSrgb;
6057

61-
let backend = iced_wgpu::Backend::new(
58+
let mut engine = iced_wgpu::Engine::new(
6259
&adapter,
6360
&device,
6461
&queue,
65-
iced_wgpu::Settings {
66-
present_mode: wgpu::PresentMode::Immediate,
67-
internal_backend: wgpu::Backends::all(),
68-
default_font: Font::DEFAULT,
69-
default_text_size: Pixels::from(16),
70-
antialiasing: Some(Antialiasing::MSAAx4),
71-
},
7262
format,
63+
Some(Antialiasing::MSAAx4),
7364
);
7465

75-
let mut renderer = Renderer::new(backend, Font::DEFAULT, Pixels::from(16));
66+
let mut renderer = Renderer::new(&engine, Font::DEFAULT, Pixels::from(16));
7667

7768
let viewport =
7869
graphics::Viewport::with_physical_size(Size::new(3840, 2160), 2.0);
@@ -117,25 +108,20 @@ fn benchmark<'a>(
117108
label: None,
118109
});
119110

120-
renderer.with_primitives(|backend, primitives| {
121-
backend.present::<&str>(
122-
&device,
123-
&queue,
124-
&mut encoder,
125-
Some(Color::BLACK),
126-
format,
127-
&texture_view,
128-
primitives,
129-
&viewport,
130-
&[],
131-
);
132-
133-
let submission = queue.submit(Some(encoder.finish()));
134-
backend.recall();
135-
136-
let _ =
137-
device.poll(wgpu::Maintain::WaitForSubmissionIndex(submission));
138-
});
111+
renderer.present::<&str>(
112+
&mut engine,
113+
&device,
114+
&queue,
115+
&mut encoder,
116+
Some(Color::BLACK),
117+
format,
118+
&texture_view,
119+
&viewport,
120+
&[],
121+
);
122+
123+
let submission = engine.submit(&queue, encoder);
124+
let _ = device.poll(wgpu::Maintain::WaitForSubmissionIndex(submission));
139125
});
140126
}
141127

core/src/rectangle.rs

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,32 @@ pub struct Rectangle<T = f32> {
1616
pub height: T,
1717
}
1818

19-
impl Rectangle<f32> {
20-
/// Creates a new [`Rectangle`] with its top-left corner in the given
21-
/// [`Point`] and with the provided [`Size`].
22-
pub fn new(top_left: Point, size: Size) -> Self {
19+
impl<T> Rectangle<T>
20+
where
21+
T: Default,
22+
{
23+
/// Creates a new [`Rectangle`] with its top-left corner at the origin
24+
/// and with the provided [`Size`].
25+
pub fn with_size(size: Size<T>) -> Self {
2326
Self {
24-
x: top_left.x,
25-
y: top_left.y,
27+
x: T::default(),
28+
y: T::default(),
2629
width: size.width,
2730
height: size.height,
2831
}
2932
}
33+
}
3034

31-
/// Creates a new [`Rectangle`] with its top-left corner at the origin
32-
/// and with the provided [`Size`].
33-
pub fn with_size(size: Size) -> Self {
35+
impl Rectangle<f32> {
36+
/// A rectangle starting at [`Point::ORIGIN`] with infinite width and height.
37+
pub const INFINITE: Self = Self::new(Point::ORIGIN, Size::INFINITY);
38+
39+
/// Creates a new [`Rectangle`] with its top-left corner in the given
40+
/// [`Point`] and with the provided [`Size`].
41+
pub const fn new(top_left: Point, size: Size) -> Self {
3442
Self {
35-
x: 0.0,
36-
y: 0.0,
43+
x: top_left.x,
44+
y: top_left.y,
3745
width: size.width,
3846
height: size.height,
3947
}
@@ -139,13 +147,20 @@ impl Rectangle<f32> {
139147
}
140148

141149
/// Snaps the [`Rectangle`] to __unsigned__ integer coordinates.
142-
pub fn snap(self) -> Rectangle<u32> {
143-
Rectangle {
150+
pub fn snap(self) -> Option<Rectangle<u32>> {
151+
let width = self.width as u32;
152+
let height = self.height as u32;
153+
154+
if width < 1 || height < 1 {
155+
return None;
156+
}
157+
158+
Some(Rectangle {
144159
x: self.x as u32,
145160
y: self.y as u32,
146-
width: self.width as u32,
147-
height: self.height as u32,
148-
}
161+
width,
162+
height,
163+
})
149164
}
150165

151166
/// Expands the [`Rectangle`] a given amount.

core/src/renderer.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,39 +9,39 @@ use crate::{
99
/// A component that can be used by widgets to draw themselves on a screen.
1010
pub trait Renderer {
1111
/// Starts recording a new layer.
12-
fn start_layer(&mut self);
12+
fn start_layer(&mut self, bounds: Rectangle);
1313

1414
/// Ends recording a new layer.
1515
///
1616
/// The new layer will clip its contents to the provided `bounds`.
17-
fn end_layer(&mut self, bounds: Rectangle);
17+
fn end_layer(&mut self);
1818

1919
/// Draws the primitives recorded in the given closure in a new layer.
2020
///
2121
/// The layer will clip its contents to the provided `bounds`.
2222
fn with_layer(&mut self, bounds: Rectangle, f: impl FnOnce(&mut Self)) {
23-
self.start_layer();
23+
self.start_layer(bounds);
2424
f(self);
25-
self.end_layer(bounds);
25+
self.end_layer();
2626
}
2727

2828
/// Starts recording with a new [`Transformation`].
29-
fn start_transformation(&mut self);
29+
fn start_transformation(&mut self, transformation: Transformation);
3030

3131
/// Ends recording a new layer.
3232
///
3333
/// The new layer will clip its contents to the provided `bounds`.
34-
fn end_transformation(&mut self, transformation: Transformation);
34+
fn end_transformation(&mut self);
3535

3636
/// Applies a [`Transformation`] to the primitives recorded in the given closure.
3737
fn with_transformation(
3838
&mut self,
3939
transformation: Transformation,
4040
f: impl FnOnce(&mut Self),
4141
) {
42-
self.start_transformation();
42+
self.start_transformation(transformation);
4343
f(self);
44-
self.end_transformation(transformation);
44+
self.end_transformation();
4545
}
4646

4747
/// Applies a translation to the primitives recorded in the given closure.

core/src/renderer/null.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,14 @@ use crate::{
77
Background, Color, Font, Pixels, Point, Rectangle, Size, Transformation,
88
};
99

10-
use std::borrow::Cow;
11-
1210
impl Renderer for () {
13-
fn start_layer(&mut self) {}
11+
fn start_layer(&mut self, _bounds: Rectangle) {}
1412

15-
fn end_layer(&mut self, _bounds: Rectangle) {}
13+
fn end_layer(&mut self) {}
1614

17-
fn start_transformation(&mut self) {}
15+
fn start_transformation(&mut self, _transformation: Transformation) {}
1816

19-
fn end_transformation(&mut self, _transformation: Transformation) {}
17+
fn end_transformation(&mut self) {}
2018

2119
fn clear(&mut self) {}
2220

@@ -45,8 +43,6 @@ impl text::Renderer for () {
4543
Pixels(16.0)
4644
}
4745

48-
fn load_font(&mut self, _font: Cow<'static, [u8]>) {}
49-
5046
fn fill_paragraph(
5147
&mut self,
5248
_paragraph: &Self::Paragraph,

core/src/size.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,17 @@ where
9999
}
100100
}
101101
}
102+
103+
impl<T> std::ops::Mul<T> for Size<T>
104+
where
105+
T: std::ops::Mul<Output = T> + Copy,
106+
{
107+
type Output = Size<T>;
108+
109+
fn mul(self, rhs: T) -> Self::Output {
110+
Size {
111+
width: self.width * rhs,
112+
height: self.height * rhs,
113+
}
114+
}
115+
}

core/src/text.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ pub use paragraph::Paragraph;
1111
use crate::alignment;
1212
use crate::{Color, Pixels, Point, Rectangle, Size};
1313

14-
use std::borrow::Cow;
1514
use std::hash::{Hash, Hasher};
1615

1716
/// A paragraph.
@@ -192,9 +191,6 @@ pub trait Renderer: crate::Renderer {
192191
/// Returns the default size of [`Text`].
193192
fn default_size(&self) -> Pixels;
194193

195-
/// Loads a [`Self::Font`] from its bytes.
196-
fn load_font(&mut self, font: Cow<'static, [u8]>);
197-
198194
/// Draws the given [`Paragraph`] at the given position and with the given
199195
/// [`Color`].
200196
fn fill_paragraph(

core/src/transformation.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ impl Transformation {
4242
}
4343
}
4444

45+
impl Default for Transformation {
46+
fn default() -> Self {
47+
Transformation::IDENTITY
48+
}
49+
}
50+
4551
impl Mul for Transformation {
4652
type Output = Self;
4753

examples/custom_shader/src/scene.rs

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ use pipeline::cube::{self, Cube};
99

1010
use iced::mouse;
1111
use iced::time::Duration;
12-
use iced::widget::shader;
13-
use iced::{Color, Rectangle, Size};
12+
use iced::widget::shader::{self, Viewport};
13+
use iced::{Color, Rectangle};
1414

1515
use glam::Vec3;
1616
use rand::Rng;
@@ -130,25 +130,29 @@ impl Primitive {
130130
impl shader::Primitive for Primitive {
131131
fn prepare(
132132
&self,
133-
format: wgpu::TextureFormat,
134133
device: &wgpu::Device,
135134
queue: &wgpu::Queue,
136-
_bounds: Rectangle,
137-
target_size: Size<u32>,
138-
_scale_factor: f32,
135+
format: wgpu::TextureFormat,
139136
storage: &mut shader::Storage,
137+
_bounds: &Rectangle,
138+
viewport: &Viewport,
140139
) {
141140
if !storage.has::<Pipeline>() {
142-
storage.store(Pipeline::new(device, queue, format, target_size));
141+
storage.store(Pipeline::new(
142+
device,
143+
queue,
144+
format,
145+
viewport.physical_size(),
146+
));
143147
}
144148

145149
let pipeline = storage.get_mut::<Pipeline>().unwrap();
146150

147-
//upload data to GPU
151+
// Upload data to GPU
148152
pipeline.update(
149153
device,
150154
queue,
151-
target_size,
155+
viewport.physical_size(),
152156
&self.uniforms,
153157
self.cubes.len(),
154158
&self.cubes,
@@ -157,20 +161,19 @@ impl shader::Primitive for Primitive {
157161

158162
fn render(
159163
&self,
164+
encoder: &mut wgpu::CommandEncoder,
160165
storage: &shader::Storage,
161166
target: &wgpu::TextureView,
162-
_target_size: Size<u32>,
163-
viewport: Rectangle<u32>,
164-
encoder: &mut wgpu::CommandEncoder,
167+
clip_bounds: &Rectangle<u32>,
165168
) {
166-
//at this point our pipeline should always be initialized
169+
// At this point our pipeline should always be initialized
167170
let pipeline = storage.get::<Pipeline>().unwrap();
168171

169-
//render primitive
172+
// Render primitive
170173
pipeline.render(
171174
target,
172175
encoder,
173-
viewport,
176+
*clip_bounds,
174177
self.cubes.len() as u32,
175178
self.show_depth_buffer,
176179
);

0 commit comments

Comments
 (0)