1use winit::{
3 event::*,
4 event_loop::{ ControlFlow, EventLoop },
5 window::{ WindowBuilder, Window },
6};
7
8struct State {
9
10 instance: wgpu::Instance,
11 adapter: wgpu::Adapter,
12 surface: wgpu::Surface,
13 device: wgpu::Device,
14 queue: wgpu::Queue,
15 config: wgpu::SurfaceConfiguration,
16 size: winit::dpi::PhysicalSize<u32>,
17 clear_color: wgpu::Color,
18 render_pipeline: wgpu::RenderPipeline,
19
20}
21
22impl State {
23
24 async fn new(window: &Window) -> Self {
25
26 let size = window.inner_size();
27 let instance = wgpu::Instance::new(wgpu::Backends::all());
28 let surface = unsafe { instance.create_surface(window) };
29 let adapter = instance.request_adapter(
30
31 &wgpu::RequestAdapterOptions {
32
33 power_preference: wgpu::PowerPreference::default(),
34 compatible_surface: Some(&surface),
35 force_fallback_adapter: false,
36
37 },
38 ).await.unwrap();
39
40 let (device, queue) = adapter.request_device(
41
42 &wgpu::DeviceDescriptor {
43
44 label: None,
45 features: wgpu::Features::empty(),
46 limits: wgpu::Limits::default(),
47
48 },
49 None,
50 ).await.unwrap();
51
52 let config = wgpu::SurfaceConfiguration {
53
54 usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
55 format: surface.get_supported_formats(&adapter)[0],
56 width: size.width,
57 height: size.height,
58 present_mode: wgpu::PresentMode::Fifo,
59
60 };
61 surface.configure(&device, &config);
62
63 let clear_color = wgpu::Color::BLACK;
64
65 let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
66
67 label: Some("Shader"),
68 source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
69
70 });
71
72 let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
73
74 label: Some("Render Pipeline Laypout"),
75 bind_group_layouts: &[],
76 push_constant_ranges: &[],
77
78 });
79
80 let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
81
82 label: Some("Render Pipeline"),
83 layout: Some(&render_pipeline_layout),
84 vertex: wgpu::VertexState {
85
86 module: &shader,
87 entry_point: "vs_main",
88 buffers: &[],
89
90 },
91 fragment: Some(wgpu::FragmentState {
92
93 module: &shader,
94 entry_point: "fs_main",
95 targets: &[Some(wgpu::ColorTargetState {
96
97 format: config.format,
98 blend: Some(wgpu::BlendState::REPLACE),
99 write_mask: wgpu::ColorWrites::ALL,
100
101 })],
102
103 }),
104 primitive: wgpu::PrimitiveState {
105
106 topology: wgpu::PrimitiveTopology::TriangleList,
107 strip_index_format: None,
108 front_face: wgpu::FrontFace::Ccw,
109 cull_mode: Some(wgpu::Face::Back),
110 polygon_mode: wgpu::PolygonMode::Fill,
111 unclipped_depth: false,
112 conservative: false,
113
114 },
115 depth_stencil: None,
116 multisample: wgpu::MultisampleState {
117
118 count: 1,
119 mask: !0,
120 alpha_to_coverage_enabled: false,
121
122 },
123 multiview: None,
124
125 });
126
127 Self {
128
129 instance,
130 adapter,
131 surface,
132 device,
133 queue,
134 config,
135 size,
136 clear_color,
137 render_pipeline,
138
139 }
140 }
141
142 fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
143
144 if new_size.width > 0 && new_size.height > 0 {
145
146 self.size = new_size;
147 self.config.width = new_size.width;
148 self.config.height = new_size.height;
149 self.surface.configure(&self.device, &self.config);
150
151 }
152 }
153
154 fn input(&mut self, event: &WindowEvent) -> bool {
155
156 match event {
157
158 WindowEvent::CursorMoved { position, .. } => {
159
160 self.clear_color = wgpu::Color {
161
162 r: position.x as f64 / self.size.width as f64,
163 g: position.y as f64 / self.size.height as f64,
164 b: 1.0,
165 a: 1.0,
166
167 };
168 true
169
170 }
171 _ => false,
172 }
173 }
174
175 fn update(&mut self) {
176
177
178
179 }
180
181 fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
182
183 let output = self.surface.get_current_texture()?;
184 let view = output.texture.create_view(&wgpu::TextureViewDescriptor::default());
185 let mut encoder = self.device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
186
187 label: Some("Render Encoder"),
188
189 });
190
191 {
192 let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
193
194 label: Some("Render Pass"),
195 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
196
197 view: &view,
198 resolve_target: None,
199 ops: wgpu::Operations {
200
201 load: wgpu::LoadOp::Clear(self.clear_color),
202 store: true,
203
204 },
205 })],
206 depth_stencil_attachment: None,
207
208 });
209
210 render_pass.set_pipeline(&self.render_pipeline);
211 render_pass.draw(0..3, 0..1);
212 }
213
214 self.queue.submit(std::iter::once(encoder.finish()));
215 output.present();
216
217 Ok(())
218 }
219}
220
221pub async fn run() {
222
223 env_logger::init();
224 let event_loop = EventLoop::new();
225 let window = WindowBuilder::new().build(&event_loop).unwrap();
226
227 let mut state = State::new(&window).await;
228
229 event_loop.run(move |event, _, control_flow| {
230
231 match event {
232
233 Event::WindowEvent {
234
235 ref event,
236 window_id,
237
238 } if window_id == window.id() => if !state.input(event) {
239
240 match event {
241
242 WindowEvent::CloseRequested | WindowEvent::KeyboardInput {
243
244 input: KeyboardInput {
245
246 state: ElementState::Pressed,
247 virtual_keycode: Some(VirtualKeyCode::Escape),
248 ..
249
250 },
251 ..
252
253 } => *control_flow = ControlFlow::Exit,
254 WindowEvent::Resized(physical_size) => {
255
256 state.resize(*physical_size);
257
258 },
259 WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
260
261 state.resize(**new_inner_size);
262
263 },
264 _ => {},
265
266 }
267 }
268 Event::RedrawRequested(window_id) if window_id == window.id() => {
269
270 state.update();
271 match state.render() {
272
273 Ok(_) => {}
274 Err(wgpu::SurfaceError::Lost) => state.resize(state.size),
275 Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
276 Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"),
277 Err(e) => eprintln!("{e:?}"),
278
279 }
280
281 },
282 Event::MainEventsCleared => {
283
284 window.request_redraw();
285
286 }
287 _ => {}
288 }
289 });
290}