1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
use std::io::Write;
use gpgpu::{
primitives::pixels::Rgba8UintNorm, BufOps, DescriptorSet, Framework, GpuConstImage, GpuImage,
GpuUniformBuffer, ImgOps,
};
use image::buffer::ConvertBuffer;
use minifb::{Key, Window, WindowOptions};
use nokhwa::{Camera, CameraFormat, Resolution};
const WIDTH: usize = 1280;
const HEIGHT: usize = 720;
fn main() {
let fw = Framework::default();
let mut camera = {
let camera_format = CameraFormat::new(
Resolution {
width_x: WIDTH as u32,
height_y: HEIGHT as u32,
},
nokhwa::FrameFormat::MJPEG,
30,
);
Camera::new(0, Some(camera_format)).unwrap()
};
let mut window = Window::new(
"gpgpu webcam example",
WIDTH,
HEIGHT,
WindowOptions::default(),
)
.unwrap();
camera.open_stream().unwrap();
window.limit_update_rate(Some(std::time::Duration::from_secs_f32(1.0 / 60.0)));
let gpu_input = GpuConstImage::<Rgba8UintNorm>::new(&fw, WIDTH as u32, HEIGHT as u32);
let buf_time = GpuUniformBuffer::<f32>::with_capacity(&fw, 1);
let gpu_output = GpuImage::<Rgba8UintNorm>::new(&fw, WIDTH as u32, HEIGHT as u32);
let shader = gpgpu::Shader::from_wgsl_file(&fw, "examples/webcam/shader.wgsl").unwrap();
let desc = DescriptorSet::default()
.bind_const_image(&gpu_input)
.bind_image(&gpu_output)
.bind_uniform_buffer(&buf_time);
let program = gpgpu::Program::new(&shader, "main").add_descriptor_set(desc);
let kernel = gpgpu::Kernel::new(&fw, program);
let time = std::time::Instant::now();
let mut frame_buffer = vec![0u32; WIDTH * HEIGHT * 4];
let mut total = 0.0;
let mut count = 0;
while window.is_open() && !window.is_key_down(Key::Escape) {
let fps = std::time::Instant::now();
let cam_buf = camera.frame().unwrap();
gpu_input.write_image_buffer(&cam_buf.convert()).unwrap();
buf_time.write(&[time.elapsed().as_secs_f32()]).unwrap();
kernel.enqueue(WIDTH as u32 / 32, HEIGHT as u32 / 31, 1);
gpu_output
.read_blocking(bytemuck::cast_slice_mut(&mut frame_buffer))
.unwrap();
window
.update_with_buffer(&frame_buffer, WIDTH, HEIGHT)
.unwrap();
print_fps(fps.elapsed().as_secs_f32(), &mut total, &mut count);
}
}
fn print_fps(elapsed: f32, total: &mut f32, count: &mut u32) {
let fps = 1.0 / elapsed;
*total += fps;
*count += 1;
print!(
"\rFPS: {:00.0}\tAverage: {:00.2}",
fps,
*total / *count as f32
);
std::io::stdout().flush().unwrap();
}