Add command line args for loading svg

This commit is contained in:
Raph Levien 2020-05-31 09:55:20 -07:00
parent c603cafc6c
commit f3cb904f86
5 changed files with 139 additions and 30 deletions

72
Cargo.lock generated
View file

@ -26,6 +26,15 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407"
[[package]]
name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
dependencies = [
"winapi 0.3.8",
]
[[package]]
name = "approx"
version = "0.3.2"
@ -59,6 +68,17 @@ dependencies = [
"raw-window-handle",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi 0.3.8",
]
[[package]]
name = "autocfg"
version = "1.0.0"
@ -106,6 +126,21 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "clap"
version = "2.33.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129"
dependencies = [
"ansi_term",
"atty",
"bitflags",
"strsim",
"textwrap",
"unicode-width",
"vec_map",
]
[[package]]
name = "cloudabi"
version = "0.0.3"
@ -259,6 +294,15 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f36b5f248235f45773d4944f555f83ea61fe07b18b561ccf99d7483d7381e54d"
[[package]]
name = "hermit-abi"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71"
dependencies = [
"libc",
]
[[package]]
name = "inflate"
version = "0.4.5"
@ -525,6 +569,7 @@ dependencies = [
name = "piet-gpu"
version = "0.1.0"
dependencies = [
"clap",
"piet",
"piet-gpu-hal",
"piet-gpu-types",
@ -758,6 +803,12 @@ dependencies = [
"byteorder",
]
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "syn"
version = "1.0.17"
@ -769,6 +820,21 @@ dependencies = [
"unicode-xid 0.2.0",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"unicode-width",
]
[[package]]
name = "unicode-width"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
[[package]]
name = "unicode-xid"
version = "0.1.0"
@ -781,6 +847,12 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "void"
version = "1.0.2"

View file

@ -26,3 +26,4 @@ png = "0.16.2"
rand = "0.7.3"
roxmltree = "0.11"
winit = "0.22"
clap = "2.33"

View file

@ -2,10 +2,12 @@ use std::fs::File;
use std::io::BufWriter;
use std::path::Path;
use clap::{Arg, App};
use piet_gpu_hal::vulkan::VkInstance;
use piet_gpu_hal::{CmdBuf, Device, Error, MemFlags};
use piet_gpu::{render_scene, PietGpuRenderContext, Renderer, HEIGHT, WIDTH};
use piet_gpu::{render_scene, render_svg, PietGpuRenderContext, Renderer, HEIGHT, WIDTH};
#[allow(unused)]
fn dump_scene(buf: &[u8]) {
@ -152,6 +154,17 @@ fn trace_ptcl(buf: &[u32]) {
fn main() -> Result<(), Error> {
let matches = App::new("piet-gpu test")
.arg(Arg::with_name("INPUT")
.index(1))
.arg(Arg::with_name("flip")
.short("f")
.long("flip"))
.arg(Arg::with_name("scale")
.short("s")
.long("scale")
.takes_value(true))
.get_matches();
let (instance, _) = VkInstance::new(None)?;
unsafe {
let device = instance.device(None)?;
@ -161,7 +174,17 @@ fn main() -> Result<(), Error> {
let query_pool = device.create_query_pool(5)?;
let mut ctx = PietGpuRenderContext::new();
render_scene(&mut ctx);
if let Some(input) = matches.value_of("INPUT") {
let mut scale = matches.value_of("scale")
.map(|scale| scale.parse().unwrap())
.unwrap_or(8.0);
if matches.is_present("flip") {
scale = -scale;
}
render_svg(&mut ctx, input, scale);
} else {
render_scene(&mut ctx);
}
let scene = ctx.get_scene_buf();
//dump_scene(&scene);

View file

@ -34,6 +34,17 @@ const N_CIRCLES: usize = 0;
const N_WG: u32 = 16;
pub fn render_svg(rc: &mut impl RenderContext, filename: &str, scale: f64) {
let xml_str = std::fs::read_to_string(filename).unwrap();
let start = std::time::Instant::now();
let svg = PicoSvg::load(&xml_str, scale).unwrap();
println!("parsing time: {:?}", start.elapsed());
let start = std::time::Instant::now();
svg.render(rc);
println!("flattening and encoding time: {:?}", start.elapsed());
}
pub fn render_scene(rc: &mut impl RenderContext) {
let mut rng = rand::thread_rng();
for _ in 0..N_CIRCLES {
@ -138,7 +149,7 @@ pub struct Renderer<D: Device> {
k4_pipeline: D::Pipeline,
k4_ds: D::DescriptorSet,
n_elements: usize,
}
@ -177,13 +188,10 @@ impl<D: Device> Renderer<D> {
// TODO: constants
let bin_alloc_start = ((n_elements + 255) & !255) * 8;
device
.write_buffer(&bin_alloc_buf_host, &[
n_elements as u32,
0,
bin_alloc_start as u32,
])
?;
device.write_buffer(
&bin_alloc_buf_host,
&[n_elements as u32, 0, bin_alloc_start as u32],
)?;
let bin_code = include_bytes!("../shader/binning.spv");
let bin_pipeline = device.create_simple_compute_pipeline(bin_code, 4, 0)?;
let bin_ds = device.create_descriptor_set(
@ -196,12 +204,10 @@ impl<D: Device> Renderer<D> {
let coarse_alloc_buf_dev = device.create_buffer(8, dev)?;
let coarse_alloc_start = WIDTH_IN_TILES * HEIGHT_IN_TILES * PTCL_INITIAL_ALLOC;
device
.write_buffer(&coarse_alloc_buf_host, &[
n_elements as u32,
coarse_alloc_start as u32,
])
?;
device.write_buffer(
&coarse_alloc_buf_host,
&[n_elements as u32, coarse_alloc_start as u32],
)?;
let coarse_code = include_bytes!("../shader/coarse.spv");
let coarse_pipeline = device.create_simple_compute_pipeline(coarse_code, 4, 0)?;
let coarse_ds = device.create_descriptor_set(
@ -212,11 +218,7 @@ impl<D: Device> Renderer<D> {
let k4_code = include_bytes!("../shader/kernel4.spv");
let k4_pipeline = device.create_simple_compute_pipeline(k4_code, 1, 1)?;
let k4_ds = device.create_descriptor_set(
&k4_pipeline,
&[&ptcl_buf],
&[&image_dev],
)?;
let k4_ds = device.create_descriptor_set(&k4_pipeline, &[&ptcl_buf], &[&image_dev])?;
Ok(Renderer {
scene_buf,

View file

@ -29,6 +29,7 @@ pub struct FillItem {
}
struct Parser<'a> {
scale: f64,
items: &'a mut Vec<Item>,
}
@ -37,7 +38,7 @@ impl PicoSvg {
let doc = Document::parse(xml_string)?;
let root = doc.root_element();
let mut items = Vec::new();
let mut parser = Parser::new(&mut items);
let mut parser = Parser::new(&mut items, scale);
for node in root.children() {
parser.rec_parse(node)?;
}
@ -60,13 +61,16 @@ impl PicoSvg {
}
impl<'a> Parser<'a> {
fn new(items: &'a mut Vec<Item>) -> Parser<'a> {
Parser {
items
}
fn new(items: &'a mut Vec<Item>, scale: f64) -> Parser<'a> {
Parser { scale, items }
}
fn rec_parse(&mut self, node: Node) -> Result<(), Box<dyn std::error::Error>> {
let transform = if self.scale >= 0.0 {
Affine::scale(self.scale)
} else {
Affine::new([-self.scale, 0.0, 0.0, self.scale, 0.0, 1536.0])
};
if node.is_element() {
match node.tag_name().name() {
"g" => {
@ -77,21 +81,28 @@ impl<'a> Parser<'a> {
"path" => {
let d = node.attribute("d").ok_or("missing 'd' attribute")?;
let bp = BezPath::from_svg(d)?;
let path = Affine::new([1.5, 0.0, 0.0, -1.5, 0.0, 1500.0]) * bp;
let path = transform * bp;
// TODO: default fill color is black, but this is overridden in tiger to this logic.
if let Some(fill_color) = node.attribute("fill") {
if fill_color != "none" {
let color = parse_color(fill_color);
let color = modify_opacity(color, "fill-opacity", node);
self.items.push(Item::Fill(FillItem { color, path: path.clone() }));
self.items.push(Item::Fill(FillItem {
color,
path: path.clone(),
}));
}
}
if let Some(stroke_color) = node.attribute("stroke") {
if stroke_color != "none" {
let width = 1.5 * f64::from_str(node.attribute("stroke-width").ok_or("missing width")?)?;
let width = self.scale.abs()
* f64::from_str(
node.attribute("stroke-width").ok_or("missing width")?,
)?;
let color = parse_color(stroke_color);
let color = modify_opacity(color, "stroke-opacity", node);
self.items.push(Item::Stroke(StrokeItem { width, color, path }));
self.items
.push(Item::Stroke(StrokeItem { width, color, path }));
}
}
}