Skip to content

Commit

Permalink
Merge pull request #2382 from iced-rs/wgpu/better-architecture
Browse files Browse the repository at this point in the history
Improved architecture for `iced_wgpu` and `iced_tiny_skia`
  • Loading branch information
hecrj authored Apr 14, 2024
2 parents ee105e3 + dbbbadf commit 105b8bd
Show file tree
Hide file tree
Showing 67 changed files with 4,848 additions and 4,158 deletions.
2 changes: 1 addition & 1 deletion .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[alias]
lint = "clippy --workspace --no-deps -- -D warnings"
lint = "clippy --workspace --benches --all-features --no-deps -- -D warnings"
16 changes: 8 additions & 8 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
name: Check
on: [push, pull_request]
jobs:
widget:
runs-on: ubuntu-latest
steps:
- uses: hecrj/setup-rust-action@v2
- uses: actions/checkout@master
- name: Check standalone `iced_widget` crate
run: cargo check --package iced_widget --features image,svg,canvas

wasm:
runs-on: ubuntu-latest
env:
Expand All @@ -27,3 +19,11 @@ jobs:
run: cargo build --package todos --target wasm32-unknown-unknown
- name: Check compilation of `integration` example
run: cargo build --package integration --target wasm32-unknown-unknown

widget:
runs-on: ubuntu-latest
steps:
- uses: hecrj/setup-rust-action@v2
- uses: actions/checkout@master
- name: Check standalone `iced_widget` crate
run: cargo check --package iced_widget --features image,svg,canvas
58 changes: 22 additions & 36 deletions benches/wgpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,15 @@ use iced_wgpu::Renderer;
criterion_main!(benches);
criterion_group!(benches, wgpu_benchmark);

#[allow(unused_results)]
pub fn wgpu_benchmark(c: &mut Criterion) {
let _ = c
.bench_function("wgpu — canvas (light)", |b| benchmark(b, scene(10)));

let _ = c.bench_function("wgpu — canvas (heavy)", |b| {
benchmark(b, scene(1_000))
});
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>(
fn benchmark(
bencher: &mut Bencher<'_>,
widget: Element<'a, (), Theme, Renderer>,
widget: Element<'_, (), Theme, Renderer>,
) {
use iced_futures::futures::executor;
use iced_wgpu::graphics;
Expand Down Expand Up @@ -58,21 +55,15 @@ fn benchmark<'a>(

let format = wgpu::TextureFormat::Bgra8UnormSrgb;

let backend = iced_wgpu::Backend::new(
let mut engine = iced_wgpu::Engine::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,
Some(Antialiasing::MSAAx4),
);

let mut renderer = Renderer::new(backend, Font::DEFAULT, Pixels::from(16));
let mut renderer = Renderer::new(&engine, Font::DEFAULT, Pixels::from(16));

let viewport =
graphics::Viewport::with_physical_size(Size::new(3840, 2160), 2.0);
Expand Down Expand Up @@ -117,25 +108,20 @@ fn benchmark<'a>(
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));
});
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));
});
}

Expand Down
47 changes: 31 additions & 16 deletions core/src/rectangle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,32 @@ pub struct Rectangle<T = f32> {
pub height: T,
}

impl Rectangle<f32> {
/// Creates a new [`Rectangle`] with its top-left corner in the given
/// [`Point`] and with the provided [`Size`].
pub fn new(top_left: Point, size: Size) -> Self {
impl<T> Rectangle<T>
where
T: Default,
{
/// Creates a new [`Rectangle`] with its top-left corner at the origin
/// and with the provided [`Size`].
pub fn with_size(size: Size<T>) -> Self {
Self {
x: top_left.x,
y: top_left.y,
x: T::default(),
y: T::default(),
width: size.width,
height: size.height,
}
}
}

/// Creates a new [`Rectangle`] with its top-left corner at the origin
/// and with the provided [`Size`].
pub fn with_size(size: Size) -> Self {
impl Rectangle<f32> {
/// A rectangle starting at [`Point::ORIGIN`] with infinite width and height.
pub const INFINITE: Self = Self::new(Point::ORIGIN, Size::INFINITY);

/// Creates a new [`Rectangle`] with its top-left corner in the given
/// [`Point`] and with the provided [`Size`].
pub const fn new(top_left: Point, size: Size) -> Self {
Self {
x: 0.0,
y: 0.0,
x: top_left.x,
y: top_left.y,
width: size.width,
height: size.height,
}
Expand Down Expand Up @@ -139,13 +147,20 @@ impl Rectangle<f32> {
}

/// Snaps the [`Rectangle`] to __unsigned__ integer coordinates.
pub fn snap(self) -> Rectangle<u32> {
Rectangle {
pub fn snap(self) -> Option<Rectangle<u32>> {
let width = self.width as u32;
let height = self.height as u32;

if width < 1 || height < 1 {
return None;
}

Some(Rectangle {
x: self.x as u32,
y: self.y as u32,
width: self.width as u32,
height: self.height as u32,
}
width,
height,
})
}

/// Expands the [`Rectangle`] a given amount.
Expand Down
16 changes: 8 additions & 8 deletions core/src/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,39 @@ use crate::{
/// A component that can be used by widgets to draw themselves on a screen.
pub trait Renderer {
/// Starts recording a new layer.
fn start_layer(&mut self);
fn start_layer(&mut self, bounds: Rectangle);

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

/// Draws the primitives recorded in the given closure in a new layer.
///
/// The layer will clip its contents to the provided `bounds`.
fn with_layer(&mut self, bounds: Rectangle, f: impl FnOnce(&mut Self)) {
self.start_layer();
self.start_layer(bounds);
f(self);
self.end_layer(bounds);
self.end_layer();
}

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

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

/// Applies a [`Transformation`] to the primitives recorded in the given closure.
fn with_transformation(
&mut self,
transformation: Transformation,
f: impl FnOnce(&mut Self),
) {
self.start_transformation();
self.start_transformation(transformation);
f(self);
self.end_transformation(transformation);
self.end_transformation();
}

/// Applies a translation to the primitives recorded in the given closure.
Expand Down
12 changes: 4 additions & 8 deletions core/src/renderer/null.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,14 @@ use crate::{
Background, Color, Font, Pixels, Point, Rectangle, Size, Transformation,
};

use std::borrow::Cow;

impl Renderer for () {
fn start_layer(&mut self) {}
fn start_layer(&mut self, _bounds: Rectangle) {}

fn end_layer(&mut self, _bounds: Rectangle) {}
fn end_layer(&mut self) {}

fn start_transformation(&mut self) {}
fn start_transformation(&mut self, _transformation: Transformation) {}

fn end_transformation(&mut self, _transformation: Transformation) {}
fn end_transformation(&mut self) {}

fn clear(&mut self) {}

Expand Down Expand Up @@ -45,8 +43,6 @@ impl text::Renderer for () {
Pixels(16.0)
}

fn load_font(&mut self, _font: Cow<'static, [u8]>) {}

fn fill_paragraph(
&mut self,
_paragraph: &Self::Paragraph,
Expand Down
14 changes: 14 additions & 0 deletions core/src/size.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,17 @@ where
}
}
}

impl<T> std::ops::Mul<T> for Size<T>
where
T: std::ops::Mul<Output = T> + Copy,
{
type Output = Size<T>;

fn mul(self, rhs: T) -> Self::Output {
Size {
width: self.width * rhs,
height: self.height * rhs,
}
}
}
4 changes: 0 additions & 4 deletions core/src/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ pub use paragraph::Paragraph;
use crate::alignment;
use crate::{Color, Pixels, Point, Rectangle, Size};

use std::borrow::Cow;
use std::hash::{Hash, Hasher};

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

/// Loads a [`Self::Font`] from its bytes.
fn load_font(&mut self, font: Cow<'static, [u8]>);

/// Draws the given [`Paragraph`] at the given position and with the given
/// [`Color`].
fn fill_paragraph(
Expand Down
6 changes: 6 additions & 0 deletions core/src/transformation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ impl Transformation {
}
}

impl Default for Transformation {
fn default() -> Self {
Transformation::IDENTITY
}
}

impl Mul for Transformation {
type Output = Self;

Expand Down
33 changes: 18 additions & 15 deletions examples/custom_shader/src/scene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use pipeline::cube::{self, Cube};

use iced::mouse;
use iced::time::Duration;
use iced::widget::shader;
use iced::{Color, Rectangle, Size};
use iced::widget::shader::{self, Viewport};
use iced::{Color, Rectangle};

use glam::Vec3;
use rand::Rng;
Expand Down Expand Up @@ -130,25 +130,29 @@ impl Primitive {
impl shader::Primitive for Primitive {
fn prepare(
&self,
format: wgpu::TextureFormat,
device: &wgpu::Device,
queue: &wgpu::Queue,
_bounds: Rectangle,
target_size: Size<u32>,
_scale_factor: f32,
format: wgpu::TextureFormat,
storage: &mut shader::Storage,
_bounds: &Rectangle,
viewport: &Viewport,
) {
if !storage.has::<Pipeline>() {
storage.store(Pipeline::new(device, queue, format, target_size));
storage.store(Pipeline::new(
device,
queue,
format,
viewport.physical_size(),
));
}

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

//upload data to GPU
// Upload data to GPU
pipeline.update(
device,
queue,
target_size,
viewport.physical_size(),
&self.uniforms,
self.cubes.len(),
&self.cubes,
Expand All @@ -157,20 +161,19 @@ impl shader::Primitive for Primitive {

fn render(
&self,
encoder: &mut wgpu::CommandEncoder,
storage: &shader::Storage,
target: &wgpu::TextureView,
_target_size: Size<u32>,
viewport: Rectangle<u32>,
encoder: &mut wgpu::CommandEncoder,
clip_bounds: &Rectangle<u32>,
) {
//at this point our pipeline should always be initialized
// At this point our pipeline should always be initialized
let pipeline = storage.get::<Pipeline>().unwrap();

//render primitive
// Render primitive
pipeline.render(
target,
encoder,
viewport,
*clip_bounds,
self.cubes.len() as u32,
self.show_depth_buffer,
);
Expand Down
Loading

0 comments on commit 105b8bd

Please sign in to comment.