diff options
Diffstat (limited to 'vgcodec')
-rw-r--r-- | vgcodec/Cargo.lock | 80 | ||||
-rw-r--r-- | vgcodec/Cargo.toml | 1 | ||||
-rw-r--r-- | vgcodec/src/approximate.rs | 78 | ||||
-rw-r--r-- | vgcodec/src/helper.rs | 14 | ||||
-rw-r--r-- | vgcodec/src/main.rs | 20 | ||||
-rw-r--r-- | vgcodec/src/paint.rs | 3 | ||||
-rw-r--r-- | vgcodec/src/paint.wgsl | 7 |
7 files changed, 162 insertions, 41 deletions
diff --git a/vgcodec/Cargo.lock b/vgcodec/Cargo.lock index 390443b..41f0fcf 100644 --- a/vgcodec/Cargo.lock +++ b/vgcodec/Cargo.lock @@ -153,6 +153,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" [[package]] +name = "clap" +version = "4.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2148adefda54e14492fb9bddcc600b4344c5d1a3123bd666dcb939c6f0e0e57e" +dependencies = [ + "atty", + "bitflags", + "clap_derive", + "clap_lex", + "once_cell", + "strsim", + "termcolor", +] + +[[package]] +name = "clap_derive" +version = "4.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8" +dependencies = [ + "os_str_bytes", +] + +[[package]] name = "codespan-reporting" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -468,6 +505,12 @@ dependencies = [ ] [[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + +[[package]] name = "hermit-abi" version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -738,6 +781,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" [[package]] +name = "os_str_bytes" +version = "6.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" + +[[package]] name = "parking_lot" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -811,6 +860,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] name = "proc-macro2" version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -993,6 +1066,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] name = "syn" version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1081,6 +1160,7 @@ name = "vgcodec" version = "0.1.0" dependencies = [ "bytemuck", + "clap", "env_logger", "futures-intrusive", "image", diff --git a/vgcodec/Cargo.toml b/vgcodec/Cargo.toml index dd76753..b9a8415 100644 --- a/vgcodec/Cargo.toml +++ b/vgcodec/Cargo.toml @@ -12,3 +12,4 @@ bytemuck = { version = "1.12.3", features = ["derive"] } futures-intrusive = "0.5.0" image = "0.24.5" rand = "0.8.5" +clap = { version = "4.0.26", features = ["derive"] } diff --git a/vgcodec/src/approximate.rs b/vgcodec/src/approximate.rs index fc2b4ba..c4dc629 100644 --- a/vgcodec/src/approximate.rs +++ b/vgcodec/src/approximate.rs @@ -1,17 +1,13 @@ -use std::sync::Arc; - -use image::EncodableLayout; -use log::info; -use rand::Rng; -use wgpu::{Extent3d, Texture, TextureUsages}; - use crate::{ app::App, diff::Differ, export::Exporter, - helper::write_texture, paint::{PaintUniforms, Painter}, }; +use log::{debug, info}; +use rand::Rng; +use std::sync::Arc; +use wgpu::{Extent3d, Texture, TextureUsages}; #[allow(unused)] pub struct Approximator { @@ -28,7 +24,7 @@ pub struct Approximator { impl Approximator { pub fn new(app: &Arc<App>, tex_target: Texture, size: Extent3d) -> Self { - let App { device, queue, .. } = app.as_ref(); + let App { device, .. } = app.as_ref(); let tex_approx = device.create_texture(&wgpu::TextureDescriptor { size, mip_level_count: 1, @@ -51,8 +47,8 @@ impl Approximator { label: None, }); - let img_initial = image::open("a/initial.png").unwrap().into_rgba8(); - write_texture(queue, &tex_approx, img_initial.as_bytes(), size); + // let initial_init = (0..) + // write_texture(queue, &tex_approx, initial_init, size); let differ = Differ::new(&app, size, &tex_approx, &tex_target); let painter = Painter::new(&app, size, &tex_approx); @@ -79,44 +75,62 @@ impl Approximator { .copy_texture(&self.tex_savestate, &self.tex_approx, self.size); } - pub async fn run(&mut self) { - for _ in 0..10 { + pub async fn run(&mut self, iters: usize) { + let rscale = self.size.width as f32 * 0.1; + for i in 0..iters { let mut p = PaintUniforms { - x: rand::thread_rng().gen_range(0.0..256.0), - y: rand::thread_rng().gen_range(0.0..256.0), + x: rand::thread_rng().gen_range(0.0..self.size.width as f32), + y: rand::thread_rng().gen_range(0.0..self.size.height as f32), + rx: rscale, + ry: rscale, r: rand::thread_rng().gen_range(0.0..1.0), g: rand::thread_rng().gen_range(0.0..1.0), b: rand::thread_rng().gen_range(0.0..1.0), - radius: rand::thread_rng().gen_range(5.0..10.0), }; // Find initial diff self.save(); self.painter.run(p); - let mut cd = pollster::block_on(self.differ.run()); - info!("initial diff={cd}"); + let initial_diff = pollster::block_on(self.differ.run()); + debug!("initial diff={initial_diff}"); self.restore(); + let mut cd = initial_diff; self.save(); loop { let mut q = 0; - q += self.optimize_param(&mut cd, &mut p, "more red", |p| p.r += 0.1); - q += self.optimize_param(&mut cd, &mut p, "less red", |p| p.r -= 0.1); - q += self.optimize_param(&mut cd, &mut p, "more green", |p| p.g += 0.1); - q += self.optimize_param(&mut cd, &mut p, "less green", |p| p.g -= 0.1); - q += self.optimize_param(&mut cd, &mut p, "more blue", |p| p.b += 0.1); - q += self.optimize_param(&mut cd, &mut p, "less blue", |p| p.b -= 0.1); - q += self.optimize_param(&mut cd, &mut p, "increase radius", |p| p.radius *= 1.5); - q += self.optimize_param(&mut cd, &mut p, "decrease radius", |p| p.radius *= 1.5); - q += self.optimize_param(&mut cd, &mut p, "move right", |p| p.x += 5.0); - q += self.optimize_param(&mut cd, &mut p, "move left", |p| p.x -= 5.0); - q += self.optimize_param(&mut cd, &mut p, "move down", |p| p.y += 5.0); - q += self.optimize_param(&mut cd, &mut p, "move up", |p| p.y -= 5.0); + let mut k = |k: usize| { + q += k; + q == 0 + }; + if k(self.optimize_param(&mut cd, &mut p, "more red", |p| p.r += 0.1)) { + k(self.optimize_param(&mut cd, &mut p, "less red", |p| p.r -= 0.1)); + } + if k(self.optimize_param(&mut cd, &mut p, "more green", |p| p.g += 0.1)) { + k(self.optimize_param(&mut cd, &mut p, "less green", |p| p.g -= 0.1)); + } + if k(self.optimize_param(&mut cd, &mut p, "more blue", |p| p.b += 0.1)) { + k(self.optimize_param(&mut cd, &mut p, "less blue", |p| p.b -= 0.1)); + } + if k(self.optimize_param(&mut cd, &mut p, "increase rx", |p| p.rx *= 1.5)) { + k(self.optimize_param(&mut cd, &mut p, "decrease rx", |p| p.rx /= 1.5)); + } + if k(self.optimize_param(&mut cd, &mut p, "increase ry", |p| p.ry *= 1.5)) { + k(self.optimize_param(&mut cd, &mut p, "decrease ry", |p| p.ry /= 1.5)); + } + if k(self.optimize_param(&mut cd, &mut p, "move right", |p| p.x += 5.0)) { + k(self.optimize_param(&mut cd, &mut p, "move left", |p| p.x -= 5.0)); + } + if k(self.optimize_param(&mut cd, &mut p, "move down", |p| p.y += 5.0)) { + k(self.optimize_param(&mut cd, &mut p, "move up", |p| p.y -= 5.0)); + } if q == 0 { break; } } self.painter.run(p); + + info!("{i} (improvement={})", initial_diff - cd); } self.exporter.run(&self.tex_approx, "a/approx.png").await; @@ -139,13 +153,15 @@ impl Approximator { self.painter.run(p); let diff = pollster::block_on(self.differ.run()); // pollster::block_on(self.exporter.run(&self.tex_approx, &format!("a/snap.png"))); + debug!("try {label:?} ({})", diff as i64 - *current_diff as i64); self.restore(); if diff >= *current_diff { break i; } - info!("applied {label:?} (before={current_diff} after={diff})"); + debug!("applied {label:?}"); i += 1; *current_diff = diff; + *params = p } } } diff --git a/vgcodec/src/helper.rs b/vgcodec/src/helper.rs index 3aca81d..1d029b8 100644 --- a/vgcodec/src/helper.rs +++ b/vgcodec/src/helper.rs @@ -1,7 +1,15 @@ -use wgpu::{Queue, Texture, Extent3d}; - +use log::info; +use wgpu::{Extent3d, Queue, Texture}; pub fn write_texture(queue: &Queue, target: &Texture, data: &[u8], size: Extent3d) { + info!("uploading texture {size:?} ({} bytes)", data.len()); + + let bytes_per_pixel = std::mem::size_of::<u32>() as u32; + let unpadded_bytes_per_row = size.width * bytes_per_pixel; + let align = wgpu::COPY_BYTES_PER_ROW_ALIGNMENT; + let padded_bytes_per_row_padding = (align - unpadded_bytes_per_row % align) % align; + let padded_bytes_per_row = unpadded_bytes_per_row + padded_bytes_per_row_padding; + queue.write_texture( wgpu::ImageCopyTexture { texture: &target, @@ -12,7 +20,7 @@ pub fn write_texture(queue: &Queue, target: &Texture, data: &[u8], size: Extent3 &data, wgpu::ImageDataLayout { offset: 0, - bytes_per_row: Some(std::num::NonZeroU32::try_from((size.width * 4) as u32).unwrap()), + bytes_per_row: Some(std::num::NonZeroU32::try_from(padded_bytes_per_row).unwrap()), rows_per_image: None, }, size, diff --git a/vgcodec/src/main.rs b/vgcodec/src/main.rs index 7fb0750..2be0793 100644 --- a/vgcodec/src/main.rs +++ b/vgcodec/src/main.rs @@ -7,8 +7,9 @@ pub mod paint; use app::App; use approximate::Approximator; +use clap::Parser; use helper::write_texture; -use image::EncodableLayout; +use log::info; use wgpu::TextureUsages; fn main() { @@ -16,12 +17,21 @@ fn main() { pollster::block_on(run()); } +#[derive(Parser)] +#[clap(about)] +struct Args { + #[clap(short = 'I', long)] + iterations: usize, + infile: String, +} + async fn run() { + let args = Args::parse(); let app = app::App::new().await; let App { device, queue, .. } = app.as_ref(); - let img_target = image::open("a/a.png").unwrap().into_rgba8(); + let img_target = image::open(&args.infile).unwrap().into_rgba8(); let size = wgpu::Extent3d { width: img_target.width(), @@ -39,8 +49,10 @@ async fn run() { label: None, }); - write_texture(queue, &tex_target, img_target.as_bytes(), size); + let img_raw = img_target.into_raw(); + info!("{}", img_raw.len()); + write_texture(queue, &tex_target, &img_raw, size); let mut a = Approximator::new(&app, tex_target, size); - a.run().await; + a.run(args.iterations).await; } diff --git a/vgcodec/src/paint.rs b/vgcodec/src/paint.rs index f25b749..33ab572 100644 --- a/vgcodec/src/paint.rs +++ b/vgcodec/src/paint.rs @@ -19,7 +19,8 @@ pub struct Painter { pub struct PaintUniforms { pub x: f32, pub y: f32, - pub radius: f32, + pub rx: f32, + pub ry: f32, pub r: f32, pub g: f32, pub b: f32, diff --git a/vgcodec/src/paint.wgsl b/vgcodec/src/paint.wgsl index f23e903..7006310 100644 --- a/vgcodec/src/paint.wgsl +++ b/vgcodec/src/paint.wgsl @@ -1,7 +1,8 @@ struct Uniforms { x: f32, y: f32, - radius: f32, + rx: f32, + ry: f32, r: f32, g: f32, b: f32 @@ -13,7 +14,9 @@ struct Uniforms { @compute @workgroup_size(1) fn main(@builtin(global_invocation_id) global_id: vec3<u32>) { let coords = global_id.xy; - if distance(vec2<f32>(coords), vec2(uniforms.x, uniforms.y)) < uniforms.radius { + let kc = vec2<f32>(coords) - vec2(uniforms.x, uniforms.y); + let d = length(kc / vec2(uniforms.rx, uniforms.ry)); + if d < 1.0 { textureStore(tex, vec2<i32>(coords), vec4<f32>(vec3<f32>(uniforms.r, uniforms.g, uniforms.b), 1.0)); } } |