From 0755e8bfaa7fea46e1d29902229fcde756fbad1e Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Wed, 23 Nov 2022 17:34:04 +0000 Subject: [PATCH] Allow arbitrary output sizes (#206) * Support basic resizing * Fix resizing --- piet-wgsl/src/main.rs | 45 ++++++++++++++++++++++++++++++++++------- piet-wgsl/src/render.rs | 25 +++++++++++++++++++---- 2 files changed, 59 insertions(+), 11 deletions(-) diff --git a/piet-wgsl/src/main.rs b/piet-wgsl/src/main.rs index 4e10486..48ddef3 100644 --- a/piet-wgsl/src/main.rs +++ b/piet-wgsl/src/main.rs @@ -20,6 +20,7 @@ use std::{fs::File, io::BufWriter}; use engine::Engine; +use render::next_multiple_of; use wgpu::{Device, Limits, Queue}; mod debug; @@ -30,7 +31,7 @@ mod render; mod shaders; mod test_scene; -async fn run() -> Result<(), Box> { +async fn run(dimensions: &Dimensions) -> Result<(), Box> { let instance = wgpu::Instance::new(wgpu::Backends::PRIMARY); let adapter = instance.request_adapter(&Default::default()).await.unwrap(); let features = adapter.features(); @@ -47,7 +48,7 @@ async fn run() -> Result<(), Box> { ) .await?; let mut engine = Engine::new(); - do_render(&device, &queue, &mut engine).await?; + do_render(&device, &queue, &mut engine, dimensions).await?; Ok(()) } @@ -69,6 +70,7 @@ async fn do_render( device: &Device, queue: &Queue, engine: &mut Engine, + dimensions: &Dimensions, ) -> Result<(), Box> { #[allow(unused)] let shaders = shaders::init_shaders(device, engine)?; @@ -76,7 +78,7 @@ async fn do_render( let scene = test_scene::gen_test_scene(); //test_scene::dump_scene_info(&scene); //let (recording, buf) = render::render(&scene, &shaders); - let (recording, buf) = render::render_full(&scene, &full_shaders); + let (recording, buf) = render::render_full(&scene, &full_shaders, dimensions); let downloads = engine.run_recording(&device, &queue, &recording)?; let mapped = downloads.map(); device.poll(wgpu::Maintain::Wait); @@ -87,14 +89,43 @@ async fn do_render( } else { let file = File::create("image.png")?; let w = BufWriter::new(file); - let mut encoder = png::Encoder::new(w, 1024, 1024); + let mut encoder = png::Encoder::new(w, dimensions.width, dimensions.height); encoder.set_color(png::ColorType::Rgba); let mut writer = encoder.write_header()?; - writer.write_image_data(&buf)?; + let expected_size = (dimensions.width * dimensions.height * 4) as usize; + + let new_width = next_multiple_of(dimensions.width, 16) as usize; + + if expected_size == buf.len() { + writer.write_image_data(&buf)?; + } else { + let mut output = Vec::::with_capacity(expected_size * 4); + for height in 0..(dimensions.height as usize) { + output.extend_from_slice( + &buf[height * new_width * 4..][..dimensions.width as usize * 4], + ); + } + writer.write_image_data(&output)?; + } } Ok(()) } -fn main() { - pollster::block_on(run()).unwrap(); +pub struct Dimensions { + width: u32, + height: u32, +} + +fn main() { + let mut args = std::env::args(); + args.next(); + let width = args + .next() + .and_then(|it| it.parse::().ok()) + .unwrap_or(1024); + let height = args + .next() + .and_then(|it| it.parse::().ok()) + .unwrap_or(1024); + pollster::block_on(run(&Dimensions { width, height })).unwrap(); } diff --git a/piet-wgsl/src/render.rs b/piet-wgsl/src/render.rs index ee13694..56951fd 100644 --- a/piet-wgsl/src/render.rs +++ b/piet-wgsl/src/render.rs @@ -6,6 +6,7 @@ use piet_scene::Scene; use crate::{ engine::{BufProxy, Recording, ResourceProxy}, shaders::{self, FullShaders, Shaders}, + Dimensions, }; const TAG_MONOID_SIZE: u64 = 12; @@ -52,7 +53,14 @@ fn size_to_words(byte_size: usize) -> u32 { (byte_size / std::mem::size_of::()) as u32 } -pub fn render(scene: &Scene, shaders: &Shaders) -> (Recording, BufProxy) { +pub const fn next_multiple_of(val: u32, rhs: u32) -> u32 { + match val % rhs { + 0 => val, + r => val + (rhs - r), + } +} + +fn render(scene: &Scene, shaders: &Shaders) -> (Recording, BufProxy) { let mut recording = Recording::default(); let data = scene.data(); let n_pathtag = data.tag_stream.len(); @@ -125,7 +133,11 @@ pub fn render(scene: &Scene, shaders: &Shaders) -> (Recording, BufProxy) { (recording, out_buf) } -pub fn render_full(scene: &Scene, shaders: &FullShaders) -> (Recording, BufProxy) { +pub fn render_full( + scene: &Scene, + shaders: &FullShaders, + dimensions: &Dimensions, +) -> (Recording, BufProxy) { let mut recording = Recording::default(); let mut ramps = crate::ramp::RampCache::default(); let mut drawdata_patches: Vec<(usize, u32)> = vec![]; @@ -192,9 +204,14 @@ pub fn render_full(scene: &Scene, shaders: &FullShaders) -> (Recording, BufProxy // TODO: calculate for real when we do rectangles let n_drawobj = n_path; let n_clip = data.n_clip; + + let new_width = next_multiple_of(dimensions.width, 16); + let new_height = next_multiple_of(dimensions.width, 16); + let config = Config { - width_in_tiles: 64, - height_in_tiles: 64, + // TODO: Replace with div_ceil once stable + width_in_tiles: new_width / 16, + height_in_tiles: new_height / 16, n_drawobj, n_path, n_clip,