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