summaryrefslogtreecommitdiffstats
path: root/wgpu/src/quad.rs
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2023-05-30 00:56:52 +0200
committerLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2023-05-30 01:08:34 +0200
commitfe9da174cafffbd77eb351c51ba017cf039a4cf4 (patch)
tree0921ada9a8907ddfd46a360c21b0fd224d81216c /wgpu/src/quad.rs
parenteb6c663420a28e087c91c39e376db3c294b5aea1 (diff)
downloadiced-fe9da174cafffbd77eb351c51ba017cf039a4cf4.tar.gz
iced-fe9da174cafffbd77eb351c51ba017cf039a4cf4.tar.bz2
iced-fe9da174cafffbd77eb351c51ba017cf039a4cf4.zip
Move `layer::quad` types to `quad` module
Not sure why I split these to begin with!
Diffstat (limited to 'wgpu/src/quad.rs')
-rw-r--r--wgpu/src/quad.rs390
1 files changed, 108 insertions, 282 deletions
diff --git a/wgpu/src/quad.rs b/wgpu/src/quad.rs
index 065da153..375b0cd7 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::quad;
+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,
- quads: &quad::Layer,
+ quads: &Batch,
transformation: Transformation,
scale: f32,
) {
@@ -87,7 +94,7 @@ impl Pipeline {
&'a self,
layer: usize,
bounds: Rectangle<u32>,
- quads: &quad::Layer,
+ quads: &Batch,
render_pass: &mut wgpu::RenderPass<'a>,
) {
if let Some(layer) = self.layers.get(layer) {
@@ -106,9 +113,9 @@ impl Pipeline {
let mut solid_offset = 0;
let mut gradient_offset = 0;
- for (quad_order, count) in quads.ordering() {
+ for (quad_order, count) in &quads.order {
match quad_order {
- quad::Order::Solid => {
+ Order::Solid => {
render_pass.set_pipeline(&self.solid.pipeline);
layer.solid.draw(
&layer.constants,
@@ -117,7 +124,7 @@ impl Pipeline {
);
solid_offset += count;
}
- quad::Order::Gradient => {
+ Order::Gradient => {
render_pass.set_pipeline(&self.gradient.pipeline);
layer.gradient.draw(
&layer.constants,
@@ -177,7 +184,7 @@ impl Layer {
&mut self,
device: &wgpu::Device,
queue: &wgpu::Queue,
- quads: &quad::Layer,
+ quads: &Batch,
transformation: Transformation,
scale: f32,
) {
@@ -192,303 +199,122 @@ impl Layer {
bytemuck::bytes_of(&uniforms),
);
- let solids = quads.solids();
- let gradients = quads.gradients();
+ let _ = self.solid.instances.resize(device, quads.solids.len());
+ let _ = self
+ .gradient
+ .instances
+ .resize(device, quads.gradients.len());
+
+ let _ = self.solid.instances.write(queue, 0, &quads.solids);
+ let _ = self.gradient.instances.write(queue, 0, &quads.gradients);
- let _ = self.solid.instances.resize(device, solids.len());
- let _ = self.gradient.instances.resize(device, gradients.len());
- let _ = self.solid.instances.write(queue, 0, solids);
- self.solid.instance_count = solids.len();
- let _ = self.gradient.instances.write(queue, 0, gradients);
- self.gradient.instance_count = gradients.len();
+ self.solid.instance_count = quads.solids.len();
+ self.gradient.instance_count = quads.gradients.len();
}
}
-mod solid {
- use crate::layer::quad;
- use crate::quad::{color_target_state, Vertex, INDICES, INITIAL_INSTANCES};
- use crate::Buffer;
- use std::ops::Range;
-
- #[derive(Debug)]
- pub struct Pipeline {
- pub pipeline: wgpu::RenderPipeline,
- }
+/// 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 Layer {
- pub instances: Buffer<quad::Solid>,
- pub instance_count: usize,
- }
+ /// The size of the [`Quad`].
+ pub size: [f32; 2],
- 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 color of the [`Quad`], in __linear RGB__.
+ pub border_color: [f32; 4],
- Self {
- instances,
- instance_count: 0,
- }
- }
+ /// The border radii of the [`Quad`].
+ pub border_radius: [f32; 4],
- pub fn draw<'a>(
- &'a self,
- constants: &'a wgpu::BindGroup,
- render_pass: &mut wgpu::RenderPass<'a>,
- range: Range<usize>,
- ) {
- #[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,
- range.start as u32..range.end 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,
- },
- );
+ /// The quad order of the [`Layer`]; stored as a tuple of the quad type & its count.
+ order: Vec<(Order, usize)>,
- Self { pipeline }
- }
- }
+ /// The last index of quad ordering.
+ index: usize,
}
-mod gradient {
- use crate::layer::quad;
- use crate::quad::{color_target_state, Vertex, INDICES, INITIAL_INSTANCES};
- use crate::Buffer;
- use std::ops::Range;
-
- #[derive(Debug)]
- pub struct Pipeline {
- pub pipeline: wgpu::RenderPipeline,
- }
-
- #[derive(Debug)]
- pub struct Layer {
- pub instances: Buffer<quad::Gradient>,
- pub instance_count: usize,
+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()
}
- 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 quad_order = match background {
+ Background::Color(color) => {
+ self.solids.push(Solid {
+ color: color.into_linear(),
+ quad,
+ });
- Self {
- instances,
- instance_count: 0,
+ Order::Solid
}
- }
-
- pub fn draw<'a>(
- &'a self,
- constants: &'a wgpu::BindGroup,
- render_pass: &mut wgpu::RenderPass<'a>,
- range: Range<usize>,
- ) {
- #[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,
- range.start as u32..range.end 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) => {
+ let quad = 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,
- },
- );
+ self.gradients.push(quad);
+ Order::Gradient
+ }
+ };
- Self { pipeline }
+ match (self.order.get_mut(self.index), quad_order) {
+ (Some((quad_order, count)), Order::Solid) => match quad_order {
+ Order::Solid => {
+ *count += 1;
+ }
+ Order::Gradient => {
+ self.order.push((Order::Solid, 1));
+ self.index += 1;
+ }
+ },
+ (Some((quad_order, count)), Order::Gradient) => match quad_order {
+ Order::Solid => {
+ self.order.push((Order::Gradient, 1));
+ self.index += 1;
+ }
+ Order::Gradient => {
+ *count += 1;
+ }
+ },
+ (None, _) => {
+ self.order.push((quad_order, 1));
+ }
}
}
}
+#[derive(Debug, Copy, Clone)]
+/// The identifier of a quad, used for ordering.
+enum Order {
+ /// A solid quad
+ Solid,
+ /// A gradient quad
+ Gradient,
+}
+
fn color_target_state(
format: wgpu::TextureFormat,
) -> [Option<wgpu::ColorTargetState>; 1] {