Enkom-Tech/wello is Enkom’s maintained fork of linebender/vello. We merge upstream selectively, keep Enkom-specific changes here when needed, and target the WAPP viewer/browser stack with wgpu / naga 29.x (see WAPP-SDK). This is not a mirror of upstream. Upstream design discussion belongs on Linebender’s repo and Zulip; use this repo for fork-specific issues and PRs.
The published Rust crate name remains vello (workspace version 0.9.0). API-focused notes also live in vello/README.md.
| Area | Role |
|---|---|
vello, vello_encoding, vello_shaders |
Core GPU renderer and supporting crates |
examples/ |
with_winit, simple, headless, WASM helpers, shared scenes |
sparse_strips/ |
Experimental CPU / hybrid / sparse-strip pipelines (vello_cpu, vello_hybrid, …) |
glifo |
Glyph-related utilities used by the workspace |
vello_tests, xtask |
Tests and maintenance tooling |
Depend on the vello package from this repository. Cargo checks out the full workspace, so vello_encoding and vello_shaders resolve from the same revision—you do not need separate patches for those crate names.
[dependencies]
vello = { git = "https://github.com/Enkom-Tech/wello", package = "vello", rev = "<full-commit-sha>" }
# Or, for a moving target: branch = "main" (not recommended for releases)Pin rev to a commit SHA or use tag = "..." for reproducible builds. Align your own wgpu dependency with the version declared in this repo’s root Cargo.toml under [workspace.dependencies] (currently 29.0.3) so types match across your app and Vello.
Wello is a 2D graphics engine written in Rust, centered on GPU compute. It can draw large 2D scenes at interactive or near-interactive frame rates using wgpu. Behavior and goals follow upstream Vello; this fork adds the workspace above and Enkom integration work.
Quickstart to run an example program:
cargo run -p with_winitIt is used as the rendering backend for Xilem, a Rust GUI toolkit.
Warning
Like upstream Vello, Wello should be treated as alpha-quality for many production uses. Notable gaps include:
Significant changes are documented in the changelog.
Wello (like Vello) sits in the same part of the stack as renderers such as Skia, Cairo, and Piet: shapes, images, gradients, text, and similar features through a PostScript-style API familiar from SVG and the <canvas> 2D context.
The design favors GPU throughput: stages that are often CPU-bound or need extra textures in classic renderers are parallelized with prefix-style algorithms so more work stays on the GPU with fewer temporaries.
A capable GPU with compute shader support is required for the main (GPU) pipeline.
Wello is intended to sit deep in UI or document stacks. Building a Scene is straightforward; wiring wgpu (device, queue, targets) is the heavier part.
A minimal sketch of rendering to a texture:
use vello::kurbo::{Affine, Circle};
use vello::peniko::{Color, Fill};
use vello::peniko::color::palette;
use vello::wgpu::{
Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages,
TextureViewDescriptor,
};
use vello::{AaConfig, Renderer, RendererOptions, RenderParams, Scene};
// Obtain `device` and `queue` from your wgpu setup (adapter, instance, etc.)
let (width, height) = (800_u32, 600_u32);
let device: vello::wgpu::Device = todo!();
let queue: vello::wgpu::Queue = todo!();
let mut renderer = Renderer::new(&device, RendererOptions::default())
.expect("Failed to create renderer");
let mut scene = Scene::new();
scene.fill(
Fill::NonZero,
Affine::IDENTITY,
Color::from_rgb8(242, 140, 168),
None,
&Circle::new((420.0, 200.0), 120.0),
);
let size = Extent3d {
width,
height,
depth_or_array_layers: 1,
};
let target = device.create_texture(&TextureDescriptor {
label: Some("Vello render target"),
size,
mip_level_count: 1,
sample_count: 1,
dimension: TextureDimension::D2,
format: TextureFormat::Rgba8Unorm,
usage: TextureUsages::STORAGE_BINDING | TextureUsages::COPY_SRC,
view_formats: &[],
});
let target_view = target.create_view(&TextureViewDescriptor::default());
renderer
.render_to_texture(
&device,
&queue,
&scene,
&target_view,
&RenderParams {
base_color: palette::css::BLACK,
width,
height,
antialiasing_method: AaConfig::Msaa16,
},
)
.expect("Failed to render to a texture");
// Read back or sample `target` / `target_view` as needed (see `examples/headless`)Working examples live under examples/ (winit, simple surface setup, headless, WASM).
Upstream has reported on the order of 177 fps for the paris-30k test scene on an M1 Max at 1600×1600 as a favorable case. Treat that as indicative, not a guarantee on your hardware or this fork’s exact revision.
A separate Linebender integration for rendering SVG files is available through vello_svg.
A separate Linebender integration for playing Lottie animations is available through velato.
A separate Linebender integration for rendering raw scenes or Lottie and SVG files in Bevy through bevy_vello.
Examples are separate workspace packages under examples/ so they can carry their own dependencies. Run them with Cargo’s --package / -p flag.
The winit example (examples/with_winit) renders to a native window. By default it shows the GhostScript Tiger and any SVGs you drop in examples/assets/downloads.
A custom list of SVG file paths (and directories to render all SVG files from) can be provided as arguments instead.
It also includes a collection of test scenes showing the capabilities of vello, which can be shown with --test-scenes.
cargo run -p with_winitWe aim to target all environments which can support WebGPU with the default limits.
We defer to wgpu for this support.
Other platforms are more tricky, and may require special building/running procedures.
Because the GPU pipeline relies on compute shaders, the web path depends on WebGPU. Support in Chrome is the most mature; Firefox and Safari are still catching up, so you may need preview builds or flags.
The following command builds and runs a web version of the winit demo.
This uses cargo-run-wasm to build the example for web, and host a local server for it
# Make sure the Rust toolchain supports the wasm32 target
rustup target add wasm32-unknown-unknown
# The binary name must also be explicitly provided as it differs from the package name
cargo run_wasm -p with_winit --bin with_winit_binThere is also a web demo available here on supporting web browsers.
Warning
The web is not a primary target for upstream Vello; WebGPU implementations vary, so the WASM example may be fragile.
The with_winit example supports running on Android, using cargo apk.
cargo apk run -p with_winit --libTip
cargo apk doesn't support running in release mode without configuration.
See their crates page docs (around package.metadata.android.signing.<profile>).
See also cargo-apk#16.
To run in release mode, you must add the following to examples/with_winit/Cargo.toml (changing $HOME to your home directory):
[package.metadata.android.signing.release]
path = "$HOME/.android/debug.keystore"
keystore_password = "android"Note
As cargo apk does not allow passing command line arguments or environment variables to the app when ran, these can be embedded into the
program at compile time (currently for Android only)
with_winit currently supports the environment variables:
VELLO_STATIC_LOG, which is equivalent toRUST_LOGVELLO_STATIC_ARGS, which is equivalent to passing in command line arguments
For example (with unix shell environment variable syntax):
VELLO_STATIC_LOG="vello=trace" VELLO_STATIC_ARGS="--test-scenes" cargo apk run -p with_winit --libThis workspace is verified against Rust 1.88 and later (see rust-version in the root Cargo.toml and RUST_MIN_VER in .github/workflows/ci.yml).
Future toolchain bumps may land without a semver-major release, consistent with upstream policy.
If compilation fails on an older toolchain
A dependency may have raised its own MSRV. If you cannot upgrade Rust, try pinning that dependency:
cargo update -p package_name --precise 0.1.1Upstream Vello is discussed on Linebender Zulip in #vello (readable without an account).
For Wello-specific bugs, features, and PRs, use Enkom-Tech/wello on GitHub. The Rust code of conduct applies.
Unless you state otherwise, contributions you submit for inclusion are licensed as described under License.
Upstream Vello was previously piet-gpu, built on a custom HAL (piet-gpu-hal) rather than wgpu.
An archive of this version can be found in the branches custom-hal-archive-with-shaders and custom-hal-archive.
This succeeded the previous prototype, piet-metal, and included work adapted from piet-dx12.
The decision to lay down piet-gpu-hal in favor of WebGPU is discussed in detail in the blog post Requiem for piet-gpu-hal.
A vision document dated December 2020 explained the longer-term goals of the project, and how we might get there. Many of these items are out-of-date or completed, but it still may provide some useful background.
The Vello lineage draws on ideas from projects such as:
- Pathfinder
- Spinel
- Forma
- Massively Parallel Vector Graphics
- Random-access rendering of general vector graphics
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
In addition, all files in vello_shaders/shader and vello_shaders/src/cpu (and subdirectories) are alternatively licensed under the Unlicense (vello_shaders/shader/UNLICENSE or http://unlicense.org/). Those files are also available under the Apache-2.0/MIT dual license above.
Assets under examples/assets keep their own per-directory LICENSE files where present.
