Awesome
A (thoroughly) parallelized experimental Rust vector-graphics renderer with both a software (CPU) and hardware (GPU) back-end having the following goals, in this order:
- Portability; supporting Fuchsia, Linux, macOS, Windows, Android & iOS.
- Performance; making use of compute-focused pipeline that is highly parallelized both at the instruction-level and the thread-level.
- Simplicity; implementing an easy-to-understand 4-stage pipeline.
- Size; minimizing the number of dependencies and focusing on vector-graphics only.
It relies on Rust's SIMD auto-vectorization/intrinsics and Rayon to have good performance on the CPU, while using WebGPU (wgpu) to take advantage of the GPU.
Getting started
Add the following to your Cargo.toml
dependencies:
forma = { version = "0.1.0", package = "forma-render" }
4-stage Pipeline
1. Curve flattening | 2. Line segment rasterization | 3. Sorting | 4. Painting |
---|---|---|---|
Bézier curves | line segments | pixel segments | sorted pixel segments, old tiles |
⬇️⬇️⬇️ | ⬇️⬇️⬇️ | ⬇️⬇️⬇️ | ⬇️⬇️⬇️ |
line segments | pixel segments | sorted pixel segments | freshly painted tiles |
Implementation Highlights ✨
Here are a few implementation highlights that make forma stand out from commonly used vector renderers.
<details> <summary>Curvature-aware flattening</summary>All higher cubic Béziers are approximated by quadratic ones, then, in parallel, flattened to line segments according to their curvature. This technique was developed by Raph Levien.
</details> <details> <summary>Cheap translations and rotations</summary>Translations and rotations can be rendered without having to re-flatten the curves, all the while maintaining full quality.
</details> <details> <summary>Parallel pixel grid intersection</summary>Line segments are transformed into pixel segments by intersecting them with the pixel grid. We developed a simple method that performs this computation in O(1) and which is run in parallel.
</details> <details> <summary>Efficient sorting</summary>We ported crumsort to Rust and parallelized it with Rayon, delivering improved performance over its pdqsort implementation for 64-bit random data. Scattering pixel segments with a sort was inspired from Allan MacKinnon's work on Spinel.
</details> <details> <summary>Update only the tiles that change (currently CPU-only)</summary>We implemented a fail-fast per-tile optimizer that tries to skip the painting step entirely. A similar approach could also be tested on the GPU.
</details>Animation as it appears on the screen | Updated tiles only |
---|---|
You can run the demo above with:
cargo run --release -p demo -- spaceship
Similar Projects
forma draws heavy inspiration from the following projects:
Example
You can use the included demo
example to render a few examples, one of which is a non-compliant & incomplete SVG renderer:
cargo run --release -p demo -- svg assets/svgs/paris-30k.svg
It renders enormous SVGs at interactive framerates, even on CPU: (compare to your web browser)
(Currently) Missing Pieces 🧩
Since this project is work-in-progress, breakage in the API, while not drastic, is expected. The performance on the GPU back-end is also expected to improve especially on mobile where performance is known to be poor and where the CPU back-end is currently advised instead.
Other than that:
- Automated layer ordering
- Strokes
- More color spaces for blends & gradients
- Faster GPU sorter
- Use of
f16
for great mobile GPU performance
Note
This is not an officially supported Google product.