summaryrefslogtreecommitdiffstats
path: root/wgpu/src/lib.rs
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector@hecrj.dev>2024-04-05 23:59:21 +0200
committerLibravatar Héctor Ramón Jiménez <hector@hecrj.dev>2024-04-05 23:59:21 +0200
commit6d3e1d835e1688fbc58622a03a784ed25ed3f0e1 (patch)
treeb1a14b0ec7b2da4368d5c98850fe9e9eebc5490a /wgpu/src/lib.rs
parent4a356cfc16f3b45d64826732009d9feeac016b28 (diff)
downloadiced-6d3e1d835e1688fbc58622a03a784ed25ed3f0e1.tar.gz
iced-6d3e1d835e1688fbc58622a03a784ed25ed3f0e1.tar.bz2
iced-6d3e1d835e1688fbc58622a03a784ed25ed3f0e1.zip
Decouple caching from layering and simplify everything
Diffstat (limited to 'wgpu/src/lib.rs')
-rw-r--r--wgpu/src/lib.rs444
1 files changed, 132 insertions, 312 deletions
diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs
index 4705cfa0..d632919f 100644
--- a/wgpu/src/lib.rs
+++ b/wgpu/src/lib.rs
@@ -60,7 +60,7 @@ pub use iced_graphics::core;
pub use wgpu;
pub use engine::Engine;
-pub use layer::{Layer, LayerMut};
+pub use layer::Layer;
pub use primitive::Primitive;
pub use settings::Settings;
@@ -85,6 +85,9 @@ pub struct Renderer {
default_text_size: Pixels,
layers: layer::Stack,
+ triangle_storage: triangle::Storage,
+ text_storage: text::Storage,
+
// TODO: Centralize all the image feature handling
#[cfg(any(feature = "svg", feature = "image"))]
image_cache: image::cache::Shared,
@@ -97,6 +100,9 @@ impl Renderer {
default_text_size: settings.default_text_size,
layers: layer::Stack::new(),
+ triangle_storage: triangle::Storage::new(),
+ text_storage: text::Storage::new(),
+
#[cfg(any(feature = "svg", feature = "image"))]
image_cache: _engine.image_cache().clone(),
}
@@ -117,9 +123,11 @@ impl Renderer {
overlay: &[T],
) {
self.draw_overlay(overlay, viewport);
-
self.prepare(engine, device, queue, format, encoder, viewport);
self.render(engine, device, encoder, frame, clear_color, viewport);
+
+ self.triangle_storage.trim();
+ self.text_storage.trim();
}
fn prepare(
@@ -134,116 +142,51 @@ impl Renderer {
let scale_factor = viewport.scale_factor() as f32;
for layer in self.layers.iter_mut() {
- match layer {
- LayerMut::Live(live) => {
- if !live.quads.is_empty() {
- engine.quad_pipeline.prepare_batch(
- device,
- encoder,
- &mut engine.staging_belt,
- &live.quads,
- viewport.projection(),
- scale_factor,
- );
- }
-
- if !live.meshes.is_empty() {
- engine.triangle_pipeline.prepare_batch(
- device,
- encoder,
- &mut engine.staging_belt,
- &live.meshes,
- viewport.projection()
- * Transformation::scale(scale_factor),
- );
- }
-
- if !live.text.is_empty() {
- engine.text_pipeline.prepare_batch(
- device,
- queue,
- encoder,
- &live.text,
- live.bounds.unwrap_or(Rectangle::with_size(
- viewport.logical_size(),
- )),
- live.transformation
- * Transformation::scale(scale_factor),
- viewport.physical_size(),
- );
- }
-
- #[cfg(any(feature = "svg", feature = "image"))]
- if !live.images.is_empty() {
- engine.image_pipeline.prepare(
- device,
- encoder,
- &mut engine.staging_belt,
- &live.images,
- viewport.projection(),
- scale_factor,
- );
- }
- }
- LayerMut::Cached(layer_transformation, mut cached) => {
- if !cached.quads.is_empty() {
- engine.quad_pipeline.prepare_cache(
- device,
- encoder,
- &mut engine.staging_belt,
- &mut cached.quads,
- viewport.projection(),
- scale_factor,
- );
- }
-
- if !cached.meshes.is_empty() {
- let transformation =
- Transformation::scale(scale_factor)
- * layer_transformation;
-
- engine.triangle_pipeline.prepare_cache(
- device,
- encoder,
- &mut engine.staging_belt,
- &mut cached.meshes,
- viewport.projection(),
- transformation,
- );
- }
-
- if !cached.text.is_empty() {
- let bounds = cached.bounds.unwrap_or(
- Rectangle::with_size(viewport.logical_size()),
- );
-
- let transformation =
- Transformation::scale(scale_factor)
- * layer_transformation;
-
- engine.text_pipeline.prepare_cache(
- device,
- queue,
- encoder,
- &mut cached.text,
- bounds,
- transformation,
- viewport.physical_size(),
- );
- }
-
- #[cfg(any(feature = "svg", feature = "image"))]
- if !cached.images.is_empty() {
- engine.image_pipeline.prepare(
- device,
- encoder,
- &mut engine.staging_belt,
- &cached.images,
- viewport.projection(),
- scale_factor,
- );
- }
- }
+ if !layer.quads.is_empty() {
+ engine.quad_pipeline.prepare(
+ device,
+ encoder,
+ &mut engine.staging_belt,
+ &layer.quads,
+ viewport.projection(),
+ scale_factor,
+ );
+ }
+
+ if !layer.triangles.is_empty() {
+ engine.triangle_pipeline.prepare(
+ device,
+ encoder,
+ &mut engine.staging_belt,
+ &mut self.triangle_storage,
+ &layer.triangles,
+ viewport.projection() * Transformation::scale(scale_factor),
+ );
+ }
+
+ if !layer.text.is_empty() {
+ engine.text_pipeline.prepare(
+ device,
+ queue,
+ encoder,
+ &mut self.text_storage,
+ &layer.text,
+ layer.bounds,
+ Transformation::scale(scale_factor),
+ viewport.physical_size(),
+ );
+ }
+
+ #[cfg(any(feature = "svg", feature = "image"))]
+ if !layer.images.is_empty() {
+ engine.image_pipeline.prepare(
+ device,
+ encoder,
+ &mut engine.staging_belt,
+ &layer.images,
+ viewport.projection(),
+ scale_factor,
+ );
}
}
}
@@ -297,208 +240,87 @@ impl Renderer {
#[cfg(any(feature = "svg", feature = "image"))]
let mut image_layer = 0;
- // TODO: Can we avoid collecting here?
let scale_factor = viewport.scale_factor() as f32;
- let screen_bounds = Rectangle::with_size(viewport.logical_size());
let physical_bounds = Rectangle::<f32>::from(Rectangle::with_size(
viewport.physical_size(),
));
- let layers: Vec<_> = self.layers.iter().collect();
- let mut i = 0;
+ let scale = Transformation::scale(scale_factor);
- // println!("RENDER");
+ for layer in self.layers.iter() {
+ let Some(physical_bounds) =
+ physical_bounds.intersection(&(layer.bounds * scale))
+ else {
+ continue;
+ };
- while i < layers.len() {
- match layers[i] {
- Layer::Live(live) => {
- let layer_transformation =
- Transformation::scale(scale_factor)
- * live.transformation;
+ let scissor_rect = physical_bounds.snap();
- let layer_bounds = live.bounds.unwrap_or(screen_bounds);
+ if !layer.quads.is_empty() {
+ engine.quad_pipeline.render(
+ quad_layer,
+ scissor_rect,
+ &layer.quads,
+ &mut render_pass,
+ );
- let Some(physical_bounds) = physical_bounds
- .intersection(&(layer_bounds * layer_transformation))
- .map(Rectangle::snap)
- else {
- continue;
- };
+ quad_layer += 1;
+ }
- if !live.quads.is_empty() {
- engine.quad_pipeline.render_batch(
- quad_layer,
- physical_bounds,
- &live.quads,
- &mut render_pass,
- );
-
- quad_layer += 1;
- }
-
- if !live.meshes.is_empty() {
- // println!("LIVE PASS");
- let _ = ManuallyDrop::into_inner(render_pass);
-
- engine.triangle_pipeline.render_batch(
- device,
- encoder,
- frame,
- mesh_layer,
- viewport.physical_size(),
- &live.meshes,
- physical_bounds,
- &layer_transformation,
- );
-
- mesh_layer += 1;
-
- render_pass =
- ManuallyDrop::new(encoder.begin_render_pass(
- &wgpu::RenderPassDescriptor {
- label: Some("iced_wgpu render pass"),
- color_attachments: &[Some(
- wgpu::RenderPassColorAttachment {
- view: frame,
- resolve_target: None,
- ops: wgpu::Operations {
- load: wgpu::LoadOp::Load,
- store: wgpu::StoreOp::Store,
- },
- },
- )],
- depth_stencil_attachment: None,
- timestamp_writes: None,
- occlusion_query_set: None,
- },
- ));
- }
-
- if !live.text.is_empty() {
- engine.text_pipeline.render_batch(
- text_layer,
- physical_bounds,
- &mut render_pass,
- );
-
- text_layer += 1;
- }
-
- #[cfg(any(feature = "svg", feature = "image"))]
- if !live.images.is_empty() {
- engine.image_pipeline.render(
- image_layer,
- physical_bounds,
- &mut render_pass,
- );
-
- image_layer += 1;
- }
-
- i += 1;
- }
- Layer::Cached(_, _) => {
- let group_len = layers[i..]
- .iter()
- .position(|layer| matches!(layer, Layer::Live(_)))
- .unwrap_or(layers.len() - i);
-
- let group =
- layers[i..i + group_len].iter().filter_map(|layer| {
- let Layer::Cached(transformation, cached) = layer
- else {
- unreachable!()
- };
-
- let physical_bounds = cached
- .bounds
- .and_then(|bounds| {
- physical_bounds.intersection(
- &(bounds
- * *transformation
- * Transformation::scale(
- scale_factor,
- )),
- )
- })
- .unwrap_or(physical_bounds)
- .snap();
-
- Some((cached, physical_bounds))
- });
-
- for (cached, bounds) in group.clone() {
- if !cached.quads.is_empty() {
- engine.quad_pipeline.render_cache(
- &cached.quads,
- bounds,
- &mut render_pass,
- );
- }
- }
-
- let group_has_meshes = group
- .clone()
- .any(|(cached, _)| !cached.meshes.is_empty());
-
- if group_has_meshes {
- // println!("CACHE PASS");
- let _ = ManuallyDrop::into_inner(render_pass);
-
- engine.triangle_pipeline.render_cache_group(
- device,
- encoder,
- frame,
- viewport.physical_size(),
- group.clone().map(|(cached, bounds)| {
- (&cached.meshes, bounds)
- }),
- );
-
- render_pass =
- ManuallyDrop::new(encoder.begin_render_pass(
- &wgpu::RenderPassDescriptor {
- label: Some("iced_wgpu render pass"),
- color_attachments: &[Some(
- wgpu::RenderPassColorAttachment {
- view: frame,
- resolve_target: None,
- ops: wgpu::Operations {
- load: wgpu::LoadOp::Load,
- store: wgpu::StoreOp::Store,
- },
- },
- )],
- depth_stencil_attachment: None,
- timestamp_writes: None,
- occlusion_query_set: None,
+ if !layer.triangles.is_empty() {
+ let _ = ManuallyDrop::into_inner(render_pass);
+
+ mesh_layer += engine.triangle_pipeline.render(
+ device,
+ encoder,
+ frame,
+ &self.triangle_storage,
+ mesh_layer,
+ &layer.triangles,
+ viewport.physical_size(),
+ physical_bounds,
+ scale,
+ );
+
+ render_pass = ManuallyDrop::new(encoder.begin_render_pass(
+ &wgpu::RenderPassDescriptor {
+ label: Some("iced_wgpu render pass"),
+ color_attachments: &[Some(
+ wgpu::RenderPassColorAttachment {
+ view: frame,
+ resolve_target: None,
+ ops: wgpu::Operations {
+ load: wgpu::LoadOp::Load,
+ store: wgpu::StoreOp::Store,
},
- ));
- }
-
- for (cached, bounds) in group {
- if !cached.text.is_empty() {
- engine.text_pipeline.render_cache(
- &cached.text,
- bounds,
- &mut render_pass,
- );
- }
-
- #[cfg(any(feature = "svg", feature = "image"))]
- if !cached.images.is_empty() {
- engine.image_pipeline.render(
- image_layer,
- bounds,
- &mut render_pass,
- );
-
- image_layer += 1;
- }
- }
-
- i += group_len;
- }
+ },
+ )],
+ depth_stencil_attachment: None,
+ timestamp_writes: None,
+ occlusion_query_set: None,
+ },
+ ));
+ }
+
+ if !layer.text.is_empty() {
+ text_layer += engine.text_pipeline.render(
+ &self.text_storage,
+ text_layer,
+ &layer.text,
+ scissor_rect,
+ &mut render_pass,
+ );
+ }
+
+ #[cfg(any(feature = "svg", feature = "image"))]
+ if !layer.images.is_empty() {
+ engine.image_pipeline.render(
+ image_layer,
+ scissor_rect,
+ &mut render_pass,
+ );
+
+ image_layer += 1;
}
}
@@ -552,7 +374,7 @@ impl Renderer {
impl core::Renderer for Renderer {
fn start_layer(&mut self, bounds: Rectangle) {
- self.layers.push_clip(Some(bounds));
+ self.layers.push_clip(bounds);
}
fn end_layer(&mut self, _bounds: Rectangle) {
@@ -690,15 +512,13 @@ impl graphics::geometry::Renderer for Renderer {
fn draw_geometry(&mut self, geometry: Self::Geometry) {
match geometry {
- Geometry::Live(layers) => {
- for layer in layers {
- self.layers.draw_layer(layer);
- }
+ Geometry::Live { meshes, text } => {
+ self.layers.draw_mesh_group(meshes);
+ self.layers.draw_text_group(text);
}
- Geometry::Cached(layers) => {
- for layer in layers.as_ref() {
- self.layers.draw_cached_layer(layer);
- }
+ Geometry::Cached(cache) => {
+ self.layers.draw_mesh_cache(cache.meshes);
+ self.layers.draw_text_cache(cache.text);
}
}
}