iced_wgpu/quad/
solid.rs

1use crate::Buffer;
2use crate::graphics::color;
3use crate::quad::{self, Quad};
4
5use bytemuck::{Pod, Zeroable};
6use std::ops::Range;
7
8/// A quad filled with a solid color.
9#[derive(Clone, Copy, Debug, Pod, Zeroable)]
10#[repr(C)]
11pub struct Solid {
12    /// The background color data of the quad.
13    pub color: color::Packed,
14
15    /// The [`Quad`] data of the [`Solid`].
16    pub quad: Quad,
17}
18
19#[derive(Debug)]
20pub struct Layer {
21    instances: Buffer<Solid>,
22    instance_count: usize,
23}
24
25impl Layer {
26    pub fn new(device: &wgpu::Device) -> Self {
27        let instances = Buffer::new(
28            device,
29            "iced_wgpu.quad.solid.buffer",
30            quad::INITIAL_INSTANCES,
31            wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
32        );
33
34        Self {
35            instances,
36            instance_count: 0,
37        }
38    }
39
40    pub fn prepare(
41        &mut self,
42        device: &wgpu::Device,
43        encoder: &mut wgpu::CommandEncoder,
44        belt: &mut wgpu::util::StagingBelt,
45        instances: &[Solid],
46    ) {
47        let _ = self.instances.resize(device, instances.len());
48        let _ = self.instances.write(device, encoder, belt, 0, instances);
49
50        self.instance_count = instances.len();
51    }
52}
53
54#[derive(Debug)]
55pub struct Pipeline {
56    pipeline: wgpu::RenderPipeline,
57}
58
59impl Pipeline {
60    pub fn new(
61        device: &wgpu::Device,
62        format: wgpu::TextureFormat,
63        constants_layout: &wgpu::BindGroupLayout,
64    ) -> Self {
65        let layout =
66            device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
67                label: Some("iced_wgpu.quad.solid.pipeline"),
68                push_constant_ranges: &[],
69                bind_group_layouts: &[constants_layout],
70            });
71
72        let shader =
73            device.create_shader_module(wgpu::ShaderModuleDescriptor {
74                label: Some("iced_wgpu.quad.solid.shader"),
75                source: wgpu::ShaderSource::Wgsl(std::borrow::Cow::Borrowed(
76                    concat!(
77                        include_str!("../shader/quad.wgsl"),
78                        "\n",
79                        include_str!("../shader/vertex.wgsl"),
80                        "\n",
81                        include_str!("../shader/quad/solid.wgsl"),
82                    ),
83                )),
84            });
85
86        let pipeline =
87            device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
88                label: Some("iced_wgpu.quad.solid.pipeline"),
89                layout: Some(&layout),
90                vertex: wgpu::VertexState {
91                    module: &shader,
92                    entry_point: Some("solid_vs_main"),
93                    buffers: &[wgpu::VertexBufferLayout {
94                        array_stride: std::mem::size_of::<Solid>() as u64,
95                        step_mode: wgpu::VertexStepMode::Instance,
96                        attributes: &wgpu::vertex_attr_array!(
97                            // Color
98                            0 => Float32x4,
99                            // Position
100                            1 => Float32x2,
101                            // Size
102                            2 => Float32x2,
103                            // Border color
104                            3 => Float32x4,
105                            // Border radius
106                            4 => Float32x4,
107                            // Border width
108                            5 => Float32,
109                            // Shadow color
110                            6 => Float32x4,
111                            // Shadow offset
112                            7 => Float32x2,
113                            // Shadow blur radius
114                            8 => Float32,
115                        ),
116                    }],
117                    compilation_options:
118                        wgpu::PipelineCompilationOptions::default(),
119                },
120                fragment: Some(wgpu::FragmentState {
121                    module: &shader,
122                    entry_point: Some("solid_fs_main"),
123                    targets: &quad::color_target_state(format),
124                    compilation_options:
125                        wgpu::PipelineCompilationOptions::default(),
126                }),
127                primitive: wgpu::PrimitiveState {
128                    topology: wgpu::PrimitiveTopology::TriangleList,
129                    front_face: wgpu::FrontFace::Cw,
130                    ..Default::default()
131                },
132                depth_stencil: None,
133                multisample: wgpu::MultisampleState {
134                    count: 1,
135                    mask: !0,
136                    alpha_to_coverage_enabled: false,
137                },
138                multiview: None,
139                cache: None,
140            });
141
142        Self { pipeline }
143    }
144
145    pub fn render<'a>(
146        &'a self,
147        render_pass: &mut wgpu::RenderPass<'a>,
148        constants: &'a wgpu::BindGroup,
149        layer: &'a Layer,
150        range: Range<usize>,
151    ) {
152        render_pass.set_pipeline(&self.pipeline);
153        render_pass.set_bind_group(0, constants, &[]);
154        render_pass.set_vertex_buffer(0, layer.instances.slice(..));
155
156        render_pass.draw(0..6, range.start as u32..range.end as u32);
157    }
158}