Skip to content

Commit fc18815

Browse files
authored
Use Push Constants instead of an Uniform Buffer for the window viewport (#1)
* testing push constants * works * dunno * dunno * some improvements * cleanup
1 parent 2635e09 commit fc18815

File tree

3 files changed

+43
-96
lines changed

3 files changed

+43
-96
lines changed

src/app.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ impl<'window> ApplicationHandler for App<'window> {
1717
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
1818
if self.window.is_none() {
1919
let win_attr = Window::default_attributes().with_title("wgpu winit example");
20-
// use Arc.
2120
let window = Arc::new(
2221
event_loop
2322
.create_window(win_attr)
@@ -37,13 +36,11 @@ impl<'window> ApplicationHandler for App<'window> {
3736
) {
3837
match event {
3938
WindowEvent::CloseRequested => {
40-
// macOS err: https://github.com/rust-windowing/winit/issues/3668
41-
// This will be fixed as winit 0.30.1.
4239
event_loop.exit();
4340
}
4441
WindowEvent::Resized(size) => {
4542
if let Some(gpu) = self.gpu.as_mut() {
46-
gpu.resize(size.width, size.height);
43+
gpu.set_size(size.width, size.height);
4744
}
4845
}
4946
WindowEvent::RedrawRequested => {

src/gpu.rs

Lines changed: 39 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use bytemuck::bytes_of;
12
use bytemuck::cast_slice;
23
use bytemuck::Pod;
34
use bytemuck::Zeroable;
@@ -8,12 +9,6 @@ use wgpu::MemoryHints::Performance;
89
use wgpu::ShaderSource;
910
use winit::window::Window;
1011

11-
#[repr(C)]
12-
#[derive(Debug, Copy, Clone, Pod, Zeroable)]
13-
struct Uniforms {
14-
screen_size: [f32; 2],
15-
}
16-
1712
#[repr(C)]
1813
#[derive(Copy, Clone, Debug, Pod, Zeroable)]
1914
struct Instance {
@@ -41,9 +36,7 @@ pub struct Gpu<'window> {
4136
num_indices: u32,
4237
instance_buffer: wgpu::Buffer,
4338
instance_count: u32,
44-
45-
uniform_buffer: wgpu::Buffer,
46-
uniform_bind_group: wgpu::BindGroup,
39+
viewport: [f32; 2],
4740
}
4841

4942
impl<'window> Gpu<'window> {
@@ -52,16 +45,22 @@ impl<'window> Gpu<'window> {
5245
}
5346

5447
pub async fn new_async(window: Arc<Window>) -> Gpu<'window> {
48+
/*
49+
* window
50+
*/
51+
5552
let size = window.inner_size();
5653
let width = size.width.max(1);
5754
let height = size.height.max(1);
55+
let viewport = [width as f32, height as f32];
5856

5957
/*
6058
* wgpu
6159
*/
6260

6361
let instance = wgpu::Instance::default();
6462
let surface = instance.create_surface(Arc::clone(&window)).unwrap();
63+
let push_const_size = std::mem::size_of::<[f32; 2]>() as u32;
6564

6665
let adapter = instance
6766
.request_adapter(&wgpu::RequestAdapterOptions {
@@ -76,9 +75,11 @@ impl<'window> Gpu<'window> {
7675
.request_device(
7776
&wgpu::DeviceDescriptor {
7877
label: None,
79-
required_features: wgpu::Features::empty(),
80-
required_limits: wgpu::Limits::downlevel_webgl2_defaults()
81-
.using_resolution(adapter.limits()),
78+
required_features: wgpu::Features::PUSH_CONSTANTS,
79+
required_limits: wgpu::Limits {
80+
max_push_constant_size: push_const_size,
81+
..Default::default()
82+
},
8283
memory_hints: Performance,
8384
},
8485
None,
@@ -90,6 +91,15 @@ impl<'window> Gpu<'window> {
9091

9192
surface.configure(&device, &config);
9293

94+
/*
95+
* push constants
96+
*/
97+
98+
let push_constant_range = wgpu::PushConstantRange {
99+
stages: wgpu::ShaderStages::VERTEX,
100+
range: 0..push_const_size,
101+
};
102+
93103
/*
94104
* rects
95105
*/
@@ -100,17 +110,6 @@ impl<'window> Gpu<'window> {
100110
Instance::new(700.0, 100.0, 200.0, 200.0),
101111
];
102112

103-
/*
104-
* instances
105-
*/
106-
107-
let instance_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
108-
label: Some("Instance Buffer"),
109-
contents: cast_slice(&rects),
110-
usage: wgpu::BufferUsages::VERTEX,
111-
});
112-
let instance_count = rects.len() as u32;
113-
114113
/*
115114
* vertices
116115
*/
@@ -138,42 +137,15 @@ impl<'window> Gpu<'window> {
138137
let num_indices = indices.len() as u32;
139138

140139
/*
141-
* uniforms
140+
* instances
142141
*/
143142

144-
let uniforms = Uniforms {
145-
screen_size: [width as f32, height as f32],
146-
};
147-
148-
let uniform_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
149-
label: Some("Uniform Buffer"),
150-
contents: cast_slice(&[uniforms]),
151-
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
152-
});
153-
154-
let uniform_bind_group_layout =
155-
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
156-
label: Some("Uniform Bind Group Layout"),
157-
entries: &[wgpu::BindGroupLayoutEntry {
158-
binding: 0,
159-
visibility: wgpu::ShaderStages::VERTEX,
160-
ty: wgpu::BindingType::Buffer {
161-
ty: wgpu::BufferBindingType::Uniform,
162-
has_dynamic_offset: false,
163-
min_binding_size: None,
164-
},
165-
count: None,
166-
}],
167-
});
168-
169-
let uniform_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
170-
label: Some("Uniform Bind Group"),
171-
layout: &uniform_bind_group_layout,
172-
entries: &[wgpu::BindGroupEntry {
173-
binding: 0,
174-
resource: uniform_buffer.as_entire_binding(),
175-
}],
143+
let instance_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
144+
label: Some("Instance Buffer"),
145+
contents: cast_slice(&rects),
146+
usage: wgpu::BufferUsages::VERTEX,
176147
});
148+
let instance_count = rects.len() as u32;
177149

178150
/*
179151
* shader
@@ -191,8 +163,8 @@ impl<'window> Gpu<'window> {
191163
let render_pipeline_layout =
192164
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
193165
label: Some("Render Pipeline Layout"),
194-
bind_group_layouts: &[&uniform_bind_group_layout],
195-
push_constant_ranges: &[],
166+
bind_group_layouts: &[],
167+
push_constant_ranges: &[push_constant_range],
196168
});
197169

198170
let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
@@ -202,6 +174,7 @@ impl<'window> Gpu<'window> {
202174
module: &shader,
203175
entry_point: Some("vs_main"),
204176
buffers: &[
177+
// Vertex buffer
205178
wgpu::VertexBufferLayout {
206179
array_stride: std::mem::size_of::<[f32; 2]>() as wgpu::BufferAddress,
207180
step_mode: wgpu::VertexStepMode::Vertex,
@@ -211,6 +184,7 @@ impl<'window> Gpu<'window> {
211184
format: wgpu::VertexFormat::Float32x2,
212185
}],
213186
},
187+
// Instance buffer
214188
wgpu::VertexBufferLayout {
215189
array_stride: std::mem::size_of::<Instance>() as wgpu::BufferAddress,
216190
step_mode: wgpu::VertexStepMode::Instance,
@@ -238,16 +212,6 @@ impl<'window> Gpu<'window> {
238212
}),
239213
primitive: wgpu::PrimitiveState {
240214
topology: wgpu::PrimitiveTopology::TriangleList,
241-
// strip_index_format: None,
242-
// front_face: wgpu::FrontFace::Ccw,
243-
// cull_mode: Some(wgpu::Face::Back),
244-
// // Setting this to anything other than Fill requires Features::POLYGON_MODE_LINE
245-
// // or Features::POLYGON_MODE_POINT
246-
// polygon_mode: wgpu::PolygonMode::Fill,
247-
// // Requires Features::DEPTH_CLIP_CONTROL
248-
// unclipped_depth: false,
249-
// // Requires Features::CONSERVATIVE_RASTERIZATION
250-
// conservative: false,
251215
..Default::default()
252216
},
253217
depth_stencil: None,
@@ -267,31 +231,23 @@ impl<'window> Gpu<'window> {
267231
num_indices,
268232
instance_buffer,
269233
instance_count,
270-
uniform_buffer,
271-
uniform_bind_group,
234+
viewport,
272235
}
273236
}
274237

275-
pub fn resize(&mut self, width: u32, height: u32) {
276-
self.device.poll(wgpu::Maintain::Wait);
277-
238+
pub fn set_size(&mut self, width: u32, height: u32) {
278239
let width = width.max(1);
279240
let height = height.max(1);
280241

281242
self.config.width = width;
282243
self.config.height = height;
283-
284244
self.surface.configure(&self.device, &self.config);
285-
286-
let surface_uniform = Uniforms {
287-
screen_size: [width as f32, height as f32],
288-
};
289-
290-
self.queue
291-
.write_buffer(&self.uniform_buffer, 0, cast_slice(&[surface_uniform]));
245+
self.viewport = [width as f32, height as f32];
292246
}
293247

294248
pub fn draw(&mut self) {
249+
self.device.poll(wgpu::Maintain::Wait);
250+
295251
let frame = self
296252
.surface
297253
.get_current_texture()
@@ -314,12 +270,7 @@ impl<'window> Gpu<'window> {
314270
view: &view,
315271
resolve_target: None,
316272
ops: wgpu::Operations {
317-
load: wgpu::LoadOp::Clear(wgpu::Color {
318-
r: 0.104,
319-
g: 0.133,
320-
b: 0.212,
321-
a: 1.0,
322-
}),
273+
load: wgpu::LoadOp::Clear(wgpu::Color::BLACK),
323274
store: wgpu::StoreOp::Store,
324275
},
325276
})],
@@ -329,7 +280,7 @@ impl<'window> Gpu<'window> {
329280
});
330281

331282
rpass.set_pipeline(&self.render_pipeline);
332-
rpass.set_bind_group(0, &self.uniform_bind_group, &[]);
283+
rpass.set_push_constants(wgpu::ShaderStages::VERTEX, 0, bytes_of(&self.viewport));
333284
rpass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
334285
rpass.set_vertex_buffer(1, self.instance_buffer.slice(..));
335286
rpass.set_index_buffer(self.index_buffer.slice(..), wgpu::IndexFormat::Uint16);

src/shader.wgsl

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
@group(0) @binding(0)
2-
var<uniform> view_size: vec2<f32>;
1+
var<push_constant> viewport: vec2<f32>;
32

43
struct VertexOutput {
54
@builtin(position) clip_position: vec4<f32>,
@@ -21,8 +20,8 @@ fn vs_main(
2120
);
2221

2322
let pos = inst_pos + vert_pos * inst_size;
24-
let ndc_x = (pos.x / view_size.x) * 2.0 - 1.0;
25-
let ndc_y = 1.0 - (pos.y / view_size.y) * 2.0;
23+
let ndc_x = (pos.x / viewport.x) * 2.0 - 1.0;
24+
let ndc_y = 1.0 - (pos.y / viewport.y) * 2.0;
2625

2726
var output: VertexOutput;
2827
output.clip_position = vec4<f32>(ndc_x, ndc_y, 1.0, 1.0);

0 commit comments

Comments
 (0)