diff options
Diffstat (limited to 'wgpu')
| -rw-r--r-- | wgpu/src/lib.rs | 2 | ||||
| -rw-r--r-- | wgpu/src/primitive.rs | 7 | ||||
| -rw-r--r-- | wgpu/src/renderer.rs | 32 | ||||
| -rw-r--r-- | wgpu/src/shader/triangle.frag | 8 | ||||
| -rw-r--r-- | wgpu/src/shader/triangle.frag.spv | bin | 0 -> 372 bytes | |||
| -rw-r--r-- | wgpu/src/shader/triangle.vert | 17 | ||||
| -rw-r--r-- | wgpu/src/shader/triangle.vert.spv | bin | 0 -> 1468 bytes | |||
| -rw-r--r-- | wgpu/src/triangle.rs | 239 | 
8 files changed, 303 insertions, 2 deletions
diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 9f9ed8db..972f56af 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -24,6 +24,8 @@  #![deny(unused_results)]  #![deny(unsafe_code)]  #![deny(rust_2018_idioms)] +pub mod triangle; +  mod image;  mod primitive;  mod quad; diff --git a/wgpu/src/primitive.rs b/wgpu/src/primitive.rs index 6c61f800..815ba3b0 100644 --- a/wgpu/src/primitive.rs +++ b/wgpu/src/primitive.rs @@ -3,6 +3,9 @@ use iced_native::{      Vector, VerticalAlignment,  }; +use crate::triangle; +use std::sync::Arc; +  /// A rendering primitive.  #[derive(Debug, Clone)]  pub enum Primitive { @@ -63,6 +66,10 @@ pub enum Primitive {          /// The content of the clip          content: Box<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>),  }  impl Default for Primitive { diff --git a/wgpu/src/renderer.rs b/wgpu/src/renderer.rs index 365ef1ef..050daca9 100644 --- a/wgpu/src/renderer.rs +++ b/wgpu/src/renderer.rs @@ -1,9 +1,11 @@ -use crate::{image, quad, text, Image, Primitive, Quad, Transformation}; +use crate::{ +    image, quad, text, triangle, Image, Primitive, Quad, Transformation, +};  use iced_native::{      renderer::{Debugger, Windowed},      Background, Color, Layout, MouseCursor, Point, Rectangle, Vector, Widget,  }; - +use std::sync::Arc;  use wgpu::{      Adapter, BackendBit, CommandEncoderDescriptor, Device, DeviceDescriptor,      Extensions, Limits, PowerPreference, Queue, RequestAdapterOptions, @@ -24,6 +26,7 @@ pub struct Renderer {      quad_pipeline: quad::Pipeline,      image_pipeline: crate::image::Pipeline,      text_pipeline: text::Pipeline, +    triangle_pipeline: crate::triangle::Pipeline,  }  struct Layer<'a> { @@ -31,6 +34,7 @@ struct Layer<'a> {      offset: Vector<u32>,      quads: Vec<Quad>,      images: Vec<Image>, +    meshes: Vec<Arc<triangle::Mesh2D>>,      text: Vec<wgpu_glyph::Section<'a>>,  } @@ -42,6 +46,7 @@ impl<'a> Layer<'a> {              quads: Vec::new(),              images: Vec::new(),              text: Vec::new(), +            meshes: Vec::new(),          }      }  } @@ -64,6 +69,7 @@ impl Renderer {          let text_pipeline = text::Pipeline::new(&mut device);          let quad_pipeline = quad::Pipeline::new(&mut device);          let image_pipeline = crate::image::Pipeline::new(&mut device); +        let triangle_pipeline = triangle::Pipeline::new(&mut device);          Self {              device, @@ -71,6 +77,7 @@ impl Renderer {              quad_pipeline,              image_pipeline,              text_pipeline, +            triangle_pipeline,          }      } @@ -244,6 +251,9 @@ impl Renderer {                      scale: [bounds.width, bounds.height],                  });              } +            Primitive::Mesh2D(mesh) => { +                layer.meshes.push(mesh.clone()); +            }              Primitive::Clip {                  bounds,                  offset, @@ -322,6 +332,24 @@ impl Renderer {      ) {          let bounds = layer.bounds * dpi; +        if layer.meshes.len() > 0 { +            let translated = transformation +                * Transformation::translate( +                    -(layer.offset.x as f32) * dpi, +                    -(layer.offset.y as f32) * dpi, +                ); + +            self.triangle_pipeline.draw( +                &mut self.device, +                encoder, +                target, +                translated, +                dpi, +                &layer.meshes, +                bounds, +            ); +        } +          if layer.quads.len() > 0 {              self.quad_pipeline.draw(                  &mut self.device, diff --git a/wgpu/src/shader/triangle.frag b/wgpu/src/shader/triangle.frag new file mode 100644 index 00000000..e39c45e7 --- /dev/null +++ b/wgpu/src/shader/triangle.frag @@ -0,0 +1,8 @@ +#version 450 + +layout(location = 0) in vec4 i_Color; +layout(location = 0) out vec4 o_Color; + +void main() { +    o_Color = i_Color; +} diff --git a/wgpu/src/shader/triangle.frag.spv b/wgpu/src/shader/triangle.frag.spv Binary files differnew file mode 100644 index 00000000..11201872 --- /dev/null +++ b/wgpu/src/shader/triangle.frag.spv diff --git a/wgpu/src/shader/triangle.vert b/wgpu/src/shader/triangle.vert new file mode 100644 index 00000000..fd86ecd6 --- /dev/null +++ b/wgpu/src/shader/triangle.vert @@ -0,0 +1,17 @@ +#version 450 + +layout(location = 0) in vec2 i_Position; +layout(location = 1) in vec4 i_Color; + +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); +    o_Color = i_Color; +} diff --git a/wgpu/src/shader/triangle.vert.spv b/wgpu/src/shader/triangle.vert.spv Binary files differnew file mode 100644 index 00000000..bc39c451 --- /dev/null +++ b/wgpu/src/shader/triangle.vert.spv diff --git a/wgpu/src/triangle.rs b/wgpu/src/triangle.rs new file mode 100644 index 00000000..38157d00 --- /dev/null +++ b/wgpu/src/triangle.rs @@ -0,0 +1,239 @@ +//! Draw meshes of triangles. +use crate::Transformation; +use iced_native::Rectangle; +use std::{mem, sync::Arc}; + +#[derive(Debug)] +pub(crate) struct Pipeline { +    pipeline: wgpu::RenderPipeline, +    constants: wgpu::BindGroup, +    constants_buffer: wgpu::Buffer, +} + +impl Pipeline { +    pub fn new(device: &mut wgpu::Device) -> Pipeline { +        let constant_layout = +            device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { +                bindings: &[wgpu::BindGroupLayoutBinding { +                    binding: 0, +                    visibility: wgpu::ShaderStage::VERTEX, +                    ty: wgpu::BindingType::UniformBuffer { dynamic: false }, +                }], +            }); + +        let constants_buffer = device +            .create_buffer_mapped( +                1, +                wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, +            ) +            .fill_from_slice(&[Uniforms::default()]); + +        let constant_bind_group = +            device.create_bind_group(&wgpu::BindGroupDescriptor { +                layout: &constant_layout, +                bindings: &[wgpu::Binding { +                    binding: 0, +                    resource: wgpu::BindingResource::Buffer { +                        buffer: &constants_buffer, +                        range: 0..std::mem::size_of::<Uniforms>() as u64, +                    }, +                }], +            }); + +        let layout = +            device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { +                bind_group_layouts: &[&constant_layout], +            }); + +        let vs = include_bytes!("shader/triangle.vert.spv"); +        let vs_module = device.create_shader_module( +            &wgpu::read_spirv(std::io::Cursor::new(&vs[..])) +                .expect("Read triangle vertex shader as SPIR-V"), +        ); + +        let fs = include_bytes!("shader/triangle.frag.spv"); +        let fs_module = device.create_shader_module( +            &wgpu::read_spirv(std::io::Cursor::new(&fs[..])) +                .expect("Read triangle fragment shader as SPIR-V"), +        ); + +        let pipeline = +            device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { +                layout: &layout, +                vertex_stage: wgpu::ProgrammableStageDescriptor { +                    module: &vs_module, +                    entry_point: "main", +                }, +                fragment_stage: Some(wgpu::ProgrammableStageDescriptor { +                    module: &fs_module, +                    entry_point: "main", +                }), +                rasterization_state: Some(wgpu::RasterizationStateDescriptor { +                    front_face: wgpu::FrontFace::Cw, +                    cull_mode: wgpu::CullMode::None, +                    depth_bias: 0, +                    depth_bias_slope_scale: 0.0, +                    depth_bias_clamp: 0.0, +                }), +                primitive_topology: wgpu::PrimitiveTopology::TriangleList, +                color_states: &[wgpu::ColorStateDescriptor { +                    format: wgpu::TextureFormat::Bgra8UnormSrgb, +                    color_blend: wgpu::BlendDescriptor { +                        src_factor: wgpu::BlendFactor::SrcAlpha, +                        dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, +                        operation: wgpu::BlendOperation::Add, +                    }, +                    alpha_blend: wgpu::BlendDescriptor { +                        src_factor: wgpu::BlendFactor::One, +                        dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, +                        operation: wgpu::BlendOperation::Add, +                    }, +                    write_mask: wgpu::ColorWrite::ALL, +                }], +                depth_stencil_state: None, +                index_format: wgpu::IndexFormat::Uint16, +                vertex_buffers: &[wgpu::VertexBufferDescriptor { +                    stride: mem::size_of::<Vertex2D>() as u64, +                    step_mode: wgpu::InputStepMode::Vertex, +                    attributes: &[ +                        // Position +                        wgpu::VertexAttributeDescriptor { +                            shader_location: 0, +                            format: wgpu::VertexFormat::Float2, +                            offset: 0, +                        }, +                        // Color +                        wgpu::VertexAttributeDescriptor { +                            shader_location: 1, +                            format: wgpu::VertexFormat::Float4, +                            offset: 4 * 2, +                        }, +                    ], +                }], +                sample_count: 1, +                sample_mask: !0, +                alpha_to_coverage_enabled: false, +            }); + +        Pipeline { +            pipeline, +            constants: constant_bind_group, +            constants_buffer, +        } +    } + +    pub fn draw( +        &mut self, +        device: &mut wgpu::Device, +        encoder: &mut wgpu::CommandEncoder, +        target: &wgpu::TextureView, +        transformation: Transformation, +        scale: f32, +        meshes: &Vec<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 mesh in meshes { +            let vertices_buffer = device +                .create_buffer_mapped( +                    mesh.vertices.len(), +                    wgpu::BufferUsage::VERTEX, +                ) +                .fill_from_slice(&mesh.vertices); + +            let indices_buffer = device +                .create_buffer_mapped( +                    mesh.indices.len(), +                    wgpu::BufferUsage::INDEX, +                ) +                .fill_from_slice(&mesh.indices); + +            render_pass.set_pipeline(&self.pipeline); +            render_pass.set_bind_group(0, &self.constants, &[]); +            render_pass.set_index_buffer(&indices_buffer, 0); +            render_pass.set_vertex_buffers(0, &[(&vertices_buffer, 0)]); +            render_pass.set_scissor_rect( +                bounds.x, +                bounds.y, +                bounds.width, +                bounds.height, +            ); + +            render_pass.draw_indexed(0..mesh.indices.len() as u32, 0, 0..1); +        } +    } +} + +#[repr(C)] +#[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, +        } +    } +} + +/// A two-dimensional vertex with some color in __linear__ RGBA. +#[repr(C)] +#[derive(Copy, Clone, Debug)] +pub struct Vertex2D { +    /// The vertex position +    pub position: [f32; 2], +    /// The vertex color in __linear__ RGBA. +    pub color: [f32; 4], +} + +/// A set of [`Vertex2D`] and indices representing a list of triangles. +/// +/// [`Vertex2D`]: struct.Vertex2D.html +#[derive(Clone, Debug)] +pub struct Mesh2D { +    /// The vertices of the mesh +    pub vertices: Vec<Vertex2D>, +    /// The list of vertex indices that defines the triangles of the mesh. +    /// +    /// Therefore, this list should always have a length that is a multiple of 3. +    pub indices: Vec<u16>, +}  | 
