1use crate::data_structures::texture::{self, Texture};
2
3#[repr(C)]
4#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
5pub struct Vertex {
6 pub position: [f32; 3],
7 pub tex_coords: [f32; 2],
8}
9
10impl Vertex {
11 pub fn desc() -> wgpu::VertexBufferLayout<'static> {
12 use std::mem;
13 wgpu::VertexBufferLayout {
14 array_stride: mem::size_of::<Vertex>() as wgpu::BufferAddress,
15 step_mode: wgpu::VertexStepMode::Vertex,
16 attributes: &[
17 wgpu::VertexAttribute {
18 offset: 0,
19 shader_location: 0,
20 format: wgpu::VertexFormat::Float32x3,
21 },
22 wgpu::VertexAttribute {
23 offset: mem::size_of::<[f32; 3]>() as wgpu::BufferAddress,
24 shader_location: 1,
25 format: wgpu::VertexFormat::Float32x2,
26 },
27 ],
28 }
29 }
30}
31
32#[allow(dead_code)]
33fn mk_shader(device: &wgpu::Device) -> wgpu::ShaderModule {
34 device.create_shader_module(wgpu::ShaderModuleDescriptor {
35 label: Some("Shader"),
36 source: wgpu::ShaderSource::Wgsl(include_str!("icon.wgsl").into()),
37 })
38}
39
40pub fn mk_bind_group_layout(device: &wgpu::Device) -> wgpu::BindGroupLayout {
41 device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
42 entries: &[
43 wgpu::BindGroupLayoutEntry {
44 binding: 0,
45 visibility: wgpu::ShaderStages::FRAGMENT,
46 ty: wgpu::BindingType::Texture {
47 multisampled: false,
48 view_dimension: wgpu::TextureViewDimension::D2,
49 sample_type: wgpu::TextureSampleType::Float { filterable: true },
50 },
51 count: None,
52 },
53 wgpu::BindGroupLayoutEntry {
54 binding: 1,
55 visibility: wgpu::ShaderStages::FRAGMENT,
56 ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
57 count: None,
58 },
59 ],
60 label: Some("Menu texture_bind_group_layout"),
61 })
62}
63
64pub fn mk_bind_group(
69 device: &wgpu::Device,
70 texture_atlas: &Texture,
71 texture_bind_group_layout: &wgpu::BindGroupLayout,
72) -> wgpu::BindGroup {
73 device.create_bind_group(&wgpu::BindGroupDescriptor {
74 layout: texture_bind_group_layout,
75 entries: &[
76 wgpu::BindGroupEntry {
77 binding: 0,
78 resource: wgpu::BindingResource::TextureView(&texture_atlas.view),
79 },
80 wgpu::BindGroupEntry {
81 binding: 1,
82 resource: wgpu::BindingResource::Sampler(texture_atlas.sampler.as_ref().unwrap()),
83 },
84 ],
85 label: Some("diffuse_bind_group"),
86 })
87}
88
89pub fn mk_screen_size_bind_group_layout(device: &wgpu::Device) -> wgpu::BindGroupLayout {
90 device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
91 entries: &[wgpu::BindGroupLayoutEntry {
92 binding: 0,
93 visibility: wgpu::ShaderStages::VERTEX,
94 ty: wgpu::BindingType::Buffer {
95 ty: wgpu::BufferBindingType::Uniform,
96 has_dynamic_offset: false,
97 min_binding_size: None,
98 },
99 count: None,
100 }],
101 label: Some("screen_size_bind_group_layout"),
102 })
103}
104
105pub fn mk_screen_size_bind_group(
106 device: &wgpu::Device,
107 buffer: &wgpu::Buffer,
108 layout: &wgpu::BindGroupLayout,
109) -> wgpu::BindGroup {
110 device.create_bind_group(&wgpu::BindGroupDescriptor {
111 layout,
112 entries: &[wgpu::BindGroupEntry {
113 binding: 0,
114 resource: buffer.as_entire_binding(),
115 }],
116 label: Some("screen_size_bind_group"),
117 })
118}
119
120fn mk_pipeline_layout(
121 device: &wgpu::Device,
122 texture_bind_group_layout: wgpu::BindGroupLayout,
123 screen_size_bind_group_layout: &wgpu::BindGroupLayout,
124) -> wgpu::PipelineLayout {
125 device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
126 label: Some("Menu Render Pipeline Layout"),
127 bind_group_layouts: &[&texture_bind_group_layout, screen_size_bind_group_layout],
128 ..Default::default()
129 })
130}
131
132fn mk_texture_bind_group_layout(device: &wgpu::Device) -> wgpu::BindGroupLayout {
133 device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
134 entries: &[
135 wgpu::BindGroupLayoutEntry {
136 binding: 0,
137 visibility: wgpu::ShaderStages::FRAGMENT,
138 ty: wgpu::BindingType::Texture {
139 multisampled: false,
140 view_dimension: wgpu::TextureViewDimension::D2,
141 sample_type: wgpu::TextureSampleType::Float { filterable: true },
142 },
143 count: None,
144 },
145 wgpu::BindGroupLayoutEntry {
146 binding: 1,
147 visibility: wgpu::ShaderStages::FRAGMENT,
148 ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
149 count: None,
150 },
151 ],
152 label: Some("Menu texture_bind_group_layout"),
153 })
154}
155
156fn mk_render_pipeline(
157 device: &wgpu::Device,
158 config: &wgpu::SurfaceConfiguration,
159 render_pipeline_layout: &wgpu::PipelineLayout,
160 shader: &wgpu::ShaderModule,
161 sample_count: u32,
162) -> wgpu::RenderPipeline {
163 device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
164 label: Some("Menu Render Pipeline"),
165 layout: Some(&render_pipeline_layout),
166 vertex: wgpu::VertexState {
167 module: shader,
168 entry_point: Some("vs_main"),
169 buffers: &[Vertex::desc()],
170 compilation_options: Default::default(),
171 },
172 fragment: Some(wgpu::FragmentState {
173 module: shader,
174 entry_point: Some("fs_main"),
175 targets: &[Some(wgpu::ColorTargetState {
176 format: config.format,
177 blend: Some(wgpu::BlendState {
178 color: wgpu::BlendComponent::OVER,
179 alpha: wgpu::BlendComponent::OVER,
180 }),
181 write_mask: wgpu::ColorWrites::ALL,
182 })],
183 compilation_options: Default::default(),
184 }),
185 primitive: wgpu::PrimitiveState {
186 topology: wgpu::PrimitiveTopology::TriangleList,
187 strip_index_format: None,
188 front_face: wgpu::FrontFace::Ccw,
189 cull_mode: Some(wgpu::Face::Back),
190 polygon_mode: wgpu::PolygonMode::Fill,
191 unclipped_depth: false,
192 conservative: false,
193 },
194 depth_stencil: Some(wgpu::DepthStencilState {
195 format: texture::Texture::DEPTH_FORMAT,
196 depth_write_enabled: true,
197 depth_compare: wgpu::CompareFunction::LessEqual,
198 stencil: wgpu::StencilState::default(),
199 bias: wgpu::DepthBiasState::default(),
200 }),
201 multisample: wgpu::MultisampleState {
202 count: sample_count,
203 mask: !0,
204 alpha_to_coverage_enabled: false,
205 },
206 multiview_mask: None,
207 cache: None,
209 })
210}
211
212pub fn mk_gui_pipeline(device: &wgpu::Device, config: &wgpu::SurfaceConfiguration, screen_size_layout: &wgpu::BindGroupLayout, sample_count: u32) -> wgpu::RenderPipeline {
213 let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
214 label: Some("Shader"),
215 source: wgpu::ShaderSource::Wgsl(include_str!("icon.wgsl").into()),
216 });
217 let texture_bind_group_layout = mk_texture_bind_group_layout(device);
218 let render_pipeline_layout = &mk_pipeline_layout(device, texture_bind_group_layout, screen_size_layout);
219 mk_render_pipeline(device, config, render_pipeline_layout, &shader, sample_count)
220}