diff options
author | 2023-02-08 00:47:16 +0100 | |
---|---|---|
committer | 2023-02-24 13:37:31 +0100 | |
commit | 730d6a07564d014c470e02f233394ec98325d463 (patch) | |
tree | 531f0a7865058b1e9f17f8d6a67f75c301df00ce | |
parent | b8c1809ea101cece6943432fd3597f785c39af09 (diff) | |
download | iced-730d6a07564d014c470e02f233394ec98325d463.tar.gz iced-730d6a07564d014c470e02f233394ec98325d463.tar.bz2 iced-730d6a07564d014c470e02f233394ec98325d463.zip |
Reuse a `RenderPass` as much as possible in `iced_wgpu`
Diffstat (limited to '')
-rw-r--r-- | examples/integration/src/main.rs | 1 | ||||
-rw-r--r-- | wgpu/Cargo.toml | 5 | ||||
-rw-r--r-- | wgpu/src/backend.rs | 261 | ||||
-rw-r--r-- | wgpu/src/image.rs | 10 | ||||
-rw-r--r-- | wgpu/src/quad.rs | 10 | ||||
-rw-r--r-- | wgpu/src/text.rs | 40 | ||||
-rw-r--r-- | wgpu/src/triangle.rs | 10 | ||||
-rw-r--r-- | wgpu/src/window/compositor.rs | 29 |
8 files changed, 196 insertions, 170 deletions
diff --git a/examples/integration/src/main.rs b/examples/integration/src/main.rs index 5af30ab1..a7a90ced 100644 --- a/examples/integration/src/main.rs +++ b/examples/integration/src/main.rs @@ -250,6 +250,7 @@ pub fn main() { &device, &queue, &mut encoder, + None, &view, primitive, &viewport, diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index b3fbfc00..7a6b75f0 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -59,8 +59,9 @@ path = "../graphics" [dependencies.glyphon] version = "0.2" -git = "https://github.com/hecrj/glyphon.git" -rev = "3c2acb9dea5b9fcb0fa650b3c73b3a3242c62f4a" +# git = "https://github.com/hecrj/glyphon.git" +# rev = "3c2acb9dea5b9fcb0fa650b3c73b3a3242c62f4a" +path = "../../glyphon" [dependencies.tracing] version = "0.1.6" diff --git a/wgpu/src/backend.rs b/wgpu/src/backend.rs index 8c4c0daa..9d1e3d1c 100644 --- a/wgpu/src/backend.rs +++ b/wgpu/src/backend.rs @@ -5,8 +5,7 @@ use crate::{Settings, Transformation}; use iced_graphics::backend; use iced_graphics::layer::Layer; -use iced_graphics::{Primitive, Viewport}; -use iced_native::{Font, Size}; +use iced_graphics::{Color, Font, Primitive, Size, Viewport}; #[cfg(feature = "tracing")] use tracing::info_span; @@ -71,6 +70,7 @@ impl Backend { device: &wgpu::Device, queue: &wgpu::Queue, encoder: &mut wgpu::CommandEncoder, + clear_color: Option<Color>, frame: &wgpu::TextureView, primitives: &[Primitive], viewport: &Viewport, @@ -87,18 +87,25 @@ impl Backend { let mut layers = Layer::generate(primitives, viewport); layers.push(Layer::overlay(overlay_text, viewport)); - for layer in layers { - self.flush( - device, - queue, - scale_factor, - transformation, - &layer, - encoder, - frame, - target_size, - ); - } + self.prepare( + device, + queue, + encoder, + scale_factor, + transformation, + target_size, + &layers, + ); + + self.render( + device, + encoder, + frame, + clear_color, + scale_factor, + target_size, + &layers, + ); self.quad_pipeline.end_frame(); self.text_pipeline.end_frame(); @@ -108,90 +115,153 @@ impl Backend { self.image_pipeline.end_frame(device, queue, encoder); } - fn flush( + fn prepare( &mut self, device: &wgpu::Device, queue: &wgpu::Queue, + _encoder: &mut wgpu::CommandEncoder, scale_factor: f32, transformation: Transformation, - layer: &Layer<'_>, - encoder: &mut wgpu::CommandEncoder, - target: &wgpu::TextureView, target_size: Size<u32>, + layers: &[Layer<'_>], ) { - let bounds = (layer.bounds * scale_factor).snap(); + for layer in layers { + let bounds = (layer.bounds * scale_factor).snap(); - if bounds.width < 1 || bounds.height < 1 { - return; - } + if bounds.width < 1 || bounds.height < 1 { + return; + } - if !layer.quads.is_empty() { - self.quad_pipeline.prepare( - device, - queue, - &layer.quads, - transformation, - scale_factor, - ); - - let mut render_pass = - encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - label: Some("iced_wgpu::quad render pass"), - color_attachments: &[Some( - wgpu::RenderPassColorAttachment { - view: target, - resolve_target: None, - ops: wgpu::Operations { - load: wgpu::LoadOp::Load, - store: true, - }, - }, - )], - depth_stencil_attachment: None, - }); + if !layer.quads.is_empty() { + self.quad_pipeline.prepare( + device, + queue, + &layer.quads, + transformation, + scale_factor, + ); + } - self.quad_pipeline.render(bounds, &mut render_pass); - } + if !layer.meshes.is_empty() { + let scaled = transformation + * Transformation::scale(scale_factor, scale_factor); + + self.triangle_pipeline.prepare( + device, + queue, + &layer.meshes, + scaled, + ); + } - if !layer.meshes.is_empty() { - let scaled = transformation - * Transformation::scale(scale_factor, scale_factor); - - self.triangle_pipeline.prepare( - device, - queue, - &layer.meshes, - scaled, - ); - - self.triangle_pipeline.render( - device, - encoder, - target, - target_size, - &layer.meshes, - scale_factor, - ); + #[cfg(any(feature = "image", feature = "svg"))] + { + if !layer.images.is_empty() { + let scaled = transformation + * Transformation::scale(scale_factor, scale_factor); + + self.image_pipeline.prepare( + device, + queue, + _encoder, + &layer.images, + scaled, + scale_factor, + ); + } + } + + if !layer.text.is_empty() { + self.text_pipeline.prepare( + device, + queue, + &layer.text, + layer.bounds, + scale_factor, + target_size, + ); + } } + } + fn render( + &mut self, + device: &wgpu::Device, + encoder: &mut wgpu::CommandEncoder, + target: &wgpu::TextureView, + clear_color: Option<Color>, + scale_factor: f32, + target_size: Size<u32>, + layers: &[Layer<'_>], + ) { + use std::mem::ManuallyDrop; + + let mut quad_layer = 0; + let mut triangle_layer = 0; #[cfg(any(feature = "image", feature = "svg"))] - { - if !layer.images.is_empty() { - let scaled = transformation - * Transformation::scale(scale_factor, scale_factor); + let mut image_layer = 0; + let mut text_layer = 0; + + let mut render_pass = ManuallyDrop::new(encoder.begin_render_pass( + &wgpu::RenderPassDescriptor { + label: Some("iced_wgpu::quad render pass"), + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: target, + resolve_target: None, + ops: wgpu::Operations { + load: match clear_color { + Some(background_color) => wgpu::LoadOp::Clear({ + let [r, g, b, a] = + background_color.into_linear(); + + wgpu::Color { + r: f64::from(r), + g: f64::from(g), + b: f64::from(b), + a: f64::from(a), + } + }), + None => wgpu::LoadOp::Load, + }, + store: true, + }, + })], + depth_stencil_attachment: None, + }, + )); + + for layer in layers { + let bounds = (layer.bounds * scale_factor).snap(); - self.image_pipeline.prepare( + if bounds.width < 1 || bounds.height < 1 { + return; + } + + if !layer.quads.is_empty() { + self.quad_pipeline + .render(quad_layer, bounds, &mut render_pass); + + quad_layer += 1; + } + + if !layer.meshes.is_empty() { + let _ = ManuallyDrop::into_inner(render_pass); + + self.triangle_pipeline.render( device, - queue, encoder, - &layer.images, - scaled, + target, + triangle_layer, + target_size, + &layer.meshes, scale_factor, ); - let mut render_pass = - encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - label: Some("iced_wgpu::image render pass"), + triangle_layer += 1; + + render_pass = ManuallyDrop::new(encoder.begin_render_pass( + &wgpu::RenderPassDescriptor { + label: Some("iced_wgpu::quad render pass"), color_attachments: &[Some( wgpu::RenderPassColorAttachment { view: target, @@ -203,24 +273,31 @@ impl Backend { }, )], depth_stencil_attachment: None, - }); + }, + )); + } - self.image_pipeline.render(bounds, &mut render_pass); + #[cfg(any(feature = "image", feature = "svg"))] + { + if !layer.images.is_empty() { + self.image_pipeline.render( + image_layer, + bounds, + &mut render_pass, + ); + + image_layer += 1; + } } - } - if !layer.text.is_empty() { - self.text_pipeline.prepare( - device, - queue, - &layer.text, - layer.bounds, - scale_factor, - target_size, - ); - - self.text_pipeline.render(encoder, target); + if !layer.text.is_empty() { + self.text_pipeline.render(text_layer, &mut render_pass); + + text_layer += 1; + } } + + let _ = ManuallyDrop::into_inner(render_pass); } } diff --git a/wgpu/src/image.rs b/wgpu/src/image.rs index 5d1ae8d7..db05d2ff 100644 --- a/wgpu/src/image.rs +++ b/wgpu/src/image.rs @@ -45,7 +45,6 @@ pub struct Pipeline { layers: Vec<Layer>, prepare_layer: usize, - render_layer: usize, } #[derive(Debug)] @@ -321,7 +320,6 @@ impl Pipeline { layers: Vec::new(), prepare_layer: 0, - render_layer: 0, } } @@ -452,11 +450,12 @@ impl Pipeline { } pub fn render<'a>( - &'a mut self, + &'a self, + layer: usize, bounds: Rectangle<u32>, render_pass: &mut wgpu::RenderPass<'a>, ) { - if let Some(layer) = self.layers.get(self.render_layer) { + if let Some(layer) = self.layers.get(layer) { render_pass.set_pipeline(&self.pipeline); render_pass.set_scissor_rect( @@ -474,8 +473,6 @@ impl Pipeline { render_pass.set_vertex_buffer(0, self.vertices.slice(..)); layer.render(render_pass); - - self.render_layer += 1; } } @@ -496,7 +493,6 @@ impl Pipeline { .trim(&mut self.texture_atlas, &mut (device, queue, encoder)); self.prepare_layer = 0; - self.render_layer = 0; } } diff --git a/wgpu/src/quad.rs b/wgpu/src/quad.rs index c1aa49c4..246cc5e1 100644 --- a/wgpu/src/quad.rs +++ b/wgpu/src/quad.rs @@ -17,7 +17,6 @@ pub struct Pipeline { indices: wgpu::Buffer, layers: Vec<Layer>, prepare_layer: usize, - render_layer: usize, } impl Pipeline { @@ -140,7 +139,6 @@ impl Pipeline { indices, layers: Vec::new(), prepare_layer: 0, - render_layer: 0, } } @@ -163,11 +161,12 @@ impl Pipeline { } pub fn render<'a>( - &'a mut self, + &'a self, + layer: usize, bounds: Rectangle<u32>, render_pass: &mut wgpu::RenderPass<'a>, ) { - if let Some(layer) = self.layers.get(self.render_layer) { + if let Some(layer) = self.layers.get(layer) { render_pass.set_pipeline(&self.pipeline); render_pass.set_scissor_rect( @@ -184,14 +183,11 @@ impl Pipeline { render_pass.set_vertex_buffer(0, self.vertices.slice(..)); layer.draw(render_pass); - - self.render_layer += 1; } } pub fn end_frame(&mut self) { self.prepare_layer = 0; - self.render_layer = 0; } } diff --git a/wgpu/src/text.rs b/wgpu/src/text.rs index 95994a4e..73708fd8 100644 --- a/wgpu/src/text.rs +++ b/wgpu/src/text.rs @@ -16,7 +16,7 @@ pub struct Pipeline { system: Option<System>, renderers: Vec<glyphon::TextRenderer>, atlas: glyphon::TextAtlas, - layer: usize, + prepare_layer: usize, } #[ouroboros::self_referencing] @@ -55,7 +55,7 @@ impl Pipeline { ), renderers: Vec::new(), atlas: glyphon::TextAtlas::new(device, queue, format), - layer: 0, + prepare_layer: 0, } } @@ -88,12 +88,12 @@ impl Pipeline { target_size: Size<u32>, ) { self.system.as_mut().unwrap().with_mut(|fields| { - if self.renderers.len() <= self.layer { + if self.renderers.len() <= self.prepare_layer { self.renderers .push(glyphon::TextRenderer::new(device, queue)); } - let renderer = &mut self.renderers[self.layer]; + let renderer = &mut self.renderers[self.prepare_layer]; let keys: Vec<_> = sections .iter() @@ -179,35 +179,21 @@ impl Pipeline { &mut glyphon::SwashCache::new(fields.fonts), ) .expect("Prepare text sections"); + + self.prepare_layer += 1; }); } - pub fn render( - &mut self, - encoder: &mut wgpu::CommandEncoder, - target: &wgpu::TextureView, + pub fn render<'a>( + &'a self, + layer: usize, + render_pass: &mut wgpu::RenderPass<'a>, ) { - let mut render_pass = - encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - label: None, - color_attachments: &[Some(wgpu::RenderPassColorAttachment { - view: target, - resolve_target: None, - ops: wgpu::Operations { - load: wgpu::LoadOp::Load, - store: true, - }, - })], - depth_stencil_attachment: None, - }); - - let renderer = &mut self.renderers[self.layer]; + let renderer = &self.renderers[layer]; renderer - .render(&self.atlas, &mut render_pass) + .render(&self.atlas, render_pass) .expect("Render text"); - - self.layer += 1; } pub fn end_frame(&mut self) { @@ -216,7 +202,7 @@ impl Pipeline { .unwrap() .with_render_cache_mut(|cache| cache.trim()); - self.layer = 0; + self.prepare_layer = 0; } pub fn measure( diff --git a/wgpu/src/triangle.rs b/wgpu/src/triangle.rs index 572af1e8..1b537bf4 100644 --- a/wgpu/src/triangle.rs +++ b/wgpu/src/triangle.rs @@ -22,7 +22,6 @@ pub struct Pipeline { layers: Vec<Layer>, prepare_layer: usize, - render_layer: usize, } #[derive(Debug)] @@ -235,7 +234,7 @@ impl Layer { } fn render<'a>( - &'a mut self, + &'a self, solid: &'a solid::Pipeline, #[cfg(not(target_arch = "wasm32"))] gradient: &'a gradient::Pipeline, meshes: &[Mesh<'_>], @@ -331,7 +330,6 @@ impl Pipeline { layers: Vec::new(), prepare_layer: 0, - render_layer: 0, } } @@ -373,6 +371,7 @@ impl Pipeline { device: &wgpu::Device, encoder: &mut wgpu::CommandEncoder, target: &wgpu::TextureView, + layer: usize, target_size: Size<u32>, meshes: &[Mesh<'_>], scale_factor: f32, @@ -413,7 +412,7 @@ impl Pipeline { depth_stencil_attachment: None, }); - let layer = &mut self.layers[self.render_layer]; + let layer = &mut self.layers[layer]; layer.render( &self.solid, @@ -425,8 +424,6 @@ impl Pipeline { ); } - self.render_layer += 1; - if let Some(blit) = &mut self.blit { blit.draw(encoder, target); } @@ -434,7 +431,6 @@ impl Pipeline { pub fn end_frame(&mut self) { self.prepare_layer = 0; - self.render_layer = 0; } } diff --git a/wgpu/src/window/compositor.rs b/wgpu/src/window/compositor.rs index 6e1acc06..365cb603 100644 --- a/wgpu/src/window/compositor.rs +++ b/wgpu/src/window/compositor.rs @@ -190,39 +190,12 @@ impl<Theme> iced_graphics::window::Compositor for Compositor<Theme> { .texture .create_view(&wgpu::TextureViewDescriptor::default()); - let _ = - encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - label: Some( - "iced_wgpu::window::Compositor render pass", - ), - color_attachments: &[Some( - wgpu::RenderPassColorAttachment { - view, - resolve_target: None, - ops: wgpu::Operations { - load: wgpu::LoadOp::Clear({ - let [r, g, b, a] = - background_color.into_linear(); - - wgpu::Color { - r: f64::from(r), - g: f64::from(g), - b: f64::from(b), - a: f64::from(a), - } - }), - store: true, - }, - }, - )], - depth_stencil_attachment: None, - }); - renderer.with_primitives(|backend, primitives| { backend.present( &self.device, &self.queue, &mut encoder, + Some(background_color), view, primitives, viewport, |