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, Clone)]
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/color.wgsl"),
78                        "\n",
79                        include_str!("../shader/quad.wgsl"),
80                        "\n",
81                        include_str!("../shader/vertex.wgsl"),
82                        "\n",
83                        include_str!("../shader/quad/solid.wgsl"),
84                    ),
85                )),
86            });
87
88        let pipeline =
89            device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
90                label: Some("iced_wgpu.quad.solid.pipeline"),
91                layout: Some(&layout),
92                vertex: wgpu::VertexState {
93                    module: &shader,
94                    entry_point: Some("solid_vs_main"),
95                    buffers: &[wgpu::VertexBufferLayout {
96                        array_stride: std::mem::size_of::<Solid>() as u64,
97                        step_mode: wgpu::VertexStepMode::Instance,
98                        attributes: &wgpu::vertex_attr_array!(
99                            // Color
100                            0 => Float32x4,
101                            // Position
102                            1 => Float32x2,
103                            // Size
104                            2 => Float32x2,
105                            // Border color
106                            3 => Float32x4,
107                            // Border radius
108                            4 => Float32x4,
109                            // Border width
110                            5 => Float32,
111                            // Shadow color
112                            6 => Float32x4,
113                            // Shadow offset
114                            7 => Float32x2,
115                            // Shadow blur radius
116                            8 => Float32,
117                            // Snap
118                            9 => Uint32,
119                        ),
120                    }],
121                    compilation_options:
122                        wgpu::PipelineCompilationOptions::default(),
123                },
124                fragment: Some(wgpu::FragmentState {
125                    module: &shader,
126                    entry_point: Some("solid_fs_main"),
127                    targets: &quad::color_target_state(format),
128                    compilation_options:
129                        wgpu::PipelineCompilationOptions::default(),
130                }),
131                primitive: wgpu::PrimitiveState {
132                    topology: wgpu::PrimitiveTopology::TriangleList,
133                    front_face: wgpu::FrontFace::Cw,
134                    ..Default::default()
135                },
136                depth_stencil: None,
137                multisample: wgpu::MultisampleState {
138                    count: 1,
139                    mask: !0,
140                    alpha_to_coverage_enabled: false,
141                },
142                multiview: None,
143                cache: None,
144            });
145
146        Self { pipeline }
147    }
148
149    pub fn render<'a>(
150        &'a self,
151        render_pass: &mut wgpu::RenderPass<'a>,
152        constants: &'a wgpu::BindGroup,
153        layer: &'a Layer,
154        range: Range<usize>,
155    ) {
156        render_pass.set_pipeline(&self.pipeline);
157        render_pass.set_bind_group(0, constants, &[]);
158        render_pass.set_vertex_buffer(0, layer.instances.slice(..));
159
160        render_pass.draw(0..6, range.start as u32..range.end as u32);
161    }
162}