1pub mod shape;
2pub mod uniform;
3pub mod vertex;
4
5use std::collections::HashMap;
6use std::sync::Arc;
7use std::sync::Mutex;
8use sketchbook::aspects::*;
9use sketchbook::Point2;
10use wgpu::util::DeviceExt;
11use winit::event::VirtualKeyCode;
12
13use wgpu::RenderPipeline;
14use wgpu::Surface;
15use wgpu::SurfaceConfiguration;
16use wgpu::{Device, Queue};
17use winit::dpi::{PhysicalPosition, PhysicalSize};
18use winit::event::ElementState;
19use winit::event::MouseButton;
20use winit::event::WindowEvent;
21use winit::window::Window;
22
23use crate::fifo::FiFoPush;
24
25use super::vec_buffer::VecBuffer;
26use super::{DisplayInfo, Events};
27use std::time::Instant;
28
29use shape::*;
30use uniform::*;
31use vertex::*;
32
33use crate::double_buffer::*;
34use super::device::*;
35
36#[derive(Default)]
37pub struct Frame {
38 pub background: wgpu::Color,
39 pub buffer: Vec<ShapeRaw>,
40}
41
42pub struct Display {
43 event_queue: FiFoPush<Events>,
44 frame: DoubleBufferRead<Frame>,
45 info: Arc<Mutex<DisplayInfo>>,
46
47 shape_buffer: VecBuffer<ShapeRaw>,
48 background: wgpu::Color,
49
50 device: WgpuDevice,
51 render_pipeline: RenderPipeline,
52
53 vertex_buffer: wgpu::Buffer,
54 screen_buffer: wgpu::Buffer,
55 screen_bind_group: wgpu::BindGroup,
56 index_buffer: wgpu::Buffer,
57}
58
59const VERTICES: &[VertexRaw] = &[
60 Vertex { x: 1., y: 1. }.to_raw(),
61 Vertex { x: -1., y: 1. }.to_raw(),
62 Vertex { x: 1., y: -1. }.to_raw(),
63 Vertex { x: -1., y: -1. }.to_raw(),
64];
65
66const INDICES: &[u16] = &[0, 1, 2, 1, 2, 3];
67
68impl Display {
69 pub fn new(
70 instance: &wgpu::Instance,
71 window: Window,
72 event_queue: FiFoPush<Events>,
73 frame: DoubleBufferRead<Frame>,
74 info: Arc<Mutex<DisplayInfo>>,
75 ) -> Display {
76 let surface = WgpuSurface::for_window(instance, window);
77 let adapter = surface.best_adapter(instance, WgpuSurface::prefer_high_power).expect("Failed to get adapter.");
78 println!("Adapter: {:?}", adapter.adapter.get_info());
79 let mut device = pollster::block_on(adapter.create_device()).expect("Failed to get device.");
80
81 let vertex_buffer = device.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
82 label: Some("Vertex Buffer"),
83 contents: bytemuck::cast_slice(VERTICES),
84 usage: wgpu::BufferUsages::VERTEX,
85 });
86
87 let index_buffer = device.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
88 label: Some("Index Buffer"),
89 contents: bytemuck::cast_slice(INDICES),
90 usage: wgpu::BufferUsages::INDEX,
91 });
92
93 let shape_buffer = VecBuffer::new(
94 &device.device,
95 wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
96 );
97
98 let screen_uniform = Uniform {
99 surface_size: device.inner_size(),
100 scale: device.scale_factor(),
101 }
102 .to_raw();
103 let screen_buffer = device.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
104 label: Some("Screen Buffer"),
105 contents: bytemuck::cast_slice(&[screen_uniform]),
106 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
107 });
108
109 let screen_bind_group_layout =
110 device.device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
111 entries: &[wgpu::BindGroupLayoutEntry {
112 binding: 0,
113 visibility: wgpu::ShaderStages::VERTEX,
114 ty: wgpu::BindingType::Buffer {
115 ty: wgpu::BufferBindingType::Uniform,
116 has_dynamic_offset: false,
117 min_binding_size: None,
118 },
119 count: None,
120 }],
121 label: Some("screen_bind_group_layout"),
122 });
123
124 let screen_bind_group = device.device.create_bind_group(&wgpu::BindGroupDescriptor {
125 layout: &screen_bind_group_layout,
126 entries: &[wgpu::BindGroupEntry {
127 binding: 0,
128 resource: screen_buffer.as_entire_binding(),
129 }],
130 label: Some("screen_bind_group"),
131 });
132
133 let render_pipeline = device.create_pipeline(
134 include_str!("shader.wgsl"),
135 &[&screen_bind_group_layout],
136 &[VertexRaw::description(), ShapeRaw::description()],
137 );
138
139 Self {
140 vertex_buffer,
141 screen_buffer,
142 screen_bind_group,
143 index_buffer,
144 frame,
145 event_queue,
146 info,
147 device,
148 render_pipeline,
149 shape_buffer,
150 background: wgpu::Color { r: 0.1, g: 0.2, b: 0.3, a: 1.0 },
151 }
152 }
153
154 pub fn trigger_draw(&mut self) {
155 self.event_queue.push(Events::Draw(draw::env_api::Events::Draw));
156 }
157
158 pub fn mouse_move(&mut self, position: PhysicalPosition<f64>) {
159 let position = position.to_logical(self.device.scale_factor());
160 self.event_queue.push(Events::Mouse(mouse::env_api::Events::MoveAbsolute(Point2 {
161 x: position.x,
162 y: position.y,
163 })));
164 }
165
166 pub fn mouse_input(&mut self, state: ElementState, button: MouseButton) {
167 let event = match (state, button) {
168 (ElementState::Pressed, button) => {
169 mouse::env_api::Events::Press(button)
170 }
171 (ElementState::Released, button) => {
172 mouse::env_api::Events::Release(button)
173 }
174 };
175 self.event_queue.push(Events::Mouse(event));
176 }
177
178 pub fn keyboard_input(&mut self, keycode: VirtualKeyCode, state: ElementState) {
179 match state {
180 ElementState::Pressed => {
181 self.event_queue
182 .push(Events::Keyboard(keyboard::env_api::Events::Press(keycode)));
183 }
184 ElementState::Released => {
185 self.event_queue
186 .push(Events::Keyboard(keyboard::env_api::Events::Release(keycode)));
187 }
188 }
189 }
190
191 pub fn close(&mut self) {
192 self.event_queue.push(Events::Close);
193 }
194
195 pub fn window_request_redraw(&mut self) {
196 self.device.request_redraw();
197 }
198
199 pub fn handle_window_event(
200 &mut self,
201 event: &WindowEvent<'_>,
202 ) {
203 match event {
204 WindowEvent::Resized(size) => {
205 self.resize(*size);
206 }
207 WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
208 self.resize(**new_inner_size);
209 }
210 WindowEvent::CursorMoved { position, .. } => {
211 self.mouse_move(*position);
212 }
213 WindowEvent::MouseInput { state, button, .. } => {
214 self.mouse_input(*state, *button);
215 }
216 WindowEvent::KeyboardInput { input, .. } => {
217 if let Some(keycode) = input.virtual_keycode {
218 self.keyboard_input(keycode, input.state);
219 }
220 }
221 WindowEvent::CloseRequested => {
222 self.close();
223 }
224 _ => {}
225 }
226 }
227
228 pub fn resize(&mut self, size: PhysicalSize<u32>) {
229 self.device.resize(size);
230
231 {
232 let mut info = self.info.lock().unwrap();
233 let size = size.to_logical(self.device.scale_factor());
234 info.width = size.width;
235 info.height = size.height;
236 }
237
238 self.trigger_draw();
239
240 self.device.queue.write_buffer(
241 &self.screen_buffer,
242 0,
243 bytemuck::cast_slice(&[Uniform {
244 surface_size: size,
245 scale: self.device.scale_factor(),
246 }
247 .to_raw()]),
248 );
249 }
250
251 fn update_draw_buffer(&mut self) {
252 if let Some(frame) = self.frame.if_changed() {
253 self.background = frame.background;
254 self.shape_buffer.load_data(&self.device.device, &self.device.queue, &frame.buffer);
255 }
256 }
257
258 pub fn redraw(&mut self) {
259 self.update_draw_buffer();
260
261 let result = self.device.redraw(|view, encoder| {
262 let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
263 label: Some("Render Pass"),
264 color_attachments: &[wgpu::RenderPassColorAttachment {
265 view,
266 resolve_target: None,
267 ops: wgpu::Operations {
268 load: wgpu::LoadOp::Clear(self.background),
269 store: true,
270 },
271 }],
272 depth_stencil_attachment: None,
273 });
274
275 render_pass.set_pipeline(&self.render_pipeline);
276 render_pass.set_bind_group(0, &self.screen_bind_group, &[]);
277 render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
278 render_pass.set_vertex_buffer(1, self.shape_buffer.slice());
279 render_pass.set_index_buffer(self.index_buffer.slice(..), wgpu::IndexFormat::Uint16);
280 render_pass.draw_indexed(
281 0..INDICES.len() as u32,
282 0,
283 0..self.shape_buffer.len() as u32,
284 );
285 });
286
287 match result {
288 Err(wgpu::SurfaceError::Outdated | wgpu::SurfaceError::Lost) => {
289 self.resize(self.device.inner_size());
291 }
292 _ => {}
293 }
294 }
295}