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 = 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 0 => Float32x4,
96 1 => Float32x2,
98 2 => Float32x2,
100 3 => Float32x4,
102 4 => Float32x4,
104 5 => Float32,
106 6 => Float32x4,
108 7 => Float32x2,
110 8 => Float32,
112 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}