summaryrefslogtreecommitdiff
path: root/rust/crates/gpu/src/sdf_pipeline.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/crates/gpu/src/sdf_pipeline.rs')
-rw-r--r--rust/crates/gpu/src/sdf_pipeline.rs307
1 files changed, 0 insertions, 307 deletions
diff --git a/rust/crates/gpu/src/sdf_pipeline.rs b/rust/crates/gpu/src/sdf_pipeline.rs
deleted file mode 100644
index d2612fe1..00000000
--- a/rust/crates/gpu/src/sdf_pipeline.rs
+++ /dev/null
@@ -1,307 +0,0 @@
-use bytemuck::{Pod, Zeroable};
-use wgpu::util::DeviceExt;
-
-use crate::{GPU_TEXTURE_FORMAT, context::GpuContext};
-
-const FULLSCREEN_SHADER_SOURCE: &str = include_str!("shaders/fullscreen.wgsl");
-const JFA_INIT_SHADER_SOURCE: &str = include_str!("shaders/jfa_init.wgsl");
-const JFA_STEP_SHADER_SOURCE: &str = include_str!("shaders/jfa_step.wgsl");
-
-pub struct SignedDistanceFieldTextures {
- pub inside_texture: wgpu::Texture,
- pub outside_texture: wgpu::Texture,
-}
-
-pub struct SdfPipeline {
- texture_bind_group_layout: wgpu::BindGroupLayout,
- uniform_bind_group_layout: wgpu::BindGroupLayout,
- init_pipeline: wgpu::RenderPipeline,
- step_pipeline: wgpu::RenderPipeline,
-}
-
-#[repr(C)]
-#[derive(Clone, Copy, Pod, Zeroable)]
-struct JfaInitUniformBuffer {
- resolution: [f32; 2],
- invert: f32,
- _padding: f32,
-}
-
-#[repr(C)]
-#[derive(Clone, Copy, Pod, Zeroable)]
-struct JfaStepUniformBuffer {
- resolution: [f32; 2],
- step_size: f32,
- _padding: f32,
-}
-
-impl SdfPipeline {
- pub fn new(device: &wgpu::Device) -> Self {
- let texture_bind_group_layout =
- device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
- label: Some("gpu-sdf-texture-bind-group-layout"),
- entries: &[
- wgpu::BindGroupLayoutEntry {
- binding: 0,
- visibility: wgpu::ShaderStages::FRAGMENT,
- ty: wgpu::BindingType::Texture {
- multisampled: false,
- view_dimension: wgpu::TextureViewDimension::D2,
- sample_type: wgpu::TextureSampleType::Float { filterable: true },
- },
- count: None,
- },
- wgpu::BindGroupLayoutEntry {
- binding: 1,
- visibility: wgpu::ShaderStages::FRAGMENT,
- ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
- count: None,
- },
- ],
- });
- let uniform_bind_group_layout =
- device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
- label: Some("gpu-sdf-uniform-bind-group-layout"),
- entries: &[wgpu::BindGroupLayoutEntry {
- binding: 0,
- visibility: wgpu::ShaderStages::FRAGMENT,
- ty: wgpu::BindingType::Buffer {
- ty: wgpu::BufferBindingType::Uniform,
- has_dynamic_offset: false,
- min_binding_size: None,
- },
- count: None,
- }],
- });
- let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
- label: Some("gpu-sdf-pipeline-layout"),
- bind_group_layouts: &[
- Some(&texture_bind_group_layout),
- Some(&uniform_bind_group_layout),
- ],
- immediate_size: 0,
- });
- let vertex_shader_module = device.create_shader_module(wgpu::ShaderModuleDescriptor {
- label: Some("gpu-sdf-fullscreen-shader"),
- source: wgpu::ShaderSource::Wgsl(FULLSCREEN_SHADER_SOURCE.into()),
- });
- let init_shader_module = device.create_shader_module(wgpu::ShaderModuleDescriptor {
- label: Some("gpu-jfa-init-shader"),
- source: wgpu::ShaderSource::Wgsl(JFA_INIT_SHADER_SOURCE.into()),
- });
- let step_shader_module = device.create_shader_module(wgpu::ShaderModuleDescriptor {
- label: Some("gpu-jfa-step-shader"),
- source: wgpu::ShaderSource::Wgsl(JFA_STEP_SHADER_SOURCE.into()),
- });
- let init_pipeline = create_pipeline(
- device,
- "gpu-jfa-init-pipeline",
- &pipeline_layout,
- &vertex_shader_module,
- &init_shader_module,
- );
- let step_pipeline = create_pipeline(
- device,
- "gpu-jfa-step-pipeline",
- &pipeline_layout,
- &vertex_shader_module,
- &step_shader_module,
- );
-
- Self {
- texture_bind_group_layout,
- uniform_bind_group_layout,
- init_pipeline,
- step_pipeline,
- }
- }
-
- pub fn compute_signed_distance_field(
- &self,
- context: &GpuContext,
- source_texture: &wgpu::Texture,
- width: u32,
- height: u32,
- ) -> SignedDistanceFieldTextures {
- SignedDistanceFieldTextures {
- inside_texture: self.run_jfa(context, source_texture, width, height, false),
- outside_texture: self.run_jfa(context, source_texture, width, height, true),
- }
- }
-
- fn run_jfa(
- &self,
- context: &GpuContext,
- source_texture: &wgpu::Texture,
- width: u32,
- height: u32,
- is_inverted: bool,
- ) -> wgpu::Texture {
- let ping_texture = context.create_render_texture(width, height, "gpu-jfa-ping-texture");
- let pong_texture = context.create_render_texture(width, height, "gpu-jfa-pong-texture");
-
- self.run_pass(
- context,
- source_texture,
- &ping_texture,
- &self.init_pipeline,
- bytemuck::bytes_of(&JfaInitUniformBuffer {
- resolution: [width as f32, height as f32],
- invert: if is_inverted { 1.0 } else { 0.0 },
- _padding: 0.0,
- }),
- );
-
- let mut source_is_ping = true;
- let steps = (width.max(height) as f32).log2().ceil() as u32;
- for step_index in (0..steps).rev() {
- let step_size = 2u32.pow(step_index).max(1);
- let input_texture = if source_is_ping {
- &ping_texture
- } else {
- &pong_texture
- };
- let output_texture = if source_is_ping {
- &pong_texture
- } else {
- &ping_texture
- };
- self.run_pass(
- context,
- input_texture,
- output_texture,
- &self.step_pipeline,
- bytemuck::bytes_of(&JfaStepUniformBuffer {
- resolution: [width as f32, height as f32],
- step_size: step_size as f32,
- _padding: 0.0,
- }),
- );
- source_is_ping = !source_is_ping;
- }
-
- if source_is_ping {
- ping_texture
- } else {
- pong_texture
- }
- }
-
- fn run_pass(
- &self,
- context: &GpuContext,
- input_texture: &wgpu::Texture,
- output_texture: &wgpu::Texture,
- pipeline: &wgpu::RenderPipeline,
- uniform_buffer_bytes: &[u8],
- ) {
- 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-sdf-texture-bind-group"),
- layout: &self.texture_bind_group_layout,
- entries: &[
- wgpu::BindGroupEntry {
- binding: 0,
- resource: wgpu::BindingResource::TextureView(&input_view),
- },
- wgpu::BindGroupEntry {
- binding: 1,
- resource: wgpu::BindingResource::Sampler(context.nearest_sampler()),
- },
- ],
- });
- let uniform_buffer = context
- .device()
- .create_buffer_init(&wgpu::util::BufferInitDescriptor {
- label: Some("gpu-sdf-uniform-buffer"),
- contents: uniform_buffer_bytes,
- usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
- });
- let uniform_bind_group = context
- .device()
- .create_bind_group(&wgpu::BindGroupDescriptor {
- label: Some("gpu-sdf-uniform-bind-group"),
- layout: &self.uniform_bind_group_layout,
- entries: &[wgpu::BindGroupEntry {
- binding: 0,
- resource: uniform_buffer.as_entire_binding(),
- }],
- });
- let mut encoder = context
- .device()
- .create_command_encoder(&wgpu::CommandEncoderDescriptor {
- label: Some("gpu-sdf-command-encoder"),
- });
-
- {
- let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
- label: Some("gpu-sdf-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::WHITE),
- 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()]);
- }
-}
-
-fn create_pipeline(
- device: &wgpu::Device,
- label: &'static str,
- layout: &wgpu::PipelineLayout,
- vertex_shader_module: &wgpu::ShaderModule,
- fragment_shader_module: &wgpu::ShaderModule,
-) -> wgpu::RenderPipeline {
- device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
- label: Some(label),
- layout: Some(layout),
- vertex: wgpu::VertexState {
- module: vertex_shader_module,
- entry_point: Some("vertex_main"),
- buffers: &[wgpu::VertexBufferLayout {
- array_stride: std::mem::size_of::<[f32; 2]>() as u64,
- step_mode: wgpu::VertexStepMode::Vertex,
- attributes: &[wgpu::VertexAttribute {
- format: wgpu::VertexFormat::Float32x2,
- offset: 0,
- shader_location: 0,
- }],
- }],
- compilation_options: wgpu::PipelineCompilationOptions::default(),
- },
- fragment: Some(wgpu::FragmentState {
- module: fragment_shader_module,
- entry_point: Some("fragment_main"),
- targets: &[Some(wgpu::ColorTargetState {
- format: GPU_TEXTURE_FORMAT,
- blend: None,
- write_mask: wgpu::ColorWrites::ALL,
- })],
- compilation_options: wgpu::PipelineCompilationOptions::default(),
- }),
- primitive: wgpu::PrimitiveState::default(),
- depth_stencil: None,
- multisample: wgpu::MultisampleState::default(),
- multiview_mask: None,
- cache: None,
- })
-}