diff options
author | 2023-05-11 09:12:06 -0700 | |
---|---|---|
committer | 2023-05-11 11:13:44 -0700 | |
commit | 6551a0b2ab6c831dd1d3646ecf55180339275e22 (patch) | |
tree | de1e4a85b3176f94fd006fed190ef035d3202e49 /wgpu/src/triangle.rs | |
parent | 669f7cc74b2e7918e86a8197916f503f2d3d9b93 (diff) | |
download | iced-6551a0b2ab6c831dd1d3646ecf55180339275e22.tar.gz iced-6551a0b2ab6c831dd1d3646ecf55180339275e22.tar.bz2 iced-6551a0b2ab6c831dd1d3646ecf55180339275e22.zip |
Added support for gradients as background variants + other optimizations.
Diffstat (limited to 'wgpu/src/triangle.rs')
-rw-r--r-- | wgpu/src/triangle.rs | 543 |
1 files changed, 192 insertions, 351 deletions
diff --git a/wgpu/src/triangle.rs b/wgpu/src/triangle.rs index eb15a458..0d1fead1 100644 --- a/wgpu/src/triangle.rs +++ b/wgpu/src/triangle.rs @@ -1,26 +1,19 @@ //! Draw meshes of triangles. mod msaa; -use crate::buffer::r#static::Buffer; +use crate::buffer::Buffer; use crate::core::Size; use crate::graphics::{Antialiasing, Transformation}; use crate::layer::mesh::{self, Mesh}; -#[cfg(not(target_arch = "wasm32"))] -use crate::core::Gradient; - -#[cfg(feature = "tracing")] -use tracing::info_span; +const INITIAL_INDEX_COUNT: usize = 1_000; +const INITIAL_VERTEX_COUNT: usize = 1_000; #[derive(Debug)] pub struct Pipeline { blit: Option<msaa::Blit>, solid: solid::Pipeline, - - /// Gradients are currently not supported on WASM targets due to their need of storage buffers. - #[cfg(not(target_arch = "wasm32"))] gradient: gradient::Pipeline, - layers: Vec<Layer>, prepare_layer: usize, } @@ -30,8 +23,6 @@ struct Layer { index_buffer: Buffer<u32>, index_strides: Vec<u32>, solid: solid::Layer, - - #[cfg(not(target_arch = "wasm32"))] gradient: gradient::Layer, } @@ -39,18 +30,17 @@ impl Layer { fn new( device: &wgpu::Device, solid: &solid::Pipeline, - #[cfg(not(target_arch = "wasm32"))] gradient: &gradient::Pipeline, + gradient: &gradient::Pipeline, ) -> Self { Self { index_buffer: Buffer::new( device, - "iced_wgpu::triangle index buffer", + "iced_wgpu.triangle.index_buffer", + INITIAL_INDEX_COUNT, wgpu::BufferUsages::INDEX | wgpu::BufferUsages::COPY_DST, ), index_strides: Vec::new(), solid: solid::Layer::new(device, &solid.constants_layout), - - #[cfg(not(target_arch = "wasm32"))] gradient: gradient::Layer::new(device, &gradient.constants_layout), } } @@ -60,7 +50,7 @@ impl Layer { device: &wgpu::Device, queue: &wgpu::Queue, solid: &solid::Pipeline, - #[cfg(not(target_arch = "wasm32"))] gradient: &gradient::Pipeline, + gradient: &gradient::Pipeline, meshes: &[Mesh<'_>], transformation: Transformation, ) { @@ -73,177 +63,92 @@ impl Layer { // the majority of use cases. Therefore we will write GPU data every frame (for now). let _ = self.index_buffer.resize(device, count.indices); let _ = self.solid.vertices.resize(device, count.solid_vertices); - - #[cfg(not(target_arch = "wasm32"))] let _ = self .gradient .vertices .resize(device, count.gradient_vertices); - // Prepare dynamic buffers & data store for writing - self.index_buffer.clear(); + if self.solid.uniforms.resize(device, count.solids) { + self.solid.constants = solid::Layer::bind_group( + device, + &self.solid.uniforms.raw, + &solid.constants_layout, + ); + } + + if self.gradient.uniforms.resize(device, count.gradients) { + self.gradient.constants = gradient::Layer::bind_group( + device, + &self.gradient.uniforms.raw, + &gradient.constants_layout, + ); + } + self.index_strides.clear(); + self.index_buffer.clear(); self.solid.vertices.clear(); self.solid.uniforms.clear(); - - #[cfg(not(target_arch = "wasm32"))] - { - self.gradient.uniforms.clear(); - self.gradient.vertices.clear(); - self.gradient.storage.clear(); - } + self.gradient.vertices.clear(); + self.gradient.uniforms.clear(); let mut solid_vertex_offset = 0; - let mut index_offset = 0; - - #[cfg(not(target_arch = "wasm32"))] + let mut solid_uniform_offset = 0; let mut gradient_vertex_offset = 0; + let mut gradient_uniform_offset = 0; + let mut index_offset = 0; for mesh in meshes { let origin = mesh.origin(); let indices = mesh.indices(); - let transform = - transformation * Transformation::translate(origin.x, origin.y); + let uniforms = Uniforms::new( + transformation * Transformation::translate(origin.x, origin.y), + ); - let new_index_offset = + index_offset += self.index_buffer.write(queue, index_offset, indices); - - index_offset += new_index_offset; self.index_strides.push(indices.len() as u32); - //push uniform data to CPU buffers match mesh { Mesh::Solid { buffers, .. } => { - self.solid.uniforms.push(&solid::Uniforms::new(transform)); - - let written_bytes = self.solid.vertices.write( + solid_vertex_offset += self.solid.vertices.write( queue, solid_vertex_offset, &buffers.vertices, ); - solid_vertex_offset += written_bytes; + solid_uniform_offset += self.solid.uniforms.write( + queue, + solid_uniform_offset, + &[uniforms], + ); } - #[cfg(not(target_arch = "wasm32"))] - Mesh::Gradient { - buffers, gradient, .. - } => { - let written_bytes = self.gradient.vertices.write( + Mesh::Gradient { buffers, .. } => { + gradient_vertex_offset += self.gradient.vertices.write( queue, gradient_vertex_offset, &buffers.vertices, ); - gradient_vertex_offset += written_bytes; - - match gradient { - Gradient::Linear(linear) => { - use glam::{IVec4, Vec4}; - - let start_offset = self.gradient.color_stop_offset; - let end_offset = (linear.color_stops.len() as i32) - + start_offset - - 1; - - self.gradient.uniforms.push(&gradient::Uniforms { - transform: transform.into(), - direction: Vec4::new( - linear.start.x, - linear.start.y, - linear.end.x, - linear.end.y, - ), - stop_range: IVec4::new( - start_offset, - end_offset, - 0, - 0, - ), - }); - - self.gradient.color_stop_offset = end_offset + 1; - - let stops: Vec<gradient::ColorStop> = linear - .color_stops - .iter() - .map(|stop| { - let [r, g, b, a] = stop.color.into_linear(); - - gradient::ColorStop { - offset: stop.offset, - color: Vec4::new(r, g, b, a), - } - }) - .collect(); - - self.gradient - .color_stops_pending_write - .color_stops - .extend(stops); - } - } + gradient_uniform_offset += self.gradient.uniforms.write( + queue, + gradient_uniform_offset, + &[uniforms], + ); } - #[cfg(target_arch = "wasm32")] - Mesh::Gradient { .. } => {} } } - - // Write uniform data to GPU - if count.solid_vertices > 0 { - let uniforms_resized = self.solid.uniforms.resize(device); - - if uniforms_resized { - self.solid.constants = solid::Layer::bind_group( - device, - self.solid.uniforms.raw(), - &solid.constants_layout, - ) - } - - self.solid.uniforms.write(queue); - } - - #[cfg(not(target_arch = "wasm32"))] - if count.gradient_vertices > 0 { - // First write the pending color stops to the CPU buffer - self.gradient - .storage - .push(&self.gradient.color_stops_pending_write); - - // Resize buffers if needed - let uniforms_resized = self.gradient.uniforms.resize(device); - let storage_resized = self.gradient.storage.resize(device); - - if uniforms_resized || storage_resized { - self.gradient.constants = gradient::Layer::bind_group( - device, - self.gradient.uniforms.raw(), - self.gradient.storage.raw(), - &gradient.constants_layout, - ); - } - - // Write to GPU - self.gradient.uniforms.write(queue); - self.gradient.storage.write(queue); - - // Cleanup - self.gradient.color_stop_offset = 0; - self.gradient.color_stops_pending_write.color_stops.clear(); - } } fn render<'a>( &'a self, solid: &'a solid::Pipeline, - #[cfg(not(target_arch = "wasm32"))] gradient: &'a gradient::Pipeline, + gradient: &'a gradient::Pipeline, meshes: &[Mesh<'_>], scale_factor: f32, render_pass: &mut wgpu::RenderPass<'a>, ) { let mut num_solids = 0; - #[cfg(not(target_arch = "wasm32"))] let mut num_gradients = 0; let mut last_is_solid = None; @@ -268,7 +173,8 @@ impl Layer { render_pass.set_bind_group( 0, &self.solid.constants, - &[self.solid.uniforms.offset_at_index(num_solids)], + &[(num_solids * std::mem::size_of::<Uniforms>()) + as u32], ); render_pass.set_vertex_buffer( @@ -278,7 +184,6 @@ impl Layer { num_solids += 1; } - #[cfg(not(target_arch = "wasm32"))] Mesh::Gradient { .. } => { if last_is_solid.unwrap_or(true) { render_pass.set_pipeline(&gradient.pipeline); @@ -289,10 +194,8 @@ impl Layer { render_pass.set_bind_group( 0, &self.gradient.constants, - &[self - .gradient - .uniforms - .offset_at_index(num_gradients)], + &[(num_gradients * std::mem::size_of::<Uniforms>()) + as u32], ); render_pass.set_vertex_buffer( @@ -302,8 +205,6 @@ impl Layer { num_gradients += 1; } - #[cfg(target_arch = "wasm32")] - Mesh::Gradient { .. } => {} }; render_pass.set_index_buffer( @@ -325,10 +226,7 @@ impl Pipeline { Pipeline { blit: antialiasing.map(|a| msaa::Blit::new(device, format, a)), solid: solid::Pipeline::new(device, format, antialiasing), - - #[cfg(not(target_arch = "wasm32"))] gradient: gradient::Pipeline::new(device, format, antialiasing), - layers: Vec::new(), prepare_layer: 0, } @@ -342,15 +240,11 @@ impl Pipeline { transformation: Transformation, ) { #[cfg(feature = "tracing")] - let _ = info_span!("Wgpu::Triangle", "PREPARE").entered(); + let _ = tracing::info_span!("Wgpu::Triangle", "PREPARE").entered(); if self.layers.len() <= self.prepare_layer { - self.layers.push(Layer::new( - device, - &self.solid, - #[cfg(not(target_arch = "wasm32"))] - &self.gradient, - )); + self.layers + .push(Layer::new(device, &self.solid, &self.gradient)); } let layer = &mut self.layers[self.prepare_layer]; @@ -358,7 +252,6 @@ impl Pipeline { device, queue, &self.solid, - #[cfg(not(target_arch = "wasm32"))] &self.gradient, meshes, transformation, @@ -378,9 +271,8 @@ impl Pipeline { scale_factor: f32, ) { #[cfg(feature = "tracing")] - let _ = info_span!("Wgpu::Triangle", "DRAW").entered(); + let _ = tracing::info_span!("Wgpu::Triangle", "DRAW").entered(); - // Configure render pass { let (attachment, resolve_target, load) = if let Some(blit) = &mut self.blit @@ -397,12 +289,9 @@ impl Pipeline { (target, None, wgpu::LoadOp::Load) }; - #[cfg(feature = "tracing")] - let _ = info_span!("Wgpu::Triangle", "BEGIN_RENDER_PASS").enter(); - let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - label: Some("iced_wgpu::triangle render pass"), + label: Some("iced_wgpu.triangle.render_pass"), color_attachments: &[Some( wgpu::RenderPassColorAttachment { view: attachment, @@ -417,7 +306,6 @@ impl Pipeline { layer.render( &self.solid, - #[cfg(not(target_arch = "wasm32"))] &self.gradient, meshes, scale_factor, @@ -463,15 +351,49 @@ fn multisample_state( } } +#[derive(Debug, Clone, Copy, bytemuck::Pod, bytemuck::Zeroable)] +#[repr(C)] +pub struct Uniforms { + transform: [f32; 16], + /// Uniform values must be 256-aligned; + /// see: [`wgpu::Limits`] `min_uniform_buffer_offset_alignment`. + _padding: [f32; 48], +} + +impl Uniforms { + pub fn new(transform: Transformation) -> Self { + Self { + transform: transform.into(), + _padding: [0.0; 48], + } + } + + pub fn entry() -> wgpu::BindGroupLayoutEntry { + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: true, + min_binding_size: wgpu::BufferSize::new( + std::mem::size_of::<Self>() as u64, + ), + }, + count: None, + } + } + + pub fn min_size() -> Option<wgpu::BufferSize> { + wgpu::BufferSize::new(std::mem::size_of::<Self>() as u64) + } +} + mod solid { - use crate::buffer::dynamic; - use crate::buffer::r#static::Buffer; + use crate::buffer::Buffer; use crate::graphics::primitive; - use crate::graphics::{Antialiasing, Transformation}; + use crate::graphics::Antialiasing; use crate::triangle; - use encase::ShaderType; - #[derive(Debug)] pub struct Pipeline { pub pipeline: wgpu::RenderPipeline, @@ -481,7 +403,7 @@ mod solid { #[derive(Debug)] pub struct Layer { pub vertices: Buffer<primitive::ColoredVertex2D>, - pub uniforms: dynamic::Buffer<Uniforms>, + pub uniforms: Buffer<triangle::Uniforms>, pub constants: wgpu::BindGroup, } @@ -492,17 +414,20 @@ mod solid { ) -> Self { let vertices = Buffer::new( device, - "iced_wgpu::triangle::solid vertex buffer", + "iced_wgpu.triangle.solid.vertex_buffer", + triangle::INITIAL_VERTEX_COUNT, wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST, ); - let uniforms = dynamic::Buffer::uniform( + let uniforms = Buffer::new( device, - "iced_wgpu::triangle::solid uniforms", + "iced_wgpu.triangle.solid.uniforms", + 1, + wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, ); let constants = - Self::bind_group(device, uniforms.raw(), constants_layout); + Self::bind_group(device, &uniforms.raw, constants_layout); Self { vertices, @@ -517,7 +442,7 @@ mod solid { layout: &wgpu::BindGroupLayout, ) -> wgpu::BindGroup { device.create_bind_group(&wgpu::BindGroupDescriptor { - label: Some("iced_wgpu::triangle::solid bind group"), + label: Some("iced_wgpu.triangle.solid.bind_group"), layout, entries: &[wgpu::BindGroupEntry { binding: 0, @@ -525,7 +450,7 @@ mod solid { wgpu::BufferBinding { buffer, offset: 0, - size: Some(Uniforms::min_size()), + size: triangle::Uniforms::min_size(), }, ), }], @@ -533,21 +458,7 @@ mod solid { } } - #[derive(Debug, Clone, Copy, ShaderType)] - pub struct Uniforms { - transform: glam::Mat4, - } - - impl Uniforms { - pub fn new(transform: Transformation) -> Self { - Self { - transform: transform.into(), - } - } - } - impl Pipeline { - /// Creates a new [SolidPipeline] using `solid.wgsl` shader. pub fn new( device: &wgpu::Device, format: wgpu::TextureFormat, @@ -555,23 +466,14 @@ mod solid { ) -> Self { let constants_layout = device.create_bind_group_layout( &wgpu::BindGroupLayoutDescriptor { - label: Some("iced_wgpu::triangle::solid bind group layout"), - entries: &[wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Uniform, - has_dynamic_offset: true, - min_binding_size: Some(Uniforms::min_size()), - }, - count: None, - }], + label: Some("iced_wgpu.triangle.solid.bind_group_layout"), + entries: &[triangle::Uniforms::entry()], }, ); let layout = device.create_pipeline_layout( &wgpu::PipelineLayoutDescriptor { - label: Some("iced_wgpu::triangle::solid pipeline layout"), + label: Some("iced_wgpu.triangle.solid.pipeline_layout"), bind_group_layouts: &[&constants_layout], push_constant_ranges: &[], }, @@ -579,12 +481,10 @@ mod solid { let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { - label: Some( - "iced_wgpu triangle solid create shader module", - ), + label: Some("iced_wgpu.triangle.solid.shader"), source: wgpu::ShaderSource::Wgsl( std::borrow::Cow::Borrowed(include_str!( - "shader/solid.wgsl" + "shader/triangle.wgsl" )), ), }); @@ -595,7 +495,7 @@ mod solid { layout: Some(&layout), vertex: wgpu::VertexState { module: &shader, - entry_point: "vs_main", + entry_point: "solid_vs_main", buffers: &[wgpu::VertexBufferLayout { array_stride: std::mem::size_of::< primitive::ColoredVertex2D, @@ -612,7 +512,7 @@ mod solid { }, fragment: Some(wgpu::FragmentState { module: &shader, - entry_point: "fs_main", + entry_point: "solid_fs_main", targets: &[triangle::fragment_target(format)], }), primitive: triangle::primitive_state(), @@ -630,16 +530,11 @@ mod solid { } } -#[cfg(not(target_arch = "wasm32"))] mod gradient { - use crate::buffer::dynamic; - use crate::buffer::r#static::Buffer; - use crate::graphics::Antialiasing; + use crate::graphics::{primitive, Antialiasing}; use crate::triangle; - use encase::ShaderType; - use glam::{IVec4, Vec4}; - use iced_graphics::primitive; + use crate::buffer::Buffer; #[derive(Debug)] pub struct Pipeline { @@ -649,14 +544,9 @@ mod gradient { #[derive(Debug)] pub struct Layer { - pub vertices: Buffer<primitive::Vertex2D>, - pub uniforms: dynamic::Buffer<Uniforms>, - pub storage: dynamic::Buffer<Storage>, + pub vertices: Buffer<primitive::GradientVertex2D>, + pub uniforms: Buffer<triangle::Uniforms>, pub constants: wgpu::BindGroup, - pub color_stop_offset: i32, - //Need to store these and then write them all at once - //or else they will be padded to 256 and cause gaps in the storage buffer - pub color_stops_pending_write: Storage, } impl Layer { @@ -666,94 +556,52 @@ mod gradient { ) -> Self { let vertices = Buffer::new( device, - "iced_wgpu::triangle::gradient vertex buffer", + "iced_wgpu.triangle.gradient.vertex_buffer", + triangle::INITIAL_VERTEX_COUNT, wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST, ); - let uniforms = dynamic::Buffer::uniform( + let uniforms = Buffer::new( device, - "iced_wgpu::triangle::gradient uniforms", + "iced_wgpu.triangle.gradient.uniforms", + 1, + wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, ); - // Note: with a WASM target storage buffers are not supported. Will need to use UBOs & static - // sized array (eg like the 32-sized array on OpenGL side right now) to make gradients work - let storage = dynamic::Buffer::storage( - device, - "iced_wgpu::triangle::gradient storage", - ); - - let constants = Self::bind_group( - device, - uniforms.raw(), - storage.raw(), - constants_layout, - ); + let constants = + Self::bind_group(device, &uniforms.raw, constants_layout); Self { vertices, uniforms, - storage, constants, - color_stop_offset: 0, - color_stops_pending_write: Storage { - color_stops: vec![], - }, } } pub fn bind_group( device: &wgpu::Device, uniform_buffer: &wgpu::Buffer, - storage_buffer: &wgpu::Buffer, layout: &wgpu::BindGroupLayout, ) -> wgpu::BindGroup { device.create_bind_group(&wgpu::BindGroupDescriptor { - label: Some("iced_wgpu::triangle::gradient bind group"), + label: Some("iced_wgpu.triangle.gradient.bind_group"), layout, - entries: &[ - wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::Buffer( - wgpu::BufferBinding { - buffer: uniform_buffer, - offset: 0, - size: Some(Uniforms::min_size()), - }, - ), - }, - wgpu::BindGroupEntry { - binding: 1, - resource: storage_buffer.as_entire_binding(), - }, - ], + entries: &[wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::Buffer( + wgpu::BufferBinding { + buffer: uniform_buffer, + offset: 0, + size: triangle::Uniforms::min_size(), + }, + ), + }], }) } } - #[derive(Debug, ShaderType)] - pub struct Uniforms { - pub transform: glam::Mat4, - //xy = start, zw = end - pub direction: Vec4, - //x = start stop, y = end stop, zw = padding - pub stop_range: IVec4, - } - - #[derive(Debug, ShaderType)] - pub struct ColorStop { - pub color: Vec4, - pub offset: f32, - } - - #[derive(Debug, ShaderType)] - pub struct Storage { - #[size(runtime)] - pub color_stops: Vec<ColorStop>, - } - impl Pipeline { - /// Creates a new [GradientPipeline] using `gradient.wgsl` shader. - pub(super) fn new( + pub fn new( device: &wgpu::Device, format: wgpu::TextureFormat, antialiasing: Option<Antialiasing>, @@ -761,40 +609,15 @@ mod gradient { let constants_layout = device.create_bind_group_layout( &wgpu::BindGroupLayoutDescriptor { label: Some( - "iced_wgpu::triangle::gradient bind group layout", + "iced_wgpu.triangle.gradient.bind_group_layout", ), - entries: &[ - wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Uniform, - has_dynamic_offset: true, - min_binding_size: Some(Uniforms::min_size()), - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 1, - visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Storage { - read_only: true, - }, - has_dynamic_offset: false, - min_binding_size: Some(Storage::min_size()), - }, - count: None, - }, - ], + entries: &[triangle::Uniforms::entry()], }, ); let layout = device.create_pipeline_layout( &wgpu::PipelineLayoutDescriptor { - label: Some( - "iced_wgpu::triangle::gradient pipeline layout", - ), + label: Some("iced_wgpu.triangle.gradient.pipeline_layout"), bind_group_layouts: &[&constants_layout], push_constant_ranges: &[], }, @@ -802,48 +625,66 @@ mod gradient { let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { - label: Some( - "iced_wgpu::triangle::gradient create shader module", - ), + label: Some("iced_wgpu.triangle.gradient.shader"), source: wgpu::ShaderSource::Wgsl( std::borrow::Cow::Borrowed(include_str!( - "shader/gradient.wgsl" + "shader/triangle.wgsl" )), ), }); - let pipeline = - device.create_render_pipeline( - &wgpu::RenderPipelineDescriptor { - label: Some("iced_wgpu::triangle::gradient pipeline"), - layout: Some(&layout), - vertex: wgpu::VertexState { - module: &shader, - entry_point: "vs_main", - buffers: &[wgpu::VertexBufferLayout { - array_stride: std::mem::size_of::< - primitive::Vertex2D, - >( - ) - as u64, - step_mode: wgpu::VertexStepMode::Vertex, - attributes: &wgpu::vertex_attr_array!( - // Position - 0 => Float32x2, - ), - }], - }, - fragment: Some(wgpu::FragmentState { - module: &shader, - entry_point: "fs_main", - targets: &[triangle::fragment_target(format)], - }), - primitive: triangle::primitive_state(), - depth_stencil: None, - multisample: triangle::multisample_state(antialiasing), - multiview: None, + let pipeline = device.create_render_pipeline( + &wgpu::RenderPipelineDescriptor { + label: Some("iced_wgpu.triangle.gradient.pipeline"), + layout: Some(&layout), + vertex: wgpu::VertexState { + module: &shader, + entry_point: "gradient_vs_main", + buffers: &[wgpu::VertexBufferLayout { + array_stride: std::mem::size_of::< + primitive::GradientVertex2D, + >() + as u64, + step_mode: wgpu::VertexStepMode::Vertex, + attributes: &wgpu::vertex_attr_array!( + // Position + 0 => Float32x2, + // Color 1 + 1 => Float32x4, + // Color 2 + 2 => Float32x4, + // Color 3 + 3 => Float32x4, + // Color 4 + 4 => Float32x4, + // Color 5 + 5 => Float32x4, + // Color 6 + 6 => Float32x4, + // Color 7 + 7 => Float32x4, + // Color 8 + 8 => Float32x4, + // Offsets 1-4 + 9 => Float32x4, + // Offsets 5-8 + 10 => Float32x4, + // Direction + 11 => Float32x4 + ), + }], }, - ); + fragment: Some(wgpu::FragmentState { + module: &shader, + entry_point: "gradient_fs_main", + targets: &[triangle::fragment_target(format)], + }), + primitive: triangle::primitive_state(), + depth_stencil: None, + multisample: triangle::multisample_state(antialiasing), + multiview: None, + }, + ); Self { pipeline, |