mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-09 20:31:29 +11:00
commit
feeaa31fd1
72
Cargo.lock
generated
72
Cargo.lock
generated
|
@ -26,6 +26,15 @@ version = "0.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407"
|
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]]
|
[[package]]
|
||||||
name = "approx"
|
name = "approx"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
|
@ -59,6 +68,17 @@ dependencies = [
|
||||||
"raw-window-handle",
|
"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]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
@ -106,6 +126,21 @@ version = "0.1.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
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]]
|
[[package]]
|
||||||
name = "cloudabi"
|
name = "cloudabi"
|
||||||
version = "0.0.3"
|
version = "0.0.3"
|
||||||
|
@ -259,6 +294,15 @@ version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f36b5f248235f45773d4944f555f83ea61fe07b18b561ccf99d7483d7381e54d"
|
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]]
|
[[package]]
|
||||||
name = "inflate"
|
name = "inflate"
|
||||||
version = "0.4.5"
|
version = "0.4.5"
|
||||||
|
@ -525,6 +569,7 @@ dependencies = [
|
||||||
name = "piet-gpu"
|
name = "piet-gpu"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"clap",
|
||||||
"piet",
|
"piet",
|
||||||
"piet-gpu-hal",
|
"piet-gpu-hal",
|
||||||
"piet-gpu-types",
|
"piet-gpu-types",
|
||||||
|
@ -758,6 +803,12 @@ dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.17"
|
version = "1.0.17"
|
||||||
|
@ -769,6 +820,21 @@ dependencies = [
|
||||||
"unicode-xid 0.2.0",
|
"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]]
|
[[package]]
|
||||||
name = "unicode-xid"
|
name = "unicode-xid"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -781,6 +847,12 @@ version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vec_map"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "void"
|
name = "void"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
|
|
|
@ -26,3 +26,4 @@ png = "0.16.2"
|
||||||
rand = "0.7.3"
|
rand = "0.7.3"
|
||||||
roxmltree = "0.11"
|
roxmltree = "0.11"
|
||||||
winit = "0.22"
|
winit = "0.22"
|
||||||
|
clap = "2.33"
|
||||||
|
|
|
@ -2,10 +2,12 @@ use std::fs::File;
|
||||||
use std::io::BufWriter;
|
use std::io::BufWriter;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
use clap::{Arg, App};
|
||||||
|
|
||||||
use piet_gpu_hal::vulkan::VkInstance;
|
use piet_gpu_hal::vulkan::VkInstance;
|
||||||
use piet_gpu_hal::{CmdBuf, Device, Error, MemFlags};
|
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)]
|
#[allow(unused)]
|
||||||
fn dump_scene(buf: &[u8]) {
|
fn dump_scene(buf: &[u8]) {
|
||||||
|
@ -152,6 +154,17 @@ fn trace_ptcl(buf: &[u32]) {
|
||||||
|
|
||||||
|
|
||||||
fn main() -> Result<(), Error> {
|
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)?;
|
let (instance, _) = VkInstance::new(None)?;
|
||||||
unsafe {
|
unsafe {
|
||||||
let device = instance.device(None)?;
|
let device = instance.device(None)?;
|
||||||
|
@ -161,7 +174,17 @@ fn main() -> Result<(), Error> {
|
||||||
let query_pool = device.create_query_pool(5)?;
|
let query_pool = device.create_query_pool(5)?;
|
||||||
|
|
||||||
let mut ctx = PietGpuRenderContext::new();
|
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();
|
let scene = ctx.get_scene_buf();
|
||||||
//dump_scene(&scene);
|
//dump_scene(&scene);
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,17 @@ const N_CIRCLES: usize = 0;
|
||||||
|
|
||||||
const N_WG: u32 = 16;
|
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) {
|
pub fn render_scene(rc: &mut impl RenderContext) {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
for _ in 0..N_CIRCLES {
|
for _ in 0..N_CIRCLES {
|
||||||
|
@ -138,7 +149,7 @@ pub struct Renderer<D: Device> {
|
||||||
|
|
||||||
k4_pipeline: D::Pipeline,
|
k4_pipeline: D::Pipeline,
|
||||||
k4_ds: D::DescriptorSet,
|
k4_ds: D::DescriptorSet,
|
||||||
|
|
||||||
n_elements: usize,
|
n_elements: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,13 +188,10 @@ impl<D: Device> Renderer<D> {
|
||||||
|
|
||||||
// TODO: constants
|
// TODO: constants
|
||||||
let bin_alloc_start = ((n_elements + 255) & !255) * 8;
|
let bin_alloc_start = ((n_elements + 255) & !255) * 8;
|
||||||
device
|
device.write_buffer(
|
||||||
.write_buffer(&bin_alloc_buf_host, &[
|
&bin_alloc_buf_host,
|
||||||
n_elements as u32,
|
&[n_elements as u32, 0, bin_alloc_start as u32],
|
||||||
0,
|
)?;
|
||||||
bin_alloc_start as u32,
|
|
||||||
])
|
|
||||||
?;
|
|
||||||
let bin_code = include_bytes!("../shader/binning.spv");
|
let bin_code = include_bytes!("../shader/binning.spv");
|
||||||
let bin_pipeline = device.create_simple_compute_pipeline(bin_code, 4, 0)?;
|
let bin_pipeline = device.create_simple_compute_pipeline(bin_code, 4, 0)?;
|
||||||
let bin_ds = device.create_descriptor_set(
|
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_buf_dev = device.create_buffer(8, dev)?;
|
||||||
|
|
||||||
let coarse_alloc_start = WIDTH_IN_TILES * HEIGHT_IN_TILES * PTCL_INITIAL_ALLOC;
|
let coarse_alloc_start = WIDTH_IN_TILES * HEIGHT_IN_TILES * PTCL_INITIAL_ALLOC;
|
||||||
device
|
device.write_buffer(
|
||||||
.write_buffer(&coarse_alloc_buf_host, &[
|
&coarse_alloc_buf_host,
|
||||||
n_elements as u32,
|
&[n_elements as u32, coarse_alloc_start as u32],
|
||||||
coarse_alloc_start as u32,
|
)?;
|
||||||
])
|
|
||||||
?;
|
|
||||||
let coarse_code = include_bytes!("../shader/coarse.spv");
|
let coarse_code = include_bytes!("../shader/coarse.spv");
|
||||||
let coarse_pipeline = device.create_simple_compute_pipeline(coarse_code, 4, 0)?;
|
let coarse_pipeline = device.create_simple_compute_pipeline(coarse_code, 4, 0)?;
|
||||||
let coarse_ds = device.create_descriptor_set(
|
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_code = include_bytes!("../shader/kernel4.spv");
|
||||||
let k4_pipeline = device.create_simple_compute_pipeline(k4_code, 1, 1)?;
|
let k4_pipeline = device.create_simple_compute_pipeline(k4_code, 1, 1)?;
|
||||||
let k4_ds = device.create_descriptor_set(
|
let k4_ds = device.create_descriptor_set(&k4_pipeline, &[&ptcl_buf], &[&image_dev])?;
|
||||||
&k4_pipeline,
|
|
||||||
&[&ptcl_buf],
|
|
||||||
&[&image_dev],
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(Renderer {
|
Ok(Renderer {
|
||||||
scene_buf,
|
scene_buf,
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use roxmltree::Document;
|
use roxmltree::{Document, Node};
|
||||||
|
|
||||||
use piet::kurbo::{Affine, BezPath};
|
use piet::kurbo::{Affine, BezPath};
|
||||||
|
|
||||||
|
@ -28,31 +28,19 @@ pub struct FillItem {
|
||||||
path: BezPath,
|
path: BezPath,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Parser<'a> {
|
||||||
|
scale: f64,
|
||||||
|
items: &'a mut Vec<Item>,
|
||||||
|
}
|
||||||
|
|
||||||
impl PicoSvg {
|
impl PicoSvg {
|
||||||
pub fn load(xml_string: &str, scale: f64) -> Result<PicoSvg, Box<dyn std::error::Error>> {
|
pub fn load(xml_string: &str, scale: f64) -> Result<PicoSvg, Box<dyn std::error::Error>> {
|
||||||
let doc = Document::parse(xml_string)?;
|
let doc = Document::parse(xml_string)?;
|
||||||
let root = doc.root_element();
|
let root = doc.root_element();
|
||||||
let g = root.first_element_child().ok_or("no root element")?;
|
|
||||||
let mut items = Vec::new();
|
let mut items = Vec::new();
|
||||||
for el in g.children() {
|
let mut parser = Parser::new(&mut items, scale);
|
||||||
if el.is_element() {
|
for node in root.children() {
|
||||||
let d = el.attribute("d").ok_or("missing 'd' attribute")?;
|
parser.rec_parse(node)?;
|
||||||
let bp = BezPath::from_svg(d)?;
|
|
||||||
let path = Affine::scale(scale) * bp;
|
|
||||||
if let Some(fill_color) = el.attribute("fill") {
|
|
||||||
let color = parse_color(fill_color);
|
|
||||||
items.push(Item::Fill(FillItem {
|
|
||||||
color,
|
|
||||||
path: path.clone(),
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
if let Some(stroke_color) = el.attribute("stroke") {
|
|
||||||
let width =
|
|
||||||
scale * f64::from_str(el.attribute("stroke-width").ok_or("missing width")?)?;
|
|
||||||
let color = parse_color(stroke_color);
|
|
||||||
items.push(Item::Stroke(StrokeItem { width, color, path }));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(PicoSvg { items })
|
Ok(PicoSvg { items })
|
||||||
}
|
}
|
||||||
|
@ -72,6 +60,59 @@ impl PicoSvg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Parser<'a> {
|
||||||
|
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" => {
|
||||||
|
for child in node.children() {
|
||||||
|
self.rec_parse(child)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"path" => {
|
||||||
|
let d = node.attribute("d").ok_or("missing 'd' attribute")?;
|
||||||
|
let bp = BezPath::from_svg(d)?;
|
||||||
|
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(),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(stroke_color) = node.attribute("stroke") {
|
||||||
|
if stroke_color != "none" {
|
||||||
|
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 }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_color(color: &str) -> Color {
|
fn parse_color(color: &str) -> Color {
|
||||||
if color.as_bytes()[0] == b'#' {
|
if color.as_bytes()[0] == b'#' {
|
||||||
let mut hex = u32::from_str_radix(&color[1..], 16).unwrap();
|
let mut hex = u32::from_str_radix(&color[1..], 16).unwrap();
|
||||||
|
@ -79,7 +120,27 @@ fn parse_color(color: &str) -> Color {
|
||||||
hex = (hex >> 8) * 0x110000 + ((hex >> 4) & 0xf) * 0x1100 + (hex & 0xf) * 0x11;
|
hex = (hex >> 8) * 0x110000 + ((hex >> 4) & 0xf) * 0x1100 + (hex & 0xf) * 0x11;
|
||||||
}
|
}
|
||||||
Color::from_rgba32_u32((hex << 8) + 0xff)
|
Color::from_rgba32_u32((hex << 8) + 0xff)
|
||||||
|
} else if color.starts_with("rgb(") {
|
||||||
|
let mut iter = color[4..color.len() - 1].split(',');
|
||||||
|
let r = u8::from_str(iter.next().unwrap()).unwrap();
|
||||||
|
let g = u8::from_str(iter.next().unwrap()).unwrap();
|
||||||
|
let b = u8::from_str(iter.next().unwrap()).unwrap();
|
||||||
|
Color::rgb8(r, g, b)
|
||||||
} else {
|
} else {
|
||||||
Color::from_rgba32_u32(0xff00ff80)
|
Color::from_rgba32_u32(0xff00ff80)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn modify_opacity(color: Color, attr_name: &str, node: Node) -> Color {
|
||||||
|
if let Some(opacity) = node.attribute(attr_name) {
|
||||||
|
let alpha = if opacity.ends_with("%") {
|
||||||
|
let pctg = opacity[..opacity.len() - 1].parse().unwrap_or(100.0);
|
||||||
|
pctg * 0.01
|
||||||
|
} else {
|
||||||
|
opacity.parse().unwrap_or(1.0)
|
||||||
|
};
|
||||||
|
color.with_alpha(alpha)
|
||||||
|
} else {
|
||||||
|
color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue