summaryrefslogtreecommitdiff
path: root/rust/crates/gpu/src/effect_pipeline.rs
diff options
context:
space:
mode:
authorMaze Winther <mazewinther@gmail.com>2026-04-07 01:09:13 +0200
committerMaze Winther <mazewinther@gmail.com>2026-04-07 01:09:13 +0200
commite4b67094e757917588fb624a30aa046667403add (patch)
tree55452692eac69a5a63b58f2a5cdb701dd7023d68 /rust/crates/gpu/src/effect_pipeline.rs
parent79df73643185c02493364a077402726d1fa7b9ec (diff)
downloadopencut-e4b67094e757917588fb624a30aa046667403add.tar.gz
refactor: split effects and masks into dedicated rust crates, introduce MediaTime and FrameRate
Diffstat (limited to 'rust/crates/gpu/src/effect_pipeline.rs')
-rw-r--r--rust/crates/gpu/src/effect_pipeline.rs194
1 files changed, 0 insertions, 194 deletions
diff --git a/rust/crates/gpu/src/effect_pipeline.rs b/rust/crates/gpu/src/effect_pipeline.rs
deleted file mode 100644
index c600551a..00000000
--- a/rust/crates/gpu/src/effect_pipeline.rs
+++ /dev/null
@@ -1,194 +0,0 @@
-use std::collections::HashMap;
-
-use bytemuck::{Pod, Zeroable};
-use wgpu::util::DeviceExt;
-
-use crate::{GpuError, context::GpuContext};
-
-pub struct ApplyEffectsOptions<'a> {
- pub source: &'a wgpu::Texture,
- pub width: u32,
- pub height: u32,
- pub passes: &'a [EffectPass],
-}
-
-#[derive(Clone, Debug)]
-pub struct EffectPass {
- pub shader: String,
- pub uniforms: HashMap<String, UniformValue>,
-}
-
-#[derive(Clone, Debug)]
-pub enum UniformValue {
- Number(f32),
- Vector(Vec<f32>),
-}
-
-#[repr(C)]
-#[derive(Clone, Copy, Pod, Zeroable)]
-struct EffectUniformBuffer {
- resolution: [f32; 2],
- direction: [f32; 2],
- scalars: [f32; 4],
-}
-
-pub fn apply_effects(
- context: &GpuContext,
- ApplyEffectsOptions {
- source,
- width,
- height,
- passes,
- }: ApplyEffectsOptions<'_>,
-) -> Result<wgpu::Texture, GpuError> {
- let mut current_texture: Option<wgpu::Texture> = None;
-
- for pass in passes {
- let input_texture = current_texture.as_ref().unwrap_or(source);
- let output_texture =
- context.create_render_texture(width, height, "gpu-effect-pass-output");
- let input_view = input_texture.create_view(&wgpu::TextureViewDescriptor::default());
- let output_view = output_texture.create_view(&wgpu::TextureViewDescriptor::default());
- let texture_bind_group = context
- .device()
- .create_bind_group(&wgpu::BindGroupDescriptor {
- label: Some("gpu-effect-texture-bind-group"),
- layout: context
- .shader_registry()
- .effect_texture_bind_group_layout(),
- entries: &[
- wgpu::BindGroupEntry {
- binding: 0,
- resource: wgpu::BindingResource::TextureView(&input_view),
- },
- wgpu::BindGroupEntry {
- binding: 1,
- resource: wgpu::BindingResource::Sampler(context.linear_sampler()),
- },
- ],
- });
- let uniform_buffer = context
- .device()
- .create_buffer_init(&wgpu::util::BufferInitDescriptor {
- label: Some("gpu-effect-uniform-buffer"),
- contents: bytemuck::bytes_of(&pack_effect_uniforms(pass, width, height)?),
- usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
- });
- let uniform_bind_group = context
- .device()
- .create_bind_group(&wgpu::BindGroupDescriptor {
- label: Some("gpu-effect-uniform-bind-group"),
- layout: context
- .shader_registry()
- .effect_uniform_bind_group_layout(),
- entries: &[wgpu::BindGroupEntry {
- binding: 0,
- resource: uniform_buffer.as_entire_binding(),
- }],
- });
- let pipeline = context.shader_registry().get_effect_pipeline(&pass.shader)?;
- let mut encoder = context
- .device()
- .create_command_encoder(&wgpu::CommandEncoderDescriptor {
- label: Some("gpu-effect-command-encoder"),
- });
-
- {
- let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
- label: Some("gpu-effect-render-pass"),
- color_attachments: &[Some(wgpu::RenderPassColorAttachment {
- view: &output_view,
- resolve_target: None,
- depth_slice: None,
- ops: wgpu::Operations {
- load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
- store: wgpu::StoreOp::Store,
- },
- })],
- depth_stencil_attachment: None,
- occlusion_query_set: None,
- timestamp_writes: None,
- multiview_mask: None,
- });
- render_pass.set_pipeline(pipeline);
- render_pass.set_vertex_buffer(0, context.fullscreen_quad().slice(..));
- render_pass.set_bind_group(0, &texture_bind_group, &[]);
- render_pass.set_bind_group(1, &uniform_bind_group, &[]);
- render_pass.draw(0..6, 0..1);
- }
-
- context.queue().submit([encoder.finish()]);
- current_texture = Some(output_texture);
- }
-
- current_texture.ok_or_else(|| GpuError::UnknownEffectShader {
- shader: "missing-effect-pass".to_string(),
- })
-}
-
-fn pack_effect_uniforms(
- pass: &EffectPass,
- width: u32,
- height: u32,
-) -> Result<EffectUniformBuffer, GpuError> {
- let shader = pass.shader.as_str();
- let sigma = read_number_uniform(pass, "u_sigma")?;
- let step = read_number_uniform(pass, "u_step")?;
- let direction = read_vec2_uniform(pass, "u_direction")?;
-
- for uniform in pass.uniforms.keys() {
- if uniform == "u_sigma" || uniform == "u_step" || uniform == "u_direction" {
- continue;
- }
- return Err(GpuError::UnsupportedUniform {
- shader: shader.to_string(),
- uniform: uniform.clone(),
- });
- }
-
- Ok(EffectUniformBuffer {
- resolution: [width as f32, height as f32],
- direction,
- scalars: [sigma, step, 0.0, 0.0],
- })
-}
-
-fn read_number_uniform(pass: &EffectPass, uniform: &str) -> Result<f32, GpuError> {
- let Some(value) = pass.uniforms.get(uniform) else {
- return Err(GpuError::MissingUniform {
- shader: pass.shader.clone(),
- uniform: uniform.to_string(),
- });
- };
- match value {
- UniformValue::Number(value) => Ok(*value),
- UniformValue::Vector(_) => Err(GpuError::InvalidNumberUniform {
- shader: pass.shader.clone(),
- uniform: uniform.to_string(),
- }),
- }
-}
-
-fn read_vec2_uniform(pass: &EffectPass, uniform: &str) -> Result<[f32; 2], GpuError> {
- let Some(value) = pass.uniforms.get(uniform) else {
- return Err(GpuError::MissingUniform {
- shader: pass.shader.clone(),
- uniform: uniform.to_string(),
- });
- };
- let UniformValue::Vector(values) = value else {
- return Err(GpuError::InvalidVectorUniform {
- shader: pass.shader.clone(),
- uniform: uniform.to_string(),
- expected_length: 2,
- });
- };
- if values.len() != 2 {
- return Err(GpuError::InvalidVectorUniform {
- shader: pass.shader.clone(),
- uniform: uniform.to_string(),
- expected_length: 2,
- });
- }
- Ok([values[0], values[1]])
-}