diff options
author | 2020-02-12 08:49:42 +0100 | |
---|---|---|
committer | 2020-02-12 08:49:42 +0100 | |
commit | 578ea4abb8a2dd0d53d7087322796bf9ad541b56 (patch) | |
tree | be684d9262fbf1ae0c5fc2db469d74ab0a5a98c4 /wgpu/src | |
parent | f34407bfdaf06c4bf204dc31b152be9451c243b8 (diff) | |
download | iced-578ea4abb8a2dd0d53d7087322796bf9ad541b56.tar.gz iced-578ea4abb8a2dd0d53d7087322796bf9ad541b56.tar.bz2 iced-578ea4abb8a2dd0d53d7087322796bf9ad541b56.zip |
Finish `clock` example
Diffstat (limited to 'wgpu/src')
-rw-r--r-- | wgpu/src/primitive.rs | 10 | ||||
-rw-r--r-- | wgpu/src/renderer.rs | 12 | ||||
-rw-r--r-- | wgpu/src/shader/triangle.vert | 4 | ||||
-rw-r--r-- | wgpu/src/shader/triangle.vert.spv | bin | 1468 -> 1256 bytes | |||
-rw-r--r-- | wgpu/src/triangle.rs | 80 | ||||
-rw-r--r-- | wgpu/src/widget/canvas.rs | 21 | ||||
-rw-r--r-- | wgpu/src/widget/canvas/frame.rs | 19 | ||||
-rw-r--r-- | wgpu/src/widget/canvas/layer.rs | 63 | ||||
-rw-r--r-- | wgpu/src/widget/canvas/path.rs | 2 |
9 files changed, 142 insertions, 69 deletions
diff --git a/wgpu/src/primitive.rs b/wgpu/src/primitive.rs index 481252ef..823b4b72 100644 --- a/wgpu/src/primitive.rs +++ b/wgpu/src/primitive.rs @@ -1,5 +1,5 @@ use iced_native::{ - image, svg, Background, Color, Font, HorizontalAlignment, Rectangle, + image, svg, Background, Color, Font, HorizontalAlignment, Point, Rectangle, Vector, VerticalAlignment, }; @@ -73,7 +73,13 @@ pub enum Primitive { /// A low-level primitive to render a mesh of triangles. /// /// It can be used to render many kinds of geometry freely. - Mesh2D(Arc<triangle::Mesh2D>), + Mesh2D { + /// The top-left coordinate of the mesh + origin: Point, + + /// The vertex and index buffers of the mesh + buffers: Arc<triangle::Mesh2D>, + }, } impl Default for Primitive { diff --git a/wgpu/src/renderer.rs b/wgpu/src/renderer.rs index e93090b8..25b2e99a 100644 --- a/wgpu/src/renderer.rs +++ b/wgpu/src/renderer.rs @@ -26,7 +26,7 @@ struct Layer<'a> { offset: Vector<u32>, quads: Vec<Quad>, images: Vec<Image>, - meshes: Vec<Arc<triangle::Mesh2D>>, + meshes: Vec<(Point, Arc<triangle::Mesh2D>)>, text: Vec<wgpu_glyph::Section<'a>>, } @@ -229,8 +229,8 @@ impl Renderer { scale: [bounds.width, bounds.height], }); } - Primitive::Mesh2D(mesh) => { - layer.meshes.push(mesh.clone()); + Primitive::Mesh2D { origin, buffers } => { + layer.meshes.push((*origin, buffers.clone())); } Primitive::Clip { bounds, @@ -313,9 +313,10 @@ impl Renderer { if layer.meshes.len() > 0 { let translated = transformation + * Transformation::scale(scale_factor, scale_factor) * Transformation::translate( - -(layer.offset.x as f32) * scale_factor, - -(layer.offset.y as f32) * scale_factor, + -(layer.offset.x as f32), + -(layer.offset.y as f32), ); self.triangle_pipeline.draw( @@ -323,7 +324,6 @@ impl Renderer { encoder, target, translated, - scale_factor, &layer.meshes, bounds, ); diff --git a/wgpu/src/shader/triangle.vert b/wgpu/src/shader/triangle.vert index fd86ecd6..1f2c009b 100644 --- a/wgpu/src/shader/triangle.vert +++ b/wgpu/src/shader/triangle.vert @@ -7,11 +7,9 @@ layout(location = 0) out vec4 o_Color; layout (set = 0, binding = 0) uniform Globals { mat4 u_Transform; - float u_Scale; }; void main() { - vec2 p_Position = i_Position * u_Scale; - gl_Position = u_Transform * vec4(p_Position, 0.0, 1.0); + gl_Position = u_Transform * vec4(i_Position, 0.0, 1.0); o_Color = i_Color; } diff --git a/wgpu/src/shader/triangle.vert.spv b/wgpu/src/shader/triangle.vert.spv Binary files differindex bc39c451..871f4f55 100644 --- a/wgpu/src/shader/triangle.vert.spv +++ b/wgpu/src/shader/triangle.vert.spv diff --git a/wgpu/src/triangle.rs b/wgpu/src/triangle.rs index 38157d00..6f3adbe4 100644 --- a/wgpu/src/triangle.rs +++ b/wgpu/src/triangle.rs @@ -1,6 +1,6 @@ //! Draw meshes of triangles. use crate::Transformation; -use iced_native::Rectangle; +use iced_native::{Point, Rectangle}; use std::{mem, sync::Arc}; #[derive(Debug)] @@ -128,47 +128,28 @@ impl Pipeline { encoder: &mut wgpu::CommandEncoder, target: &wgpu::TextureView, transformation: Transformation, - scale: f32, - meshes: &Vec<Arc<Mesh2D>>, + meshes: &Vec<(Point, Arc<Mesh2D>)>, bounds: Rectangle<u32>, ) { - let uniforms = Uniforms { - transform: transformation.into(), - scale, - }; - - let constants_buffer = device - .create_buffer_mapped(1, wgpu::BufferUsage::COPY_SRC) - .fill_from_slice(&[uniforms]); - - encoder.copy_buffer_to_buffer( - &constants_buffer, - 0, - &self.constants_buffer, - 0, - std::mem::size_of::<Uniforms>() as u64, - ); - - let mut render_pass = - encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - color_attachments: &[ - wgpu::RenderPassColorAttachmentDescriptor { - attachment: target, - resolve_target: None, - load_op: wgpu::LoadOp::Load, - store_op: wgpu::StoreOp::Store, - clear_color: wgpu::Color { - r: 0.0, - g: 0.0, - b: 0.0, - a: 0.0, - }, - }, - ], - depth_stencil_attachment: None, - }); + for (origin, mesh) in meshes { + let uniforms = Uniforms { + transform: (transformation + * Transformation::translate(origin.x, origin.y)) + .into(), + }; + + let constants_buffer = device + .create_buffer_mapped(1, wgpu::BufferUsage::COPY_SRC) + .fill_from_slice(&[uniforms]); + + encoder.copy_buffer_to_buffer( + &constants_buffer, + 0, + &self.constants_buffer, + 0, + std::mem::size_of::<Uniforms>() as u64, + ); - for mesh in meshes { let vertices_buffer = device .create_buffer_mapped( mesh.vertices.len(), @@ -183,6 +164,25 @@ impl Pipeline { ) .fill_from_slice(&mesh.indices); + let mut render_pass = + encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + color_attachments: &[ + wgpu::RenderPassColorAttachmentDescriptor { + attachment: target, + resolve_target: None, + load_op: wgpu::LoadOp::Load, + store_op: wgpu::StoreOp::Store, + clear_color: wgpu::Color { + r: 0.0, + g: 0.0, + b: 0.0, + a: 0.0, + }, + }, + ], + depth_stencil_attachment: None, + }); + render_pass.set_pipeline(&self.pipeline); render_pass.set_bind_group(0, &self.constants, &[]); render_pass.set_index_buffer(&indices_buffer, 0); @@ -203,14 +203,12 @@ impl Pipeline { #[derive(Debug, Clone, Copy)] struct Uniforms { transform: [f32; 16], - scale: f32, } impl Default for Uniforms { fn default() -> Self { Self { transform: *Transformation::identity().as_ref(), - scale: 1.0, } } } diff --git a/wgpu/src/widget/canvas.rs b/wgpu/src/widget/canvas.rs index 6bfeed9a..c984fee9 100644 --- a/wgpu/src/widget/canvas.rs +++ b/wgpu/src/widget/canvas.rs @@ -68,7 +68,6 @@ impl<'a, Message> Widget<Message, Renderer> for Canvas<'a> { limits: &layout::Limits, ) -> layout::Node { let limits = limits.width(self.width).height(self.height); - let size = limits.resolve(Size::ZERO); layout::Node::new(size) @@ -78,10 +77,26 @@ impl<'a, Message> Widget<Message, Renderer> for Canvas<'a> { &self, _renderer: &mut Renderer, _defaults: &Defaults, - _layout: Layout<'_>, + layout: Layout<'_>, _cursor_position: Point, ) -> (Primitive, MouseCursor) { - (Primitive::None, MouseCursor::Idle) + let bounds = layout.bounds(); + let origin = Point::new(bounds.x, bounds.y); + let size = Size::new(bounds.width, bounds.height); + + ( + Primitive::Group { + primitives: self + .layers + .iter() + .map(|layer| Primitive::Mesh2D { + origin, + buffers: layer.draw(size), + }) + .collect(), + }, + MouseCursor::Idle, + ) } fn hash_layout(&self, state: &mut Hasher) { diff --git a/wgpu/src/widget/canvas/frame.rs b/wgpu/src/widget/canvas/frame.rs index 82ff526b..3c667426 100644 --- a/wgpu/src/widget/canvas/frame.rs +++ b/wgpu/src/widget/canvas/frame.rs @@ -7,13 +7,13 @@ use crate::{ #[derive(Debug)] pub struct Frame { - width: u32, - height: u32, + width: f32, + height: f32, buffers: lyon::tessellation::VertexBuffers<triangle::Vertex2D, u16>, } impl Frame { - pub(crate) fn new(width: u32, height: u32) -> Frame { + pub fn new(width: f32, height: f32) -> Frame { Frame { width, height, @@ -21,16 +21,16 @@ impl Frame { } } - pub fn width(&self) -> u32 { + pub fn width(&self) -> f32 { self.width } - pub fn height(&self) -> u32 { + pub fn height(&self) -> f32 { self.height } pub fn center(&self) -> Point { - Point::new(self.width as f32 / 2.0, self.height as f32 / 2.0) + Point::new(self.width / 2.0, self.height / 2.0) } pub fn fill(&mut self, path: &Path, fill: Fill) { @@ -74,6 +74,13 @@ impl Frame { .tessellate_path(path.raw(), &options, &mut buffers) .expect("Stroke path"); } + + pub fn into_mesh(self) -> triangle::Mesh2D { + triangle::Mesh2D { + vertices: self.buffers.vertices, + indices: self.buffers.indices, + } + } } struct FillVertex([f32; 4]); diff --git a/wgpu/src/widget/canvas/layer.rs b/wgpu/src/widget/canvas/layer.rs index f97634e4..c239a254 100644 --- a/wgpu/src/widget/canvas/layer.rs +++ b/wgpu/src/widget/canvas/layer.rs @@ -1,13 +1,28 @@ -use crate::canvas::Frame; +use crate::{canvas::Frame, triangle}; -pub trait Layer: std::fmt::Debug {} +use iced_native::Size; +use std::cell::RefCell; +use std::sync::Arc; + +pub trait Layer: std::fmt::Debug { + fn draw(&self, bounds: Size) -> Arc<triangle::Mesh2D>; +} use std::marker::PhantomData; -use std::sync::{Arc, Weak}; #[derive(Debug)] pub struct Cached<T: Drawable> { input: PhantomData<T>, + cache: RefCell<Cache>, +} + +#[derive(Debug)] +enum Cache { + Empty, + Filled { + mesh: Arc<triangle::Mesh2D>, + bounds: Size, + }, } impl<T> Cached<T> @@ -15,14 +30,19 @@ where T: Drawable + std::fmt::Debug, { pub fn new() -> Self { - Cached { input: PhantomData } + Cached { + input: PhantomData, + cache: RefCell::new(Cache::Empty), + } } - pub fn clear(&mut self) {} + pub fn clear(&mut self) { + *self.cache.borrow_mut() = Cache::Empty; + } pub fn with<'a>(&'a self, input: &'a T) -> impl Layer + 'a { Bind { - cache: self, + layer: self, input: input, } } @@ -30,11 +50,38 @@ where #[derive(Debug)] struct Bind<'a, T: Drawable> { - cache: &'a Cached<T>, + layer: &'a Cached<T>, input: &'a T, } -impl<'a, T> Layer for Bind<'a, T> where T: Drawable + std::fmt::Debug {} +impl<'a, T> Layer for Bind<'a, T> +where + T: Drawable + std::fmt::Debug, +{ + fn draw(&self, current_bounds: Size) -> Arc<triangle::Mesh2D> { + use std::ops::Deref; + + if let Cache::Filled { mesh, bounds } = + self.layer.cache.borrow().deref() + { + if *bounds == current_bounds { + return mesh.clone(); + } + } + + let mut frame = Frame::new(current_bounds.width, current_bounds.height); + self.input.draw(&mut frame); + + let mesh = Arc::new(frame.into_mesh()); + + *self.layer.cache.borrow_mut() = Cache::Filled { + mesh: mesh.clone(), + bounds: current_bounds, + }; + + mesh + } +} pub trait Drawable { fn draw(&self, frame: &mut Frame); diff --git a/wgpu/src/widget/canvas/path.rs b/wgpu/src/widget/canvas/path.rs index 96206256..c8ba10e1 100644 --- a/wgpu/src/widget/canvas/path.rs +++ b/wgpu/src/widget/canvas/path.rs @@ -58,6 +58,8 @@ impl Builder { sweep_angle: lyon::math::Angle::radians(ellipse.end_angle), }; + let _ = self.raw.move_to(arc.sample(0.0)); + arc.for_each_quadratic_bezier(&mut |curve| { let _ = self.raw.quadratic_bezier_to(curve.ctrl, curve.to); }); |