summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--flake.nix2
-rw-r--r--src/demosaic/lmmse.rs323
-rw-r--r--src/demosaic/mod.rs11
-rw-r--r--src/main.rs51
-rw-r--r--src/pipeline.rs2
5 files changed, 215 insertions, 174 deletions
diff --git a/flake.nix b/flake.nix
index f425c9b..e6db1d0 100644
--- a/flake.nix
+++ b/flake.nix
@@ -9,7 +9,7 @@
 
   outputs = { self, nixpkgs, fenix }:
     let
-      system = "aarch64-darwin";
+      system = "x86_64-linux";
       pkgs = nixpkgs.legacyPackages.${system};
       fpkgs = fenix.packages.${system};
       rust = with fpkgs; combine (with stable; [
diff --git a/src/demosaic/lmmse.rs b/src/demosaic/lmmse.rs
index 1dc3094..9add4c1 100644
--- a/src/demosaic/lmmse.rs
+++ b/src/demosaic/lmmse.rs
@@ -1,165 +1,182 @@
 pub struct Lmmse {
-	interpolate_bind_layout: wgpu::BindGroupLayout,
-	interpolate_pipeline_layout: wgpu::PipelineLayout,
-	interpolate_shader: wgpu::ShaderModule,
-	interpolate_pipeline: wgpu::ComputePipeline,
+    interpolate_bind_layout: wgpu::BindGroupLayout,
+    interpolate_pipeline_layout: wgpu::PipelineLayout,
+    interpolate_shader: wgpu::ShaderModule,
+    interpolate_pipeline: wgpu::ComputePipeline,
 }
 
 impl super::Demosaic for Lmmse {
-	fn new(gpu: &wgpu::Device, queue: &wgpu::Queue) -> Self {
-		let interpolate_bind_layout = gpu.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
-			label: None,
-			entries: &[
-				wgpu::BindGroupLayoutEntry {
-					binding: 0,
-					visibility: wgpu::ShaderStages::COMPUTE,
-					ty: wgpu::BindingType::StorageTexture {
-						access: wgpu::StorageTextureAccess::ReadOnly,
-						format: wgpu::TextureFormat::R16Uint,
-						view_dimension: wgpu::TextureViewDimension::D2,
-					},
-					count: None,
-				},
-				wgpu::BindGroupLayoutEntry {
-					binding: 1,
-					visibility: wgpu::ShaderStages::COMPUTE,
-					ty: wgpu::BindingType::StorageTexture {
-						access: wgpu::StorageTextureAccess::WriteOnly,
-						format: wgpu::TextureFormat::Rgba32Float,
-						view_dimension: wgpu::TextureViewDimension::D2,
-					},
-					count: None,
-				}
-			],
-		});
-		let interpolate_pipeline_layout = gpu.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
-			label: None,
-			bind_group_layouts: &[&interpolate_bind_layout],
-			push_constant_ranges: &[],
-		});
-		let interpolate_shader = gpu.create_shader_module(wgpu::ShaderModuleDescriptor {
-			label: None,
-			source: wgpu::ShaderSource::Wgsl(include_str!("lmmse_01_interpolate.wgsl").into()),
-		});
-		let interpolate_pipeline = gpu.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
-			label: None,
-			layout: Some(&interpolate_pipeline_layout),
-			module: &interpolate_shader,
-			entry_point: None,
-			compilation_options: wgpu::PipelineCompilationOptions::default(),
-			cache: None,
-		});
+    fn new(gpu: &wgpu::Device, queue: &wgpu::Queue) -> Self {
+        let interpolate_bind_layout =
+            gpu.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
+                label: None,
+                entries: &[
+                    wgpu::BindGroupLayoutEntry {
+                        binding: 0,
+                        visibility: wgpu::ShaderStages::COMPUTE,
+                        ty: wgpu::BindingType::StorageTexture {
+                            access: wgpu::StorageTextureAccess::ReadOnly,
+                            format: wgpu::TextureFormat::R16Uint,
+                            view_dimension: wgpu::TextureViewDimension::D2,
+                        },
+                        count: None,
+                    },
+                    wgpu::BindGroupLayoutEntry {
+                        binding: 1,
+                        visibility: wgpu::ShaderStages::COMPUTE,
+                        ty: wgpu::BindingType::StorageTexture {
+                            access: wgpu::StorageTextureAccess::WriteOnly,
+                            format: wgpu::TextureFormat::Rgba32Float,
+                            view_dimension: wgpu::TextureViewDimension::D2,
+                        },
+                        count: None,
+                    },
+                ],
+            });
+        let interpolate_pipeline_layout =
+            gpu.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
+                label: None,
+                bind_group_layouts: &[&interpolate_bind_layout],
+                push_constant_ranges: &[],
+            });
+        let interpolate_shader = gpu.create_shader_module(wgpu::ShaderModuleDescriptor {
+            label: None,
+            source: wgpu::ShaderSource::Wgsl(include_str!("lmmse_01_interpolate.wgsl").into()),
+        });
+        let interpolate_pipeline = gpu.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
+            label: None,
+            layout: Some(&interpolate_pipeline_layout),
+            module: &interpolate_shader,
+            entry_point: None,
+            compilation_options: wgpu::PipelineCompilationOptions::default(),
+            cache: None,
+        });
 
-		Self {
-			interpolate_bind_layout,
-			interpolate_pipeline_layout,
-			interpolate_shader,
-			interpolate_pipeline,
-		}
-	}
+        Self {
+            interpolate_bind_layout,
+            interpolate_pipeline_layout,
+            interpolate_shader,
+            interpolate_pipeline,
+        }
+    }
 
-	fn demoasic(&self, gpu: &wgpu::Device, queue: &wgpu::Queue, image: &rawloader::RawImage) -> wgpu::Texture {
-		let input_texture = gpu.create_texture(&wgpu::TextureDescriptor {
-			label: None,
-			size: wgpu::Extent3d {
-				width: image.width as u32,
-				height: image.height as u32,
-				depth_or_array_layers: 1,
-			},
-			mip_level_count: 1,
-			sample_count: 1,
-			dimension: wgpu::TextureDimension::D2,
-			format: wgpu::TextureFormat::R16Uint,
-			usage: wgpu::TextureUsages::COPY_DST | wgpu::TextureUsages::STORAGE_BINDING,
-			view_formats: &[wgpu::TextureFormat::R16Uint],
-		});
+    fn demoasic(
+        &self,
+        gpu: &wgpu::Device,
+        queue: &wgpu::Queue,
+        image: &rawloader::RawImage,
+    ) -> wgpu::Texture {
+        let input_texture = gpu.create_texture(&wgpu::TextureDescriptor {
+            label: None,
+            size: wgpu::Extent3d {
+                width: image.width as u32,
+                height: image.height as u32,
+                depth_or_array_layers: 1,
+            },
+            mip_level_count: 1,
+            sample_count: 1,
+            dimension: wgpu::TextureDimension::D2,
+            format: wgpu::TextureFormat::R16Uint,
+            usage: wgpu::TextureUsages::COPY_DST | wgpu::TextureUsages::STORAGE_BINDING,
+            view_formats: &[wgpu::TextureFormat::R16Uint],
+        });
 
-		let image_data = match &image.data {
-			rawloader::RawImageData::Integer(d) => d.as_slice(),
-			_ => panic!("Unsupported input format"),
-		};
-		queue.write_texture(
-			wgpu::TexelCopyTextureInfo {
-				texture: &input_texture,
-				mip_level: 0,
-				origin: wgpu::Origin3d::ZERO,
-				aspect: wgpu::TextureAspect::All,
-			},
-			bytemuck::cast_slice(image_data),
-			wgpu::TexelCopyBufferLayout {
-				offset: 0,
-				bytes_per_row: Some(2 * image.width as u32),
-				rows_per_image: Some(image.height as u32),
-			},
-			wgpu::Extent3d {
-				width: image.width as u32,
-				height: image.height as u32,
-				depth_or_array_layers: 1,
-			}
-		);
+        let image_data = match &image.data {
+            rawloader::RawImageData::Integer(d) => d.as_slice(),
+            _ => panic!("Unsupported input format"),
+        };
+        queue.write_texture(
+            wgpu::TexelCopyTextureInfo {
+                texture: &input_texture,
+                mip_level: 0,
+                origin: wgpu::Origin3d::ZERO,
+                aspect: wgpu::TextureAspect::All,
+            },
+            bytemuck::cast_slice(image_data),
+            wgpu::TexelCopyBufferLayout {
+                offset: 0,
+                bytes_per_row: Some(2 * image.width as u32),
+                rows_per_image: Some(image.height as u32),
+            },
+            wgpu::Extent3d {
+                width: image.width as u32,
+                height: image.height as u32,
+                depth_or_array_layers: 1,
+            },
+        );
 
-		let output_texture = gpu.create_texture(&wgpu::TextureDescriptor {
-			label: None,
-			size: wgpu::Extent3d {
-				width: image.width as u32,
-				height: image.height as u32,
-				depth_or_array_layers: 1,
-			},
-			mip_level_count: 1,
-			sample_count: 1,
-			dimension: wgpu::TextureDimension::D2,
-			format: wgpu::TextureFormat::Rgba32Float,
-			usage: wgpu::TextureUsages::COPY_SRC | wgpu::TextureUsages::STORAGE_BINDING,
-			view_formats: &[wgpu::TextureFormat::Rgba32Float],
-		});
+        let output_texture = gpu.create_texture(&wgpu::TextureDescriptor {
+            label: None,
+            size: wgpu::Extent3d {
+                width: image.width as u32,
+                height: image.height as u32,
+                depth_or_array_layers: 1,
+            },
+            mip_level_count: 1,
+            sample_count: 1,
+            dimension: wgpu::TextureDimension::D2,
+            format: wgpu::TextureFormat::Rgba32Float,
+            usage: wgpu::TextureUsages::COPY_SRC | wgpu::TextureUsages::STORAGE_BINDING,
+            view_formats: &[wgpu::TextureFormat::Rgba32Float],
+        });
 
-		let bind_group = gpu.create_bind_group(&wgpu::BindGroupDescriptor {
-			label: None,
-			layout: &self.interpolate_bind_layout,
-			entries: &[
-				wgpu::BindGroupEntry {
-					binding: 0,
-					resource: wgpu::BindingResource::TextureView(&input_texture.create_view(&wgpu::TextureViewDescriptor {
-						label: None,
-						format: Some(wgpu::TextureFormat::R16Uint),
-						dimension: Some(wgpu::TextureViewDimension::D2),
-						usage: Some(wgpu::TextureUsages::STORAGE_BINDING),
-						aspect: wgpu::TextureAspect::All,
-						base_mip_level: 0,
-						mip_level_count: None,
-						base_array_layer: 0,
-						array_layer_count: None,
-					})),
-				},
-				wgpu::BindGroupEntry {
-					binding: 1,
-					resource: wgpu::BindingResource::TextureView(&output_texture.create_view(&wgpu::TextureViewDescriptor {
-						label: None,
-						format: Some(wgpu::TextureFormat::Rgba32Float),
-						dimension: Some(wgpu::TextureViewDimension::D2),
-						usage: Some(wgpu::TextureUsages::STORAGE_BINDING),
-						aspect: wgpu::TextureAspect::All,
-						base_mip_level: 0,
-						mip_level_count: None,
-						base_array_layer: 0,
-						array_layer_count: None,
-					})),
-				},
-			],
-		});
+        let bind_group = gpu.create_bind_group(&wgpu::BindGroupDescriptor {
+            label: None,
+            layout: &self.interpolate_bind_layout,
+            entries: &[
+                wgpu::BindGroupEntry {
+                    binding: 0,
+                    resource: wgpu::BindingResource::TextureView(&input_texture.create_view(
+                        &wgpu::TextureViewDescriptor {
+                            label: None,
+                            format: Some(wgpu::TextureFormat::R16Uint),
+                            dimension: Some(wgpu::TextureViewDimension::D2),
+                            usage: Some(wgpu::TextureUsages::STORAGE_BINDING),
+                            aspect: wgpu::TextureAspect::All,
+                            base_mip_level: 0,
+                            mip_level_count: None,
+                            base_array_layer: 0,
+                            array_layer_count: None,
+                        },
+                    )),
+                },
+                wgpu::BindGroupEntry {
+                    binding: 1,
+                    resource: wgpu::BindingResource::TextureView(&output_texture.create_view(
+                        &wgpu::TextureViewDescriptor {
+                            label: None,
+                            format: Some(wgpu::TextureFormat::Rgba32Float),
+                            dimension: Some(wgpu::TextureViewDimension::D2),
+                            usage: Some(wgpu::TextureUsages::STORAGE_BINDING),
+                            aspect: wgpu::TextureAspect::All,
+                            base_mip_level: 0,
+                            mip_level_count: None,
+                            base_array_layer: 0,
+                            array_layer_count: None,
+                        },
+                    )),
+                },
+            ],
+        });
 
-		let mut encoder = gpu.create_command_encoder(&wgpu::CommandEncoderDescriptor {
-			label: None,
-		});
-		{
-			let mut pass = encoder.begin_compute_pass(&wgpu::ComputePassDescriptor { label: None, timestamp_writes: None });
-			pass.set_bind_group(0, &bind_group, &[]);
-			pass.set_pipeline(&self.interpolate_pipeline);
-			pass.dispatch_workgroups((image.width as u32).div_ceil(8), (image.height as u32).div_ceil(8), 1);
-		}
-		let command_buf = encoder.finish();
-		queue.submit([command_buf]);
+        let mut encoder =
+            gpu.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
+        {
+            let mut pass = encoder.begin_compute_pass(&wgpu::ComputePassDescriptor {
+                label: None,
+                timestamp_writes: None,
+            });
+            pass.set_bind_group(0, &bind_group, &[]);
+            pass.set_pipeline(&self.interpolate_pipeline);
+            pass.dispatch_workgroups(
+                (image.width as u32).div_ceil(8),
+                (image.height as u32).div_ceil(8),
+                1,
+            );
+        }
+        let command_buf = encoder.finish();
+        queue.submit([command_buf]);
 
-		output_texture
-	}
+        output_texture
+    }
 }
diff --git a/src/demosaic/mod.rs b/src/demosaic/mod.rs
index 4e74f4b..e3d5209 100644
--- a/src/demosaic/mod.rs
+++ b/src/demosaic/mod.rs
@@ -1,6 +1,13 @@
 pub trait Demosaic {
-	fn new(gpu: &wgpu::Device, queue: &wgpu::Queue) -> Self where Self: Sized;
-	fn demoasic(&self, gpu: &wgpu::Device, queue: &wgpu::Queue, image: &rawloader::RawImage) -> wgpu::Texture;
+    fn new(gpu: &wgpu::Device, queue: &wgpu::Queue) -> Self
+    where
+        Self: Sized;
+    fn demoasic(
+        &self,
+        gpu: &wgpu::Device,
+        queue: &wgpu::Queue,
+        image: &rawloader::RawImage,
+    ) -> wgpu::Texture;
 }
 
 pub mod lmmse;
diff --git a/src/main.rs b/src/main.rs
index 53f3a41..5775d70 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,6 +1,6 @@
 use std::path::PathBuf;
 
-use bpaf::{construct, positional, OptionParser, Parser};
+use bpaf::{OptionParser, Parser, construct, positional};
 use demosaic::Demosaic;
 use image::buffer::ConvertBuffer;
 
@@ -9,7 +9,7 @@ mod pipeline;
 
 #[derive(Clone, Debug)]
 struct Args {
-    paths: Vec<PathBuf>
+    paths: Vec<PathBuf>,
 }
 
 fn args() -> OptionParser<Args> {
@@ -26,19 +26,28 @@ fn main() {
 
     // Initialize GPU
     let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor::default());
-    let adapter = pollster::block_on(instance.request_adapter(&wgpu::RequestAdapterOptions::default())).unwrap();
+    let adapter =
+        pollster::block_on(instance.request_adapter(&wgpu::RequestAdapterOptions::default()))
+            .unwrap();
 
     let downlevel_caps = adapter.get_downlevel_capabilities();
-    if !downlevel_caps.flags.contains(wgpu::DownlevelFlags::COMPUTE_SHADERS) {
+    if !downlevel_caps
+        .flags
+        .contains(wgpu::DownlevelFlags::COMPUTE_SHADERS)
+    {
         panic!("GPU does not support compute");
     }
 
-    let (gpu, queue) = pollster::block_on(adapter.request_device(&wgpu::DeviceDescriptor {
-        label: None,
-        required_features: wgpu::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES,
-        required_limits: wgpu::Limits::default(),
-        memory_hints: wgpu::MemoryHints::MemoryUsage,
-    }, None)).unwrap();
+    let (gpu, queue) = pollster::block_on(adapter.request_device(
+        &wgpu::DeviceDescriptor {
+            label: None,
+            required_features: wgpu::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES,
+            required_limits: wgpu::Limits::default(),
+            memory_hints: wgpu::MemoryHints::MemoryUsage,
+        },
+        None,
+    ))
+    .unwrap();
 
     // Process images
     for path in &args.paths {
@@ -46,7 +55,7 @@ fn main() {
         dbg!(&image.cfa);
 
         let pipeline = pipeline::Resources {
-            demosaic: Box::new(demosaic::Lmmse::new(&gpu, &queue))
+            demosaic: Box::new(demosaic::Lmmse::new(&gpu, &queue)),
         };
         let demosaiced = pipeline.demosaic.demoasic(&gpu, &queue, &image);
 
@@ -56,9 +65,8 @@ fn main() {
             usage: wgpu::BufferUsages::MAP_READ | wgpu::BufferUsages::COPY_DST,
             mapped_at_creation: false,
         });
-        let mut encoder = gpu.create_command_encoder(&wgpu::CommandEncoderDescriptor {
-            label: None,
-        });
+        let mut encoder =
+            gpu.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
         encoder.copy_texture_to_buffer(
             wgpu::TexelCopyTextureInfo {
                 texture: &demosaiced,
@@ -78,7 +86,7 @@ fn main() {
                 width: image.width as u32,
                 height: image.height as u32,
                 depth_or_array_layers: 1,
-            }
+            },
         );
         queue.submit([encoder.finish()]);
 
@@ -87,8 +95,17 @@ fn main() {
         gpu.poll(wgpu::Maintain::Wait);
         {
             let readback_data = readback_slice.get_mapped_range();
-            let result_image = image::ImageBuffer::<image::Rgba<f32>, _>::from_raw(image.width as u32, image.height as u32, bytemuck::cast_slice(&readback_data)).unwrap();
-            <_ as ConvertBuffer<image::ImageBuffer<image::Rgb<u16>, Vec<u16>>>>::convert(&result_image).save_with_format("out.png", image::ImageFormat::Png).unwrap();
+            let result_image = image::ImageBuffer::<image::Rgba<f32>, _>::from_raw(
+                image.width as u32,
+                image.height as u32,
+                bytemuck::cast_slice(&readback_data),
+            )
+            .unwrap();
+            <_ as ConvertBuffer<image::ImageBuffer<image::Rgb<u16>, Vec<u16>>>>::convert(
+                &result_image,
+            )
+            .save_with_format("out.png", image::ImageFormat::Png)
+            .unwrap();
         }
         readback_buf.unmap();
     }
diff --git a/src/pipeline.rs b/src/pipeline.rs
index 3ef02d6..c68935d 100644
--- a/src/pipeline.rs
+++ b/src/pipeline.rs
@@ -1,5 +1,5 @@
 use crate::demosaic::Demosaic;
 
 pub struct Resources {
-	pub demosaic: Box<dyn Demosaic>,
+    pub demosaic: Box<dyn Demosaic>,
 }