1use crate::Buffer;
2use crate::graphics::color;
3use crate::quad::{self, Quad};
4
5use bytemuck::{Pod, Zeroable};
6use std::ops::Range;
7
8#[derive(Clone, Copy, Debug, Pod, Zeroable)]
10#[repr(C)]
11pub struct Solid {
12 pub color: color::Packed,
14
15 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 0 => Float32x4,
101 1 => Float32x2,
103 2 => Float32x2,
105 3 => Float32x4,
107 4 => Float32x4,
109 5 => Float32,
111 6 => Float32x4,
113 7 => Float32x2,
115 8 => Float32,
117 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}