[vello_encoding] Move the encoding module into its own crate

This change moves the vello encoding logic to a new crate under
crates/encoding. Combined with the `vello_shaders` crate, this enables
lightweight integration of the Vello pipelines into renderers that don't
depend on wgpu (or perhaps written in languages other than Rust).

The Scene/Fragment API currently remain the vello crate.
This commit is contained in:
Arman Uguray 2023-04-10 16:59:44 -07:00
parent b8e1bcfac3
commit db2fefdc8f
18 changed files with 69 additions and 58 deletions

View file

@ -2,6 +2,7 @@
resolver = "2"
members = [
"crates/encoding",
"crates/shaders",
"integrations/vello_svg",
@ -40,17 +41,20 @@ hot_reload = []
buffer_labels = []
[dependencies]
bytemuck = { workspace = true }
fello = { workspace = true }
peniko = { workspace = true }
wgpu = { workspace = true }
raw-window-handle = "0.5"
futures-intrusive = "0.5.0"
parking_lot = "0.12"
bytemuck = { version = "1.12.1", features = ["derive"] }
smallvec = "1.8.0"
fello = { git = "https://github.com/dfrg/fount", rev = "58a284eaae67512fb61cf76177c5d33238d79cb1" }
peniko = { git = "https://github.com/linebender/peniko", rev = "cafdac9a211a0fb2fec5656bd663d1ac770bcc81" }
guillotiere = "0.6.2"
vello_encoding = { path = "crates/encoding" }
[workspace.dependencies]
bytemuck = { version = "1.12.1", features = ["derive"] }
fello = { git = "https://github.com/dfrg/fount", rev = "58a284eaae67512fb61cf76177c5d33238d79cb1" }
peniko = { git = "https://github.com/linebender/peniko", rev = "cafdac9a211a0fb2fec5656bd663d1ac770bcc81" }
wgpu = "0.15"
# Used for examples

View file

@ -0,0 +1,10 @@
[package]
name = "vello_encoding"
version = "0.1.0"
edition = "2021"
[dependencies]
bytemuck = { workspace = true }
fello = { workspace = true }
peniko = { workspace = true }
guillotiere = "0.6.2"

View file

@ -14,11 +14,9 @@
//
// Also licensed under MIT license, at your choice.
use crate::encoding::DrawImage;
use super::{
resolve::Patch, DrawColor, DrawLinearGradient, DrawRadialGradient, DrawTag, Glyph, GlyphRun,
PathEncoder, PathTag, Transform,
resolve::Patch, DrawColor, DrawImage, DrawLinearGradient, DrawRadialGradient, DrawTag, Glyph,
GlyphRun, PathEncoder, PathTag, Transform,
};
use fello::NormalizedCoord;

View file

@ -59,11 +59,11 @@ impl GlyphCache {
Style::Fill(Fill::EvenOdd) => encoding_cache.encode_linewidth(-2.0),
Style::Stroke(stroke) => encoding_cache.encode_linewidth(stroke.width),
}
let mut path = crate::glyph::PathEncoderPen(encoding_cache.encode_path(is_fill));
let mut path = encoding_cache.encode_path(is_fill);
scaler
.outline(GlyphId::new(key.glyph_id as u16), &mut path)
.ok()?;
if path.0.finish(false) == 0 {
if path.finish(false) == 0 {
return None;
}
let end = encoding_cache.stream_offsets();

View file

@ -381,3 +381,25 @@ impl<'a> PathEncoder<'a> {
self.n_encoded_segments
}
}
impl fello::scale::Pen for PathEncoder<'_> {
fn move_to(&mut self, x: f32, y: f32) {
self.move_to(x, y)
}
fn line_to(&mut self, x: f32, y: f32) {
self.line_to(x, y)
}
fn quad_to(&mut self, cx0: f32, cy0: f32, x: f32, y: f32) {
self.quad_to(cx0, cy0, x, y)
}
fn curve_to(&mut self, cx0: f32, cy0: f32, cx1: f32, cy1: f32, x: f32, y: f32) {
self.cubic_to(cx0, cy0, cx1, cy1, x, y)
}
fn close(&mut self) {
self.close()
}
}

View file

@ -25,7 +25,6 @@ use super::{
ramp_cache::{RampCache, Ramps},
DrawTag, Encoding, PathTag, StreamOffsets, Transform,
};
use crate::shaders;
/// Layout of a packed encoding.
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
@ -161,6 +160,7 @@ impl Resolver {
&'a mut self,
encoding: &Encoding,
packed: &mut Vec<u8>,
workgroup_size: u32,
) -> (Layout, Ramps<'a>, Images<'a>) {
let sizes = self.resolve_patches(encoding);
self.resolve_pending_images();
@ -172,7 +172,7 @@ impl Resolver {
// Compute size of data buffer
let n_path_tags =
encoding.path_tags.len() + sizes.path_tags + encoding.n_open_clips as usize;
let path_tag_padded = align_up(n_path_tags, 4 * shaders::PATHTAG_REDUCE_WG);
let path_tag_padded = align_up(n_path_tags, 4 * workgroup_size);
let capacity = path_tag_padded
+ slice_size_in_bytes(&encoding.path_data, sizes.path_data)
+ slice_size_in_bytes(

View file

@ -12,6 +12,7 @@ repository.workspace = true
[dependencies]
vello = { path = "../../" }
vello_encoding = { path = "../../crates/encoding" }
vello_svg = { path = "../../integrations/vello_svg" }
anyhow = { workspace = true }
clap = { workspace = true, features = ["derive"] }

View file

@ -17,7 +17,6 @@
use std::sync::Arc;
use vello::{
encoding::Glyph,
fello::meta::MetadataProvider,
fello::raw::FontRef,
glyph::GlyphContext,
@ -25,6 +24,7 @@ use vello::{
peniko::{Blob, Brush, BrushRef, Font, StyleRef},
SceneBuilder,
};
use vello_encoding::Glyph;
// This is very much a hack to get things working.
// On Windows, can set this to "c:\\Windows\\Fonts\\seguiemj.ttf" to get color emoji

View file

@ -16,18 +16,17 @@
//! Support for glyph rendering.
use fello::scale::Pen;
use crate::encoding::{Encoding, PathEncoder};
use crate::scene::{SceneBuilder, SceneFragment};
use peniko::kurbo::Affine;
use peniko::{Brush, Color, Fill, Style};
use fello::{
raw::types::GlyphId,
raw::FontRef,
scale::{Context, Scaler},
FontKey, Setting, Size,
use {
fello::{
raw::types::GlyphId,
raw::FontRef,
scale::{Context, Pen, Scaler},
FontKey, Setting, Size,
},
peniko::kurbo::Affine,
peniko::{Brush, Color, Fill, Style},
vello_encoding::Encoding,
};
/// General context for creating scene fragments for glyph outlines.
@ -105,9 +104,9 @@ impl<'a> GlyphProvider<'a> {
Style::Fill(Fill::EvenOdd) => encoding.encode_linewidth(-2.0),
Style::Stroke(stroke) => encoding.encode_linewidth(stroke.width),
}
let mut path = PathEncoderPen(encoding.encode_path(matches!(style, Style::Fill(_))));
let mut path = encoding.encode_path(matches!(style, Style::Fill(_)));
self.scaler.outline(GlyphId::new(gid), &mut path).ok()?;
if path.0.finish(false) != 0 {
if path.finish(false) != 0 {
Some(())
} else {
None
@ -144,27 +143,3 @@ impl Pen for BezPathPen {
self.0.close_path()
}
}
pub(crate) struct PathEncoderPen<'a>(pub PathEncoder<'a>);
impl Pen for PathEncoderPen<'_> {
fn move_to(&mut self, x: f32, y: f32) {
self.0.move_to(x, y)
}
fn line_to(&mut self, x: f32, y: f32) {
self.0.line_to(x, y)
}
fn quad_to(&mut self, cx0: f32, cy0: f32, x: f32, y: f32) {
self.0.quad_to(cx0, cy0, x, y)
}
fn curve_to(&mut self, cx0: f32, cy0: f32, cx1: f32, cy1: f32, x: f32, y: f32) {
self.0.cubic_to(cx0, cy0, cx1, cy1, x, y)
}
fn close(&mut self) {
self.0.close()
}
}

View file

@ -1,13 +1,15 @@
//! Take an encoded scene and create a graph to render it
use bytemuck::{Pod, Zeroable};
use crate::{
encoding::{Config, Encoding, Layout},
engine::{BufProxy, ImageFormat, ImageProxy, Recording, ResourceProxy},
shaders::{self, FullShaders, Shaders},
RenderParams, Scene,
};
use {
bytemuck::{Pod, Zeroable},
vello_encoding::{Config, Encoding, Layout},
};
/// State for a render in progress.
pub struct Render {
@ -213,11 +215,11 @@ impl Render {
params: &RenderParams,
robust: bool,
) -> Recording {
use crate::encoding::Resolver;
use vello_encoding::Resolver;
let mut recording = Recording::default();
let mut resolver = Resolver::new();
let mut packed = vec![];
let (layout, ramps, images) = resolver.resolve(encoding, &mut packed);
let (layout, ramps, images) = resolver.resolve(encoding, &mut packed, shaders::PATHTAG_REDUCE_WG);
let gradient_image = if ramps.height == 0 {
ResourceProxy::new_image(1, 1, ImageFormat::Rgba8)
} else {
@ -245,7 +247,7 @@ impl Render {
let new_height = next_multiple_of(params.height, 16);
let info_size = layout.bin_data_start;
let config = crate::encoding::Config {
let config = vello_encoding::Config {
width_in_tiles: new_width / 16,
height_in_tiles: new_height / 16,
target_width: params.width,

View file

@ -17,8 +17,7 @@
use fello::NormalizedCoord;
use peniko::kurbo::{Affine, Rect, Shape};
use peniko::{BlendMode, BrushRef, Color, Fill, Font, Image, Stroke, StyleRef};
use crate::encoding::{Encoding, Glyph, GlyphRun, Patch, Transform};
use vello_encoding::{Encoding, Glyph, GlyphRun, Patch, Transform};
/// Encoded definition of a scene and associated resources.
#[derive(Default)]