Skip to content

Commit 1683bef

Browse files
committed
Refactor into App struct
1 parent e5c431c commit 1683bef

File tree

3 files changed

+184
-178
lines changed

3 files changed

+184
-178
lines changed
File renamed without changes.

src/app.rs

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
use wgpu::{
2+
include_wgsl, BindGroupDescriptor, BindGroupEntry, BindGroupLayoutDescriptor,
3+
BindGroupLayoutEntry, BindingResource, BindingType, BufferBindingType, BufferDescriptor,
4+
BufferUsages, ColorTargetState, CommandEncoderDescriptor, DeviceDescriptor, Features,
5+
FragmentState, Instance, Limits, MultisampleState, PipelineLayoutDescriptor, PowerPreference,
6+
PrimitiveState, RenderPassColorAttachment, RenderPassDescriptor, RenderPipelineDescriptor,
7+
RequestAdapterOptions, ShaderStages, TextureViewDescriptor, VertexState,
8+
};
9+
use winit::window::Window;
10+
11+
use crate::MousePosition;
12+
13+
// impl bytemuck::Pod and bytemuck::Zeroable so we can use it as a buffer
14+
// I'm not sure if this is the best way to do this, but it works.
15+
unsafe impl bytemuck::Pod for MousePosition {}
16+
unsafe impl bytemuck::Zeroable for MousePosition {}
17+
18+
pub struct App<'a> {
19+
// Render stuff
20+
surface: wgpu::Surface<'a>,
21+
adapter: wgpu::Adapter,
22+
queue: wgpu::Queue,
23+
device: wgpu::Device,
24+
render_pipeline: wgpu::RenderPipeline,
25+
26+
// Buffer stuff
27+
buffer: wgpu::Buffer,
28+
bind_group: wgpu::BindGroup,
29+
pub mouse_position: Option<MousePosition>,
30+
}
31+
32+
impl App<'_> {
33+
pub async fn new(window: Window) -> Self {
34+
// Grab the window size now, so we can use it to size our surface.
35+
// We need it here because we won't have a borrow on the window later.
36+
let size = window.inner_size();
37+
38+
// Setting up access to the GPU and the surface to render too.
39+
let instance = Instance::default();
40+
let surface = instance.create_surface(window).expect("Create surface");
41+
let adapter = instance
42+
.request_adapter(&RequestAdapterOptions {
43+
power_preference: PowerPreference::default(),
44+
force_fallback_adapter: false,
45+
compatible_surface: Some(&surface),
46+
})
47+
.await
48+
.expect("Request adapter");
49+
let (device, queue) = adapter
50+
.request_device(
51+
&DeviceDescriptor {
52+
label: None,
53+
required_features: Features::default(),
54+
required_limits: Limits::default(),
55+
},
56+
None,
57+
)
58+
.await
59+
.expect("Request device");
60+
let surface_config = surface
61+
.get_default_config(&adapter, size.width, size.height)
62+
.expect("Get default surface config");
63+
surface.configure(&device, &surface_config);
64+
65+
// Set up a buffer to store mouse position
66+
let buffer = device.create_buffer(&BufferDescriptor {
67+
label: None,
68+
size: 32 * 2, // 'vec2<f32>'
69+
usage: BufferUsages::UNIFORM | BufferUsages::COPY_DST,
70+
mapped_at_creation: false,
71+
});
72+
let bind_group_layout = device.create_bind_group_layout(&BindGroupLayoutDescriptor {
73+
entries: &[BindGroupLayoutEntry {
74+
binding: 0,
75+
visibility: ShaderStages::FRAGMENT,
76+
ty: BindingType::Buffer {
77+
ty: BufferBindingType::Uniform,
78+
has_dynamic_offset: false,
79+
min_binding_size: None,
80+
},
81+
count: None,
82+
}],
83+
label: None,
84+
});
85+
let bind_group = device.create_bind_group(&BindGroupDescriptor {
86+
layout: &bind_group_layout,
87+
entries: &[BindGroupEntry {
88+
binding: 0,
89+
resource: BindingResource::Buffer(buffer.as_entire_buffer_binding()),
90+
}],
91+
label: None,
92+
});
93+
let pipeline_layout = device.create_pipeline_layout(&PipelineLayoutDescriptor {
94+
bind_group_layouts: &[&bind_group_layout],
95+
..Default::default()
96+
});
97+
98+
// Set up the render pipeline
99+
let shader = device.create_shader_module(include_wgsl!("../assets/shader.wgsl"));
100+
let render_pipeline = device.create_render_pipeline(&RenderPipelineDescriptor {
101+
label: None,
102+
layout: Some(&pipeline_layout),
103+
vertex: VertexState {
104+
module: &shader,
105+
entry_point: "vertex",
106+
buffers: &[],
107+
},
108+
primitive: PrimitiveState::default(),
109+
depth_stencil: None,
110+
multisample: MultisampleState::default(),
111+
fragment: Some(FragmentState {
112+
module: &shader,
113+
entry_point: "fragment",
114+
targets: &[Some(ColorTargetState {
115+
format: surface_config.format,
116+
blend: None,
117+
write_mask: Default::default(),
118+
})],
119+
}),
120+
multiview: None,
121+
});
122+
123+
Self {
124+
surface,
125+
adapter,
126+
queue,
127+
device,
128+
render_pipeline,
129+
buffer,
130+
bind_group,
131+
mouse_position: None,
132+
}
133+
}
134+
135+
pub fn render(&self) {
136+
let surface_texture = self
137+
.surface
138+
.get_current_texture()
139+
.expect("Get current texture");
140+
let texture_view = surface_texture
141+
.texture
142+
.create_view(&TextureViewDescriptor::default());
143+
144+
let mut command_encoder = self
145+
.device
146+
.create_command_encoder(&CommandEncoderDescriptor::default());
147+
{
148+
let mut render_pass = command_encoder.begin_render_pass(&RenderPassDescriptor {
149+
color_attachments: &[Some(RenderPassColorAttachment {
150+
view: &texture_view,
151+
resolve_target: None,
152+
ops: Default::default(),
153+
})],
154+
..Default::default()
155+
});
156+
render_pass.set_pipeline(&self.render_pipeline);
157+
render_pass.set_bind_group(0, &self.bind_group, &[]);
158+
render_pass.draw(0..6, 0..1);
159+
}
160+
161+
// Copy the mouse position into the buffer if we have one
162+
if let Some(mp) = self.mouse_position {
163+
self.queue
164+
.write_buffer(&self.buffer, 0, bytemuck::cast_slice(&[mp]))
165+
}
166+
167+
self.queue.submit(Some(command_encoder.finish()));
168+
surface_texture.present();
169+
}
170+
171+
pub fn resize(&mut self, size: winit::dpi::PhysicalSize<u32>) {
172+
self.surface.configure(
173+
&self.device,
174+
&self
175+
.surface
176+
.get_default_config(&self.adapter, size.width, size.height)
177+
.expect("Get default surface config"),
178+
);
179+
}
180+
}

src/main.rs

Lines changed: 4 additions & 178 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,14 @@
88
//! I can focus on the shader stuff. It'll probably be a good idea to go back and tweak some of that stuff later
99
//! to get it to work on other platforms, but I'm not really worried about that right now.
1010
11-
use wgpu::{
12-
include_wgsl, BindGroupDescriptor, BindGroupEntry, BindGroupLayoutDescriptor,
13-
BindGroupLayoutEntry, BindingResource, BindingType, BufferBindingType, BufferDescriptor,
14-
BufferUsages, ColorTargetState, CommandEncoderDescriptor, DeviceDescriptor, Features,
15-
FragmentState, Instance, Limits, MultisampleState, PipelineLayoutDescriptor, PowerPreference,
16-
PrimitiveState, RenderPassColorAttachment, RenderPassDescriptor, RenderPipelineDescriptor,
17-
RequestAdapterOptions, ShaderStages, TextureViewDescriptor, VertexState,
18-
};
1911
use winit::{
2012
event::{Event, WindowEvent},
2113
event_loop::EventLoop,
22-
window::{Window, WindowBuilder},
14+
window::WindowBuilder,
2315
};
2416

17+
mod app;
18+
2519
#[tokio::main]
2620
async fn main() {
2721
// Setup windowing
@@ -32,7 +26,7 @@ async fn main() {
3226
.expect("New window");
3327

3428
// Setup the app
35-
let mut app = App::new(window).await;
29+
let mut app = app::App::new(window).await;
3630

3731
// Run the event loop
3832
let _ = event_loop.run(|event, elwt| {
@@ -77,171 +71,3 @@ struct MousePosition {
7771
x: f32,
7872
y: f32,
7973
}
80-
81-
// impl bytemuck::Pod and bytemuck::Zeroable so we can use it as a buffer
82-
// I'm not sure if this is the best way to do this, but it works.
83-
unsafe impl bytemuck::Pod for MousePosition {}
84-
unsafe impl bytemuck::Zeroable for MousePosition {}
85-
86-
struct App<'a> {
87-
// Render stuff
88-
surface: wgpu::Surface<'a>,
89-
adapter: wgpu::Adapter,
90-
queue: wgpu::Queue,
91-
device: wgpu::Device,
92-
render_pipeline: wgpu::RenderPipeline,
93-
94-
// Buffer stuff
95-
buffer: wgpu::Buffer,
96-
bind_group: wgpu::BindGroup,
97-
mouse_position: Option<MousePosition>,
98-
}
99-
impl App<'_> {
100-
async fn new(window: Window) -> Self {
101-
// Grab the window size now, so we can use it to size our surface.
102-
// We need it here because we won't have a borrow on the window later.
103-
let size = window.inner_size();
104-
105-
// Setting up access to the GPU and the surface to render too.
106-
let instance = Instance::default();
107-
let surface = instance.create_surface(window).expect("Create surface");
108-
let adapter = instance
109-
.request_adapter(&RequestAdapterOptions {
110-
power_preference: PowerPreference::default(),
111-
force_fallback_adapter: false,
112-
compatible_surface: Some(&surface),
113-
})
114-
.await
115-
.expect("Request adapter");
116-
let (device, queue) = adapter
117-
.request_device(
118-
&DeviceDescriptor {
119-
label: None,
120-
required_features: Features::default(),
121-
required_limits: Limits::default(),
122-
},
123-
None,
124-
)
125-
.await
126-
.expect("Request device");
127-
let surface_config = surface
128-
.get_default_config(&adapter, size.width, size.height)
129-
.expect("Get default surface config");
130-
surface.configure(&device, &surface_config);
131-
132-
// Set up a buffer to store mouse position
133-
let buffer = device.create_buffer(&BufferDescriptor {
134-
label: None,
135-
size: 32 * 2, // 'vec2<f32>'
136-
usage: BufferUsages::UNIFORM | BufferUsages::COPY_DST,
137-
mapped_at_creation: false,
138-
});
139-
let bind_group_layout = device.create_bind_group_layout(&BindGroupLayoutDescriptor {
140-
entries: &[BindGroupLayoutEntry {
141-
binding: 0,
142-
visibility: ShaderStages::FRAGMENT,
143-
ty: BindingType::Buffer {
144-
ty: BufferBindingType::Uniform,
145-
has_dynamic_offset: false,
146-
min_binding_size: None,
147-
},
148-
count: None,
149-
}],
150-
label: None,
151-
});
152-
let bind_group = device.create_bind_group(&BindGroupDescriptor {
153-
layout: &bind_group_layout,
154-
entries: &[BindGroupEntry {
155-
binding: 0,
156-
resource: BindingResource::Buffer(buffer.as_entire_buffer_binding()),
157-
}],
158-
label: None,
159-
});
160-
let pipeline_layout = device.create_pipeline_layout(&PipelineLayoutDescriptor {
161-
bind_group_layouts: &[&bind_group_layout],
162-
..Default::default()
163-
});
164-
165-
// Set up the render pipeline
166-
let shader = device.create_shader_module(include_wgsl!("shader.wgsl"));
167-
let render_pipeline = device.create_render_pipeline(&RenderPipelineDescriptor {
168-
label: None,
169-
layout: Some(&pipeline_layout),
170-
vertex: VertexState {
171-
module: &shader,
172-
entry_point: "vertex",
173-
buffers: &[],
174-
},
175-
primitive: PrimitiveState::default(),
176-
depth_stencil: None,
177-
multisample: MultisampleState::default(),
178-
fragment: Some(FragmentState {
179-
module: &shader,
180-
entry_point: "fragment",
181-
targets: &[Some(ColorTargetState {
182-
format: surface_config.format,
183-
blend: None,
184-
write_mask: Default::default(),
185-
})],
186-
}),
187-
multiview: None,
188-
});
189-
190-
Self {
191-
surface,
192-
adapter,
193-
queue,
194-
device,
195-
render_pipeline,
196-
buffer,
197-
bind_group,
198-
mouse_position: None,
199-
}
200-
}
201-
202-
fn render(&self) {
203-
let surface_texture = self
204-
.surface
205-
.get_current_texture()
206-
.expect("Get current texture");
207-
let texture_view = surface_texture
208-
.texture
209-
.create_view(&TextureViewDescriptor::default());
210-
211-
let mut command_encoder = self
212-
.device
213-
.create_command_encoder(&CommandEncoderDescriptor::default());
214-
{
215-
let mut render_pass = command_encoder.begin_render_pass(&RenderPassDescriptor {
216-
color_attachments: &[Some(RenderPassColorAttachment {
217-
view: &texture_view,
218-
resolve_target: None,
219-
ops: Default::default(),
220-
})],
221-
..Default::default()
222-
});
223-
render_pass.set_pipeline(&self.render_pipeline);
224-
render_pass.set_bind_group(0, &self.bind_group, &[]);
225-
render_pass.draw(0..6, 0..1);
226-
}
227-
228-
// Copy the mouse position into the buffer if we have one
229-
if let Some(mp) = self.mouse_position {
230-
self.queue
231-
.write_buffer(&self.buffer, 0, bytemuck::cast_slice(&[mp]))
232-
}
233-
234-
self.queue.submit(Some(command_encoder.finish()));
235-
surface_texture.present();
236-
}
237-
238-
fn resize(&mut self, size: winit::dpi::PhysicalSize<u32>) {
239-
self.surface.configure(
240-
&self.device,
241-
&self
242-
.surface
243-
.get_default_config(&self.adapter, size.width, size.height)
244-
.expect("Get default surface config"),
245-
);
246-
}
247-
}

0 commit comments

Comments
 (0)