mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-10 20:51:29 +11:00
Allow arbitrary output sizes (#206)
* Support basic resizing * Fix resizing
This commit is contained in:
parent
98e0499b31
commit
0755e8bfaa
|
@ -20,6 +20,7 @@ use std::{fs::File, io::BufWriter};
|
||||||
|
|
||||||
use engine::Engine;
|
use engine::Engine;
|
||||||
|
|
||||||
|
use render::next_multiple_of;
|
||||||
use wgpu::{Device, Limits, Queue};
|
use wgpu::{Device, Limits, Queue};
|
||||||
|
|
||||||
mod debug;
|
mod debug;
|
||||||
|
@ -30,7 +31,7 @@ mod render;
|
||||||
mod shaders;
|
mod shaders;
|
||||||
mod test_scene;
|
mod test_scene;
|
||||||
|
|
||||||
async fn run() -> Result<(), Box<dyn std::error::Error>> {
|
async fn run(dimensions: &Dimensions) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let instance = wgpu::Instance::new(wgpu::Backends::PRIMARY);
|
let instance = wgpu::Instance::new(wgpu::Backends::PRIMARY);
|
||||||
let adapter = instance.request_adapter(&Default::default()).await.unwrap();
|
let adapter = instance.request_adapter(&Default::default()).await.unwrap();
|
||||||
let features = adapter.features();
|
let features = adapter.features();
|
||||||
|
@ -47,7 +48,7 @@ async fn run() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
do_render(&device, &queue, &mut engine).await?;
|
do_render(&device, &queue, &mut engine, dimensions).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -69,6 +70,7 @@ async fn do_render(
|
||||||
device: &Device,
|
device: &Device,
|
||||||
queue: &Queue,
|
queue: &Queue,
|
||||||
engine: &mut Engine,
|
engine: &mut Engine,
|
||||||
|
dimensions: &Dimensions,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
let shaders = shaders::init_shaders(device, engine)?;
|
let shaders = shaders::init_shaders(device, engine)?;
|
||||||
|
@ -76,7 +78,7 @@ async fn do_render(
|
||||||
let scene = test_scene::gen_test_scene();
|
let scene = test_scene::gen_test_scene();
|
||||||
//test_scene::dump_scene_info(&scene);
|
//test_scene::dump_scene_info(&scene);
|
||||||
//let (recording, buf) = render::render(&scene, &shaders);
|
//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 downloads = engine.run_recording(&device, &queue, &recording)?;
|
||||||
let mapped = downloads.map();
|
let mapped = downloads.map();
|
||||||
device.poll(wgpu::Maintain::Wait);
|
device.poll(wgpu::Maintain::Wait);
|
||||||
|
@ -87,14 +89,43 @@ async fn do_render(
|
||||||
} else {
|
} else {
|
||||||
let file = File::create("image.png")?;
|
let file = File::create("image.png")?;
|
||||||
let w = BufWriter::new(file);
|
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);
|
encoder.set_color(png::ColorType::Rgba);
|
||||||
let mut writer = encoder.write_header()?;
|
let mut writer = encoder.write_header()?;
|
||||||
|
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)?;
|
writer.write_image_data(&buf)?;
|
||||||
|
} else {
|
||||||
|
let mut output = Vec::<u8>::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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
pub struct Dimensions {
|
||||||
pollster::block_on(run()).unwrap();
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut args = std::env::args();
|
||||||
|
args.next();
|
||||||
|
let width = args
|
||||||
|
.next()
|
||||||
|
.and_then(|it| it.parse::<u32>().ok())
|
||||||
|
.unwrap_or(1024);
|
||||||
|
let height = args
|
||||||
|
.next()
|
||||||
|
.and_then(|it| it.parse::<u32>().ok())
|
||||||
|
.unwrap_or(1024);
|
||||||
|
pollster::block_on(run(&Dimensions { width, height })).unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ use piet_scene::Scene;
|
||||||
use crate::{
|
use crate::{
|
||||||
engine::{BufProxy, Recording, ResourceProxy},
|
engine::{BufProxy, Recording, ResourceProxy},
|
||||||
shaders::{self, FullShaders, Shaders},
|
shaders::{self, FullShaders, Shaders},
|
||||||
|
Dimensions,
|
||||||
};
|
};
|
||||||
|
|
||||||
const TAG_MONOID_SIZE: u64 = 12;
|
const TAG_MONOID_SIZE: u64 = 12;
|
||||||
|
@ -52,7 +53,14 @@ fn size_to_words(byte_size: usize) -> u32 {
|
||||||
(byte_size / std::mem::size_of::<u32>()) as u32
|
(byte_size / std::mem::size_of::<u32>()) 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 mut recording = Recording::default();
|
||||||
let data = scene.data();
|
let data = scene.data();
|
||||||
let n_pathtag = data.tag_stream.len();
|
let n_pathtag = data.tag_stream.len();
|
||||||
|
@ -125,7 +133,11 @@ pub fn render(scene: &Scene, shaders: &Shaders) -> (Recording, BufProxy) {
|
||||||
(recording, out_buf)
|
(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 recording = Recording::default();
|
||||||
let mut ramps = crate::ramp::RampCache::default();
|
let mut ramps = crate::ramp::RampCache::default();
|
||||||
let mut drawdata_patches: Vec<(usize, u32)> = vec![];
|
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
|
// TODO: calculate for real when we do rectangles
|
||||||
let n_drawobj = n_path;
|
let n_drawobj = n_path;
|
||||||
let n_clip = data.n_clip;
|
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 {
|
let config = Config {
|
||||||
width_in_tiles: 64,
|
// TODO: Replace with div_ceil once stable
|
||||||
height_in_tiles: 64,
|
width_in_tiles: new_width / 16,
|
||||||
|
height_in_tiles: new_height / 16,
|
||||||
n_drawobj,
|
n_drawobj,
|
||||||
n_path,
|
n_path,
|
||||||
n_clip,
|
n_clip,
|
||||||
|
|
Loading…
Reference in a new issue