summaryrefslogtreecommitdiffstats
path: root/wgpu/src
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón <hector0193@gmail.com>2023-05-30 01:47:31 +0200
committerLibravatar GitHub <noreply@github.com>2023-05-30 01:47:31 +0200
commit9253f7663dc862484988dead9a9d1a0cf2dc93f5 (patch)
tree0e3b21b14ff0d19a90c22b436e02a9a76729aea3 /wgpu/src
parent8ff2e0178ff9e53ab5cff9bdbc7c834d277a6a93 (diff)
parentc319f5113b274bedff0d18260eddbd6f9915efc3 (diff)
downloadiced-9253f7663dc862484988dead9a9d1a0cf2dc93f5.tar.gz
iced-9253f7663dc862484988dead9a9d1a0cf2dc93f5.tar.bz2
iced-9253f7663dc862484988dead9a9d1a0cf2dc93f5.zip
Merge pull request #1873 from bungoboingo/fix/bg-gradient-layering
[Fix] Quads of different background types not ordered
Diffstat (limited to 'wgpu/src')
-rw-r--r--wgpu/src/backend.rs8
-rw-r--r--wgpu/src/layer.rs50
-rw-r--r--wgpu/src/layer/quad.rs51
-rw-r--r--wgpu/src/quad.rs396
-rw-r--r--wgpu/src/quad/gradient.rs175
-rw-r--r--wgpu/src/quad/solid.rs149
6 files changed, 440 insertions, 389 deletions
diff --git a/wgpu/src/backend.rs b/wgpu/src/backend.rs
index def80a81..844987f2 100644
--- a/wgpu/src/backend.rs
+++ b/wgpu/src/backend.rs
@@ -265,8 +265,12 @@ impl Backend {
}
if !layer.quads.is_empty() {
- self.quad_pipeline
- .render(quad_layer, bounds, &mut render_pass);
+ self.quad_pipeline.render(
+ quad_layer,
+ bounds,
+ &layer.quads,
+ &mut render_pass,
+ );
quad_layer += 1;
}
diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs
index bf5c4c0a..1a870c15 100644
--- a/wgpu/src/layer.rs
+++ b/wgpu/src/layer.rs
@@ -3,18 +3,16 @@ mod image;
mod text;
pub mod mesh;
-pub mod quad;
pub use image::Image;
pub use mesh::Mesh;
-pub use quad::Quad;
pub use text::Text;
use crate::core;
use crate::core::alignment;
-use crate::core::{Background, Color, Font, Point, Rectangle, Size, Vector};
-use crate::graphics::gradient;
+use crate::core::{Color, Font, Point, Rectangle, Size, Vector};
use crate::graphics::{Primitive, Viewport};
+use crate::quad::{self, Quad};
/// A group of primitives that should be clipped together.
#[derive(Debug)]
@@ -23,7 +21,7 @@ pub struct Layer<'a> {
pub bounds: Rectangle,
/// The quads of the [`Layer`].
- pub quads: Quads,
+ pub quads: quad::Batch,
/// The triangle meshes of the [`Layer`].
pub meshes: Vec<Mesh<'a>>,
@@ -35,29 +33,12 @@ pub struct Layer<'a> {
pub images: Vec<Image>,
}
-/// The quads of the [`Layer`].
-#[derive(Default, Debug)]
-pub struct Quads {
- /// The solid quads of the [`Layer`].
- pub solids: Vec<quad::Solid>,
-
- /// The gradient quads of the [`Layer`].
- pub gradients: Vec<quad::Gradient>,
-}
-
-impl Quads {
- /// Returns true if there are no quads of any type in [`Quads`].
- pub fn is_empty(&self) -> bool {
- self.solids.is_empty() && self.gradients.is_empty()
- }
-}
-
impl<'a> Layer<'a> {
/// Creates a new [`Layer`] with the given clipping bounds.
pub fn new(bounds: Rectangle) -> Self {
Self {
bounds,
- quads: Quads::default(),
+ quads: quad::Batch::default(),
meshes: Vec::new(),
text: Vec::new(),
images: Vec::new(),
@@ -174,28 +155,7 @@ impl<'a> Layer<'a> {
border_width: *border_width,
};
- match background {
- Background::Color(color) => {
- layer.quads.solids.push(quad::Solid {
- color: color.into_linear(),
- quad,
- });
- }
- Background::Gradient(gradient) => {
- let quad = quad::Gradient {
- gradient: gradient::pack(
- gradient,
- Rectangle::new(
- quad.position.into(),
- quad.size.into(),
- ),
- ),
- quad,
- };
-
- layer.quads.gradients.push(quad);
- }
- };
+ layer.quads.add(quad, background);
}
Primitive::Image { handle, bounds } => {
let layer = &mut layers[current_layer];
diff --git a/wgpu/src/layer/quad.rs b/wgpu/src/layer/quad.rs
deleted file mode 100644
index 0bf7837a..00000000
--- a/wgpu/src/layer/quad.rs
+++ /dev/null
@@ -1,51 +0,0 @@
-//! A rectangle with certain styled properties.
-use crate::graphics::gradient;
-use bytemuck::{Pod, Zeroable};
-
-/// The properties of a quad.
-#[derive(Clone, Copy, Debug, Pod, Zeroable)]
-#[repr(C)]
-pub struct Quad {
- /// The position of the [`Quad`].
- pub position: [f32; 2],
-
- /// The size of the [`Quad`].
- pub size: [f32; 2],
-
- /// The border color of the [`Quad`], in __linear RGB__.
- pub border_color: [f32; 4],
-
- /// The border radii of the [`Quad`].
- pub border_radius: [f32; 4],
-
- /// The border width of the [`Quad`].
- pub border_width: f32,
-}
-
-/// A quad filled with a solid color.
-#[derive(Clone, Copy, Debug, Pod, Zeroable)]
-#[repr(C)]
-pub struct Solid {
- /// The background color data of the quad.
- pub color: [f32; 4],
-
- /// The [`Quad`] data of the [`Solid`].
- pub quad: Quad,
-}
-
-/// A quad filled with interpolated colors.
-#[derive(Clone, Copy, Debug)]
-#[repr(C)]
-pub struct Gradient {
- /// The background gradient data of the quad.
- pub gradient: gradient::Packed,
-
- /// The [`Quad`] data of the [`Gradient`].
- pub quad: Quad,
-}
-
-#[allow(unsafe_code)]
-unsafe impl Pod for Gradient {}
-
-#[allow(unsafe_code)]
-unsafe impl Zeroable for Gradient {}
diff --git a/wgpu/src/quad.rs b/wgpu/src/quad.rs
index 0125ec0b..9c5ed05f 100644
--- a/wgpu/src/quad.rs
+++ b/wgpu/src/quad.rs
@@ -1,10 +1,17 @@
-use crate::core::Rectangle;
-use crate::graphics::Transformation;
-use crate::layer;
+mod gradient;
+mod solid;
-use std::mem;
+use gradient::Gradient;
+use solid::Solid;
+
+use crate::core::{Background, Rectangle};
+use crate::graphics::{self, Transformation};
+
+use bytemuck::{Pod, Zeroable};
use wgpu::util::DeviceExt;
+use std::mem;
+
#[cfg(feature = "tracing")]
use tracing::info_span;
@@ -69,7 +76,7 @@ impl Pipeline {
&mut self,
device: &wgpu::Device,
queue: &wgpu::Queue,
- instances: &layer::Quads,
+ quads: &Batch,
transformation: Transformation,
scale: f32,
) {
@@ -78,7 +85,7 @@ impl Pipeline {
}
let layer = &mut self.layers[self.prepare_layer];
- layer.prepare(device, queue, instances, transformation, scale);
+ layer.prepare(device, queue, quads, transformation, scale);
self.prepare_layer += 1;
}
@@ -87,6 +94,7 @@ impl Pipeline {
&'a self,
layer: usize,
bounds: Rectangle<u32>,
+ quads: &Batch,
render_pass: &mut wgpu::RenderPass<'a>,
) {
if let Some(layer) = self.layers.get(layer) {
@@ -102,14 +110,32 @@ impl Pipeline {
);
render_pass.set_vertex_buffer(0, self.vertices.slice(..));
- if layer.solid.instance_count > 0 {
- render_pass.set_pipeline(&self.solid.pipeline);
- layer.solid.draw(&layer.constants, render_pass);
- }
-
- if layer.gradient.instance_count > 0 {
- render_pass.set_pipeline(&self.gradient.pipeline);
- layer.gradient.draw(&layer.constants, render_pass);
+ let mut solid_offset = 0;
+ let mut gradient_offset = 0;
+
+ for (kind, count) in &quads.order {
+ match kind {
+ Kind::Solid => {
+ self.solid.render(
+ render_pass,
+ &layer.constants,
+ &layer.solid,
+ solid_offset..(solid_offset + count),
+ );
+
+ solid_offset += count;
+ }
+ Kind::Gradient => {
+ self.gradient.render(
+ render_pass,
+ &layer.constants,
+ &layer.gradient,
+ gradient_offset..(gradient_offset + count),
+ );
+
+ gradient_offset += count;
+ }
+ }
}
}
}
@@ -160,7 +186,7 @@ impl Layer {
&mut self,
device: &wgpu::Device,
queue: &wgpu::Queue,
- instances: &layer::Quads,
+ quads: &Batch,
transformation: Transformation,
scale: f32,
) {
@@ -175,306 +201,94 @@ impl Layer {
bytemuck::bytes_of(&uniforms),
);
- let _ = self.solid.instances.resize(device, instances.solids.len());
- let _ = self
- .gradient
- .instances
- .resize(device, instances.gradients.len());
- let _ =
- self.solid
- .instances
- .write(queue, 0, instances.solids.as_slice());
- self.solid.instance_count = instances.solids.len();
- let _ = self.gradient.instances.write(
- queue,
- 0,
- instances.gradients.as_slice(),
- );
- self.gradient.instance_count = instances.gradients.len();
+ self.solid.prepare(device, queue, &quads.solids);
+ self.gradient.prepare(device, queue, &quads.gradients);
}
}
-mod solid {
- use crate::layer::quad;
- use crate::quad::{color_target_state, Vertex, INDICES, INITIAL_INSTANCES};
- use crate::Buffer;
+/// The properties of a quad.
+#[derive(Clone, Copy, Debug, Pod, Zeroable)]
+#[repr(C)]
+pub struct Quad {
+ /// The position of the [`Quad`].
+ pub position: [f32; 2],
- #[derive(Debug)]
- pub struct Pipeline {
- pub pipeline: wgpu::RenderPipeline,
- }
+ /// The size of the [`Quad`].
+ pub size: [f32; 2],
- #[derive(Debug)]
- pub struct Layer {
- pub instances: Buffer<quad::Solid>,
- pub instance_count: usize,
- }
+ /// The border color of the [`Quad`], in __linear RGB__.
+ pub border_color: [f32; 4],
- impl Layer {
- pub fn new(device: &wgpu::Device) -> Self {
- let instances = Buffer::new(
- device,
- "iced_wgpu.quad.solid.buffer",
- INITIAL_INSTANCES,
- wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
- );
+ /// The border radii of the [`Quad`].
+ pub border_radius: [f32; 4],
- Self {
- instances,
- instance_count: 0,
- }
- }
-
- pub fn draw<'a>(
- &'a self,
- constants: &'a wgpu::BindGroup,
- render_pass: &mut wgpu::RenderPass<'a>,
- ) {
- #[cfg(feature = "tracing")]
- let _ = tracing::info_span!("Wgpu::Quad::Solid", "DRAW").entered();
-
- render_pass.set_bind_group(0, constants, &[]);
- render_pass.set_vertex_buffer(1, self.instances.slice(..));
-
- render_pass.draw_indexed(
- 0..INDICES.len() as u32,
- 0,
- 0..self.instance_count as u32,
- );
- }
- }
+ /// The border width of the [`Quad`].
+ pub border_width: f32,
+}
- impl Pipeline {
- pub fn new(
- device: &wgpu::Device,
- format: wgpu::TextureFormat,
- constants_layout: &wgpu::BindGroupLayout,
- ) -> Self {
- let layout = device.create_pipeline_layout(
- &wgpu::PipelineLayoutDescriptor {
- label: Some("iced_wgpu.quad.solid.pipeline"),
- push_constant_ranges: &[],
- bind_group_layouts: &[constants_layout],
- },
- );
+/// A group of [`Quad`]s rendered together.
+#[derive(Default, Debug)]
+pub struct Batch {
+ /// The solid quads of the [`Layer`].
+ solids: Vec<Solid>,
- let shader =
- device.create_shader_module(wgpu::ShaderModuleDescriptor {
- label: Some("iced_wgpu.quad.solid.shader"),
- source: wgpu::ShaderSource::Wgsl(
- std::borrow::Cow::Borrowed(include_str!(
- "shader/quad.wgsl"
- )),
- ),
- });
+ /// The gradient quads of the [`Layer`].
+ gradients: Vec<Gradient>,
- let pipeline = device.create_render_pipeline(
- &wgpu::RenderPipelineDescriptor {
- label: Some("iced_wgpu.quad.solid.pipeline"),
- layout: Some(&layout),
- vertex: wgpu::VertexState {
- module: &shader,
- entry_point: "solid_vs_main",
- buffers: &[
- Vertex::buffer_layout(),
- wgpu::VertexBufferLayout {
- array_stride: std::mem::size_of::<quad::Solid>()
- as u64,
- step_mode: wgpu::VertexStepMode::Instance,
- attributes: &wgpu::vertex_attr_array!(
- // Color
- 1 => Float32x4,
- // Position
- 2 => Float32x2,
- // Size
- 3 => Float32x2,
- // Border color
- 4 => Float32x4,
- // Border radius
- 5 => Float32x4,
- // Border width
- 6 => Float32,
- ),
- },
- ],
- },
- fragment: Some(wgpu::FragmentState {
- module: &shader,
- entry_point: "solid_fs_main",
- targets: &color_target_state(format),
- }),
- primitive: wgpu::PrimitiveState {
- topology: wgpu::PrimitiveTopology::TriangleList,
- front_face: wgpu::FrontFace::Cw,
- ..Default::default()
- },
- depth_stencil: None,
- multisample: wgpu::MultisampleState {
- count: 1,
- mask: !0,
- alpha_to_coverage_enabled: false,
- },
- multiview: None,
- },
- );
-
- Self { pipeline }
- }
- }
+ /// The quad order of the [`Layer`]; stored as a tuple of the quad type & its count.
+ order: Vec<(Kind, usize)>,
}
-mod gradient {
- use crate::layer::quad;
- use crate::quad::{color_target_state, Vertex, INDICES, INITIAL_INSTANCES};
- use crate::Buffer;
-
- #[derive(Debug)]
- pub struct Pipeline {
- pub pipeline: wgpu::RenderPipeline,
+impl Batch {
+ /// Returns true if there are no quads of any type in [`Quads`].
+ pub fn is_empty(&self) -> bool {
+ self.solids.is_empty() && self.gradients.is_empty()
}
- #[derive(Debug)]
- pub struct Layer {
- pub instances: Buffer<quad::Gradient>,
- pub instance_count: usize,
- }
-
- impl Layer {
- pub fn new(device: &wgpu::Device) -> Self {
- let instances = Buffer::new(
- device,
- "iced_wgpu.quad.gradient.buffer",
- INITIAL_INSTANCES,
- wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
- );
+ /// Adds a [`Quad`] with the provided `Background` type to the quad [`Layer`].
+ pub fn add(&mut self, quad: Quad, background: &Background) {
+ let kind = match background {
+ Background::Color(color) => {
+ self.solids.push(Solid {
+ color: color.into_linear(),
+ quad,
+ });
- Self {
- instances,
- instance_count: 0,
+ Kind::Solid
}
- }
-
- pub fn draw<'a>(
- &'a self,
- constants: &'a wgpu::BindGroup,
- render_pass: &mut wgpu::RenderPass<'a>,
- ) {
- #[cfg(feature = "tracing")]
- let _ =
- tracing::info_span!("Wgpu::Quad::Gradient", "DRAW").entered();
-
- render_pass.set_bind_group(0, constants, &[]);
- render_pass.set_vertex_buffer(1, self.instances.slice(..));
-
- render_pass.draw_indexed(
- 0..INDICES.len() as u32,
- 0,
- 0..self.instance_count as u32,
- );
- }
- }
-
- impl Pipeline {
- pub fn new(
- device: &wgpu::Device,
- format: wgpu::TextureFormat,
- constants_layout: &wgpu::BindGroupLayout,
- ) -> Self {
- let layout = device.create_pipeline_layout(
- &wgpu::PipelineLayoutDescriptor {
- label: Some("iced_wgpu.quad.gradient.pipeline"),
- push_constant_ranges: &[],
- bind_group_layouts: &[constants_layout],
- },
- );
-
- let shader =
- device.create_shader_module(wgpu::ShaderModuleDescriptor {
- label: Some("iced_wgpu.quad.gradient.shader"),
- source: wgpu::ShaderSource::Wgsl(
- std::borrow::Cow::Borrowed(include_str!(
- "shader/quad.wgsl"
- )),
+ Background::Gradient(gradient) => {
+ self.gradients.push(Gradient {
+ gradient: graphics::gradient::pack(
+ gradient,
+ Rectangle::new(quad.position.into(), quad.size.into()),
),
+ quad,
});
- let pipeline =
- device.create_render_pipeline(
- &wgpu::RenderPipelineDescriptor {
- label: Some("iced_wgpu.quad.gradient.pipeline"),
- layout: Some(&layout),
- vertex: wgpu::VertexState {
- module: &shader,
- entry_point: "gradient_vs_main",
- buffers: &[
- Vertex::buffer_layout(),
- wgpu::VertexBufferLayout {
- array_stride: std::mem::size_of::<
- quad::Gradient,
- >(
- )
- as u64,
- step_mode: wgpu::VertexStepMode::Instance,
- attributes: &wgpu::vertex_attr_array!(
- // 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,
- // Position & Scale
- 12 => Float32x4,
- // Border color
- 13 => Float32x4,
- // Border radius
- 14 => Float32x4,
- // Border width
- 15 => Float32
- ),
- },
- ],
- },
- fragment: Some(wgpu::FragmentState {
- module: &shader,
- entry_point: "gradient_fs_main",
- targets: &color_target_state(format),
- }),
- primitive: wgpu::PrimitiveState {
- topology: wgpu::PrimitiveTopology::TriangleList,
- front_face: wgpu::FrontFace::Cw,
- ..Default::default()
- },
- depth_stencil: None,
- multisample: wgpu::MultisampleState {
- count: 1,
- mask: !0,
- alpha_to_coverage_enabled: false,
- },
- multiview: None,
- },
- );
+ Kind::Gradient
+ }
+ };
- Self { pipeline }
+ match self.order.last_mut() {
+ Some((last_kind, count)) if kind == *last_kind => {
+ *count += 1;
+ }
+ _ => {
+ self.order.push((kind, 1));
+ }
}
}
}
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+/// The kind of a quad.
+enum Kind {
+ /// A solid quad
+ Solid,
+ /// A gradient quad
+ Gradient,
+}
+
fn color_target_state(
format: wgpu::TextureFormat,
) -> [Option<wgpu::ColorTargetState>; 1] {
diff --git a/wgpu/src/quad/gradient.rs b/wgpu/src/quad/gradient.rs
new file mode 100644
index 00000000..2b56d594
--- /dev/null
+++ b/wgpu/src/quad/gradient.rs
@@ -0,0 +1,175 @@
+use crate::graphics::gradient;
+use crate::quad::{self, Quad};
+use crate::Buffer;
+
+use bytemuck::{Pod, Zeroable};
+use std::ops::Range;
+
+/// A quad filled with interpolated colors.
+#[derive(Clone, Copy, Debug)]
+#[repr(C)]
+pub struct Gradient {
+ /// The background gradient data of the quad.
+ pub gradient: gradient::Packed,
+
+ /// The [`Quad`] data of the [`Gradient`].
+ pub quad: Quad,
+}
+
+#[allow(unsafe_code)]
+unsafe impl Pod for Gradient {}
+
+#[allow(unsafe_code)]
+unsafe impl Zeroable for Gradient {}
+
+#[derive(Debug)]
+pub struct Layer {
+ instances: Buffer<Gradient>,
+ instance_count: usize,
+}
+
+impl Layer {
+ pub fn new(device: &wgpu::Device) -> Self {
+ let instances = Buffer::new(
+ device,
+ "iced_wgpu.quad.gradient.buffer",
+ quad::INITIAL_INSTANCES,
+ wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
+ );
+
+ Self {
+ instances,
+ instance_count: 0,
+ }
+ }
+
+ pub fn prepare(
+ &mut self,
+ device: &wgpu::Device,
+ queue: &wgpu::Queue,
+ instances: &[Gradient],
+ ) {
+ let _ = self.instances.resize(device, instances.len());
+ let _ = self.instances.write(queue, 0, instances);
+
+ self.instance_count = instances.len();
+ }
+}
+
+#[derive(Debug)]
+pub struct Pipeline {
+ pipeline: wgpu::RenderPipeline,
+}
+
+impl Pipeline {
+ pub fn new(
+ device: &wgpu::Device,
+ format: wgpu::TextureFormat,
+ constants_layout: &wgpu::BindGroupLayout,
+ ) -> Self {
+ let layout =
+ device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
+ label: Some("iced_wgpu.quad.gradient.pipeline"),
+ push_constant_ranges: &[],
+ bind_group_layouts: &[constants_layout],
+ });
+
+ let shader =
+ device.create_shader_module(wgpu::ShaderModuleDescriptor {
+ label: Some("iced_wgpu.quad.gradient.shader"),
+ source: wgpu::ShaderSource::Wgsl(std::borrow::Cow::Borrowed(
+ include_str!("../shader/quad.wgsl"),
+ )),
+ });
+
+ let pipeline =
+ device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
+ label: Some("iced_wgpu.quad.gradient.pipeline"),
+ layout: Some(&layout),
+ vertex: wgpu::VertexState {
+ module: &shader,
+ entry_point: "gradient_vs_main",
+ buffers: &[
+ quad::Vertex::buffer_layout(),
+ wgpu::VertexBufferLayout {
+ array_stride: std::mem::size_of::<Gradient>()
+ as u64,
+ step_mode: wgpu::VertexStepMode::Instance,
+ attributes: &wgpu::vertex_attr_array!(
+ // 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,
+ // Position & Scale
+ 12 => Float32x4,
+ // Border color
+ 13 => Float32x4,
+ // Border radius
+ 14 => Float32x4,
+ // Border width
+ 15 => Float32
+ ),
+ },
+ ],
+ },
+ fragment: Some(wgpu::FragmentState {
+ module: &shader,
+ entry_point: "gradient_fs_main",
+ targets: &quad::color_target_state(format),
+ }),
+ primitive: wgpu::PrimitiveState {
+ topology: wgpu::PrimitiveTopology::TriangleList,
+ front_face: wgpu::FrontFace::Cw,
+ ..Default::default()
+ },
+ depth_stencil: None,
+ multisample: wgpu::MultisampleState {
+ count: 1,
+ mask: !0,
+ alpha_to_coverage_enabled: false,
+ },
+ multiview: None,
+ });
+
+ Self { pipeline }
+ }
+
+ pub fn render<'a>(
+ &'a self,
+ render_pass: &mut wgpu::RenderPass<'a>,
+ constants: &'a wgpu::BindGroup,
+ layer: &'a Layer,
+ range: Range<usize>,
+ ) {
+ #[cfg(feature = "tracing")]
+ let _ = tracing::info_span!("Wgpu::Quad::Gradient", "DRAW").entered();
+
+ render_pass.set_pipeline(&self.pipeline);
+ render_pass.set_bind_group(0, constants, &[]);
+ render_pass.set_vertex_buffer(1, layer.instances.slice(..));
+
+ render_pass.draw_indexed(
+ 0..quad::INDICES.len() as u32,
+ 0,
+ range.start as u32..range.end as u32,
+ );
+ }
+}
diff --git a/wgpu/src/quad/solid.rs b/wgpu/src/quad/solid.rs
new file mode 100644
index 00000000..f667c42c
--- /dev/null
+++ b/wgpu/src/quad/solid.rs
@@ -0,0 +1,149 @@
+use crate::quad::{self, Quad};
+use crate::Buffer;
+
+use bytemuck::{Pod, Zeroable};
+use std::ops::Range;
+
+/// A quad filled with a solid color.
+#[derive(Clone, Copy, Debug, Pod, Zeroable)]
+#[repr(C)]
+pub struct Solid {
+ /// The background color data of the quad.
+ pub color: [f32; 4],
+
+ /// The [`Quad`] data of the [`Solid`].
+ pub quad: Quad,
+}
+
+#[derive(Debug)]
+pub struct Layer {
+ instances: Buffer<Solid>,
+ instance_count: usize,
+}
+
+impl Layer {
+ pub fn new(device: &wgpu::Device) -> Self {
+ let instances = Buffer::new(
+ device,
+ "iced_wgpu.quad.solid.buffer",
+ quad::INITIAL_INSTANCES,
+ wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
+ );
+
+ Self {
+ instances,
+ instance_count: 0,
+ }
+ }
+
+ pub fn prepare(
+ &mut self,
+ device: &wgpu::Device,
+ queue: &wgpu::Queue,
+ instances: &[Solid],
+ ) {
+ let _ = self.instances.resize(device, instances.len());
+ let _ = self.instances.write(queue, 0, instances);
+
+ self.instance_count = instances.len();
+ }
+}
+
+#[derive(Debug)]
+pub struct Pipeline {
+ pipeline: wgpu::RenderPipeline,
+}
+
+impl Pipeline {
+ pub fn new(
+ device: &wgpu::Device,
+ format: wgpu::TextureFormat,
+ constants_layout: &wgpu::BindGroupLayout,
+ ) -> Self {
+ let layout =
+ device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
+ label: Some("iced_wgpu.quad.solid.pipeline"),
+ push_constant_ranges: &[],
+ bind_group_layouts: &[constants_layout],
+ });
+
+ let shader =
+ device.create_shader_module(wgpu::ShaderModuleDescriptor {
+ label: Some("iced_wgpu.quad.solid.shader"),
+ source: wgpu::ShaderSource::Wgsl(std::borrow::Cow::Borrowed(
+ include_str!("../shader/quad.wgsl"),
+ )),
+ });
+
+ let pipeline =
+ device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
+ label: Some("iced_wgpu.quad.solid.pipeline"),
+ layout: Some(&layout),
+ vertex: wgpu::VertexState {
+ module: &shader,
+ entry_point: "solid_vs_main",
+ buffers: &[
+ quad::Vertex::buffer_layout(),
+ wgpu::VertexBufferLayout {
+ array_stride: std::mem::size_of::<Solid>() as u64,
+ step_mode: wgpu::VertexStepMode::Instance,
+ attributes: &wgpu::vertex_attr_array!(
+ // Color
+ 1 => Float32x4,
+ // Position
+ 2 => Float32x2,
+ // Size
+ 3 => Float32x2,
+ // Border color
+ 4 => Float32x4,
+ // Border radius
+ 5 => Float32x4,
+ // Border width
+ 6 => Float32,
+ ),
+ },
+ ],
+ },
+ fragment: Some(wgpu::FragmentState {
+ module: &shader,
+ entry_point: "solid_fs_main",
+ targets: &quad::color_target_state(format),
+ }),
+ primitive: wgpu::PrimitiveState {
+ topology: wgpu::PrimitiveTopology::TriangleList,
+ front_face: wgpu::FrontFace::Cw,
+ ..Default::default()
+ },
+ depth_stencil: None,
+ multisample: wgpu::MultisampleState {
+ count: 1,
+ mask: !0,
+ alpha_to_coverage_enabled: false,
+ },
+ multiview: None,
+ });
+
+ Self { pipeline }
+ }
+
+ pub fn render<'a>(
+ &'a self,
+ render_pass: &mut wgpu::RenderPass<'a>,
+ constants: &'a wgpu::BindGroup,
+ layer: &'a Layer,
+ range: Range<usize>,
+ ) {
+ #[cfg(feature = "tracing")]
+ let _ = tracing::info_span!("Wgpu::Quad::Solid", "DRAW").entered();
+
+ render_pass.set_pipeline(&self.pipeline);
+ render_pass.set_bind_group(0, constants, &[]);
+ render_pass.set_vertex_buffer(1, layer.instances.slice(..));
+
+ render_pass.draw_indexed(
+ 0..quad::INDICES.len() as u32,
+ 0,
+ range.start as u32..range.end as u32,
+ );
+ }
+}