112 lines
3.2 KiB
Rust
112 lines
3.2 KiB
Rust
use std::ops::{Deref, DerefMut};
|
|
|
|
mod data;
|
|
mod layout;
|
|
|
|
use super::*;
|
|
pub use data::*;
|
|
use layout::*;
|
|
|
|
pub struct ComputePipeline {
|
|
layout: Layout,
|
|
pipeline: wgpu::ComputePipeline,
|
|
bind_group: wgpu::BindGroup,
|
|
old_view: ComputeView,
|
|
old_len: usize,
|
|
}
|
|
|
|
const FIXED_SHADER: &str = include_str!("fixed.wgsl");
|
|
const SHADER: &str = include_str!("shader.wgsl");
|
|
|
|
impl ComputePipeline {
|
|
pub fn init(device: &wgpu::Device, config: &wgpu::SurfaceConfiguration, len: usize) -> Self {
|
|
let layout = Layout::init(device, config, len);
|
|
Self {
|
|
pipeline: layout.pipeline(device, &Self::shader(device, len)),
|
|
bind_group: layout.bind_group(device),
|
|
layout,
|
|
old_view: ComputeView::default(),
|
|
old_len: len,
|
|
}
|
|
}
|
|
|
|
pub fn update(
|
|
&mut self,
|
|
device: &wgpu::Device,
|
|
encoder: &mut wgpu::CommandEncoder,
|
|
belt: &mut wgpu::util::StagingBelt,
|
|
camera: &Camera,
|
|
size: &Vector2<u32>,
|
|
len: usize,
|
|
) {
|
|
let mut view = ComputeView::from_camera_size(camera, size, false, len);
|
|
if view != self.old_view {
|
|
for (i, b) in 1u32.to_le_bytes().iter().enumerate() {
|
|
view.bytes[i] = *b;
|
|
}
|
|
}
|
|
if len != self.old_len {
|
|
println!("new len: {}", len);
|
|
self.old_len = len;
|
|
self.pipeline = self.pipeline(device, &Self::shader(device, len));
|
|
self.work.set(work_vec(size.x, size.y, len));
|
|
}
|
|
let updated = self.work.update(device, encoder, belt)
|
|
| self.view.update(device, encoder, belt, view.bytes());
|
|
if updated {
|
|
self.bind_group = self.layout.bind_group(device);
|
|
}
|
|
self.old_view = view;
|
|
}
|
|
|
|
pub fn run(&self, encoder: &mut wgpu::CommandEncoder) {
|
|
let mut pass = encoder.begin_compute_pass(&wgpu::ComputePassDescriptor::default());
|
|
pass.set_pipeline(&self.pipeline);
|
|
pass.set_bind_group(0, &self.bind_group, &[]);
|
|
pass.dispatch_workgroups(240, 135, 1);
|
|
}
|
|
|
|
pub fn resize(
|
|
&mut self,
|
|
device: &wgpu::Device,
|
|
encoder: &mut wgpu::CommandEncoder,
|
|
belt: &mut wgpu::util::StagingBelt,
|
|
size: Vector2<u32>,
|
|
len: usize,
|
|
) {
|
|
self.work.set(work_vec(size.x, size.y, len));
|
|
self.old_len = len;
|
|
self.output.resize(
|
|
device,
|
|
wgpu::Extent3d {
|
|
width: size.x,
|
|
height: size.y,
|
|
depth_or_array_layers: 1,
|
|
},
|
|
);
|
|
self.bind_group = self.layout.bind_group(device);
|
|
}
|
|
|
|
pub fn shader(device: &wgpu::Device, len: usize) -> wgpu::ShaderModule {
|
|
let string = FIXED_SHADER.to_string() + &SHADER.replace("REPLACE_LEN", &format!("{}", len));
|
|
device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
|
label: Some("compute"),
|
|
source: wgpu::ShaderSource::Wgsl(string.into()),
|
|
})
|
|
}
|
|
}
|
|
|
|
impl Deref for ComputePipeline {
|
|
type Target = Layout;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.layout
|
|
}
|
|
}
|
|
|
|
impl DerefMut for ComputePipeline {
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
&mut self.layout
|
|
}
|
|
}
|