From 30673d2c8855967ea69ae6d4254012afc9f12022 Mon Sep 17 00:00:00 2001 From: Olivier FAURE Date: Mon, 26 Feb 2024 19:04:36 +0100 Subject: [PATCH 1/7] Update documentation Update README.md Add ARCHITECTURE.md --- ARCHITECTURE.md | 82 +++++++++++++++++++++ README.md | 150 ++++++++++++++++++++++---------------- src/lib.rs | 78 +++++++++++++++++++- src/shaders/preprocess.rs | 3 + 4 files changed, 251 insertions(+), 62 deletions(-) create mode 100644 ARCHITECTURE.md diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 000000000..a80a9f067 --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,82 @@ + +# Architecture + +This document should be update semi-regularly. Feel free to open an issue if it hasn't been updated in a few years. + +## Goals + +The major goal of Vello is to provide a high quality GPU accelerated renderer suitable for a range of 2D graphics applications, including rendering for GUI applications, creative tools, and scientific visualization. +The [roadmap for 2023](doc/roadmap_2023.md) explains the goals and plans for the next few months of development + +Vello emerges from being a research project, which attempts to answer these hypotheses: + +- To what extent is a compute-centered approach better than rasterization ([Direct2D])? +- To what extent do "advanced" GPU features (subgroups, descriptor arrays, device-scoped barriers) help? +- Can we improve quality and extend the imaging model in useful ways? + +Another goal of the overall project is to explain how the renderer is built, and to advance the state of building applications on GPU compute shaders more generally. +Much of the progress on Vello is documented in blog entries. +See [doc/blogs.md](doc/blogs.md) for pointers to those. + + +## File structure + +The repository is structured as such: + +- `crates/` + - `encoding/` - Types that represent the data that needs to be rendered. + - `shaders/` - Infrastructure to compile pipelines and shaders; see "Shader templating". + - `tests/` - Helper code for writing tests; current has a single smoke test and not much else. +- `doc/` - Various documents detailing the vision for Vello as it was developed. This directory should probably be refactored away; adding to it not recommended. +- `examples/` - Example projects using Vello. Each example is its own crate, with its own dependencies. The simplest example is the `shapes` one. +- `integrations/vello_svg` - An SVG rendered based on vello and usvg. Used in examples. May be moved to `crates/` in the future. +- `shader/` - This is where the magic happens. WGSL shaders that define the compute operations (mostly variations of prefix scan) that vello does to render a scene. + - `shared/` - Shared types, functions and constants included in other shaders through non-standard `#import` preprocessor directives (see "Shader templating"). +- `src/` - Code for the main Vello crate. + - `shaders/` - Same as `crates/shaders/` above. The duplication should eventually be removed (see #467). + - `cpu_shader/` - Function that perform the same work as their equivalently-named WGSL shaders for the CPU fallbacks. The name is a bit loose, they're not "shaders" in any real sense. + + +## Shader templating + +We implement a limited, simple preprocessor for our shaders, as wgsl has insufficient code-sharing for our needs. + +This implements only classes of statements. + +1. `import`, which imports from `shader/shared` +2. `ifdef`, `ifndef`, `else` and `endif`, as standard. + These must be at the start of their lines. + Note that there is no support for creating definitions in-shader, these are only specified externally (in `src/shaders.rs`). + Note also that this definitions cannot currently be used in-code (`import`s may be used instead) + +This format is compatible with [`wgsl-analyzer`], which we recommend using. +If you run into any issues, please report them on Zulip ([#gpu > wgsl-analyzer issues](https://xi.zulipchat.com/#narrow/stream/197075-gpu/topic/wgsl-analyzer.20issues)), and/or on the [`wgsl-analyzer`] issue tracker. +Note that new imports must currently be added to `.vscode/settings.json` for this support to work correctly. +`wgsl-analyzer` only supports imports in very few syntactic locations, so we limit their use to these places. + + +## Intermediary layers + +There are multiple layers of separation between "draw shape in Scene" and "commands are sent to wgpu": + +- First, everything you do in `Scene` appends data to an `Encoding`. +The encoding owns multiple buffers representing compressed path commands, draw commands, transforms, etc. It's a linearized representation of the things you asked the `Scene` to draw. +- From that encoding, we generate a `Recording`, which is an array of commands; each `Command` represents an operation interacting with the GPU (think "upload buffer", "dispatch", "download buffer", etc). +- We then use `WgpuEngine` to send these commands to the actual GPU. + +In principle, other backends could consume a `Recording`, but for now the only implemented wgpu backend is `WgpuEngine`. + + +### CPU rendering + +The code in `cpu_shader/*.rs` and `cpu_dispatch.rs` provides *some* support for CPU-side rendering. It's in an awkward place right now: + +- It's called through WgpuEngine, so the dependency on wgpu is still there. +- Fine rasterization (the part at the end that puts pixels on screen) doesn't work in CPU yet (see #386). +- Every single wgsl shader needs a CPU equivalent, which is pretty cumbersome. + +Still, it's useful for testing and debugging. + + +[`wgsl-analyzer`]: https://marketplace.visualstudio.com/items?itemName=wgsl-analyzer.wgsl-analyzer +[direct2d]: https://docs.microsoft.com/en-us/windows/win32/direct2d/direct2d-portal diff --git a/README.md b/README.md index 04dcf00df..93d09090b 100644 --- a/README.md +++ b/README.md @@ -14,18 +14,95 @@ -Vello is a 2d graphics rendering engine, using [`wgpu`]. +Vello is an experimental 2d graphics rendering engine written in Rust, using [`wgpu`]. It efficiently draws large 2d scenes with interactive or near-interactive performance. - - -It is used as the rendering backend for [Xilem], a UI toolkit. - Quickstart to run an example program: ```shell cargo run -p with_winit ``` +![image](https://github.com/linebender/vello/assets/8573618/cc2b742e-2135-4b70-8051-c49aeddb5d19) + +It is used as the rendering backend for [Xilem], a native Rust GUI toolkit. + + +## Motivation + +Vello is meant to fill the same place in the graphics stack as other vector graphics renderers like [Skia](https://skia.org/), [Cairo](https://www.cairographics.org/), and its predecessor project [Piet](https://www.cairographics.org/). +On a basic level, that means it provides tools to render shapes, images, gradients, texts, etc, using a PostScript-inspired API, the same that powers SVG files and [the browser `` element](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D). + +Vello's selling point is that it gets better performance than other renderers by better leveraging the GPU. +In traditional PostScript renderers, some steps of the render process like sorting and clipping either need to be handled in the CPU or done through the use of intermediary textures. +Vello avoids this by using prefix-scan algorithms to parallelize work that usually needs to happen in sequence, so that work can be offloaded to the GPU with minimal use of temporary buffers. + + +## Getting started + +Vello is meant to be integrated deep in UI render stacks. +While drawing in a Vello scene is easy, actually rendering that scene to a surface setting up a wgpu context, which is a non-trivial task. + +To use Vello as the renderer for your PDF reader / GUI toolkit / etc, your code will have to look roughly like this: + +```rust +// Initialize wgpu and get handles +let device: wgpu::Device = ...; +let queue: wgpu::Queue = ...; +let render_surface: wpg::RenderSurface<'_> = ...; +let texture_format: wgpu::TextureFormat = ...; +let mut renderer = Renderer::new( + &device, + RendererOptions { + surface_format: Some(texture_format), + use_cpu: false, + antialiasing_support: vello::AaSupport::all(), + num_init_threads: NonZeroUsize::new(1), + }, +).expect("Failed to create renderer"); + +// Create scene and draw stuff in it +let mut scene = vello::Scene::new(); + +let circle = vello::Circle::new((420.0, 200.0), 120.0); +let circle_fill_color = vello::Color::rgb(0.9529, 0.5451, 0.6588); +scene.fill( + vello::peniko::Fill::NonZero, + vello::Affine::IDENTITY, + circle_fill_color, + None, + &circle, +); + +scene.push_layer(...); +scene.fill(...); +scene.stroke(...); +scene.pop_layer(...); + +// Render to your window/buffer/etc. +let surface_texture = render_state.surface.get_current_texture() + .expect("failed to get surface texture"); +vello::block_on_wgpu( + &device, + renderer + .render_to_surface_async( + &device, + &queue, + &scene, + &surface_texture, + &render_params, + ), +).expect("Failed to render to surface"); +surface_texture.present(); +``` + +See the [`examples/`](examples) folder to see how that code integrates with frameworks like winit and bevy. + + +## Performance + +Benchmarks are on their way. + + ## Integrations ### SVG @@ -49,7 +126,7 @@ Examples must be selected using the `--package` (or `-p`) Cargo flag. ### Winit Our [winit] example ([examples/with_winit](examples/with_winit)) demonstrates rendering to a [winit] window. -By default, this renders [GhostScript Tiger] all SVG files in [examples/assets/downloads](examples/assets/downloads) directory (using [`vello_svg`](#svg)). +By default, this renders the [GhostScript Tiger] as well as all SVG files you add in the [examples/assets/downloads/](examples/assets/downloads) directory using [`vello_svg`](#svg). 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`. @@ -99,7 +176,7 @@ rustup target add wasm32-unknown-unknown cargo run_wasm -p with_winit --bin with_winit_bin ``` -> [!WARNING] +> [!WARNING] > The web is not currently a primary target for Vello, and WebGPU implementations are incomplete, so you might run into issues running this example. ### Android @@ -125,52 +202,13 @@ keystore_password = "android" ## Community -[![Xi Zulip](https://img.shields.io/badge/Xi%20Zulip-%23gpu-blue?logo=Zulip)](https://xi.zulipchat.com/#narrow/stream/197075-gpu) - -Discussion of Vello development happens in the [Xi Zulip](https://xi.zulipchat.com/), specifically the [#gpu stream](https://xi.zulipchat.com/#narrow/stream/197075-gpu). All public content can be read without logging in - -## Shader templating - -We implement a limited, simple preprocessor for our shaders, as wgsl has insufficient code-sharing for our needs. - -This implements only classes of statements. - -1. `import`, which imports from `shader/shared` -2. `ifdef`, `ifndef`, `else` and `endif`, as standard. - These must be at the start of their lines. - Note that there is no support for creating definitions in-shader, these are only specified externally (in `src/shaders.rs`). - Note also that this definitions cannot currently be used in-code (`import`s may be used instead) - -This format is compatible with [`wgsl-analyzer`], which we recommend using. -If you run into any issues, please report them on Zulip ([#gpu > wgsl-analyzer issues](https://xi.zulipchat.com/#narrow/stream/197075-gpu/topic/wgsl-analyzer.20issues)), and/or on the [`wgsl-analyzer`] issue tracker. -Note that new imports must currently be added to `.vscode/settings.json` for this support to work correctly. -`wgsl-analyzer` only supports imports in very few syntactic locations, so we limit their use to these places. - -## GPU abstraction - -Our rendering code does not directly interact with `wgpu`. -Instead, we generate a `Recording`, a simple value type, then an `Engine` plays that recording to the actual GPU. -The only currently implemented `Engine` uses `wgpu`. +Discussion of Vello development happens in the [Xi Zulip](https://xi.zulipchat.com/), specifically the [#gpu stream](https://xi.zulipchat.com/#narrow/stream/197075-gpu). All public content can be read without logging in. -The idea is that this can abstract easily over multiple GPU back-ends, without either the render logic needing to be polymorphic or having dynamic dispatch at the GPU abstraction. -The goal is to be more agile. - -## Goals - -The major goal of Vello is to provide a high quality GPU accelerated renderer suitable for a range of 2D graphics applications, including rendering for GUI applications, creative tools, and scientific visualization. -The [roadmap for 2023](doc/roadmap_2023.md) explains the goals and plans for the next few months of development - -Vello emerges from being a research project, which attempts to answer these hypotheses: - -- To what extent is a compute-centered approach better than rasterization ([Direct2D])? - -- To what extent do "advanced" GPU features (subgroups, descriptor arrays, device-scoped barriers) help? - -- Can we improve quality and extend the imaging model in useful ways? +Contributions are welcome by pull request. The [Rust code of conduct] applies. -Another goal of the overall project is to explain how the renderer is built, and to advance the state of building applications on GPU compute shaders more generally. -Much of the progress on Vello is documented in blog entries. -See [doc/blogs.md](doc/blogs.md) for pointers to those. +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +licensed as above, without any additional terms or conditions. ## History @@ -215,16 +253,7 @@ The intent is for this research to be used in as broad a context as possible. The files in subdirectories of the [`examples/assets`](examples/assets) directory are licensed solely under their respective licenses, available in the `LICENSE` file in their directories. -## Contribution - -Contributions are welcome by pull request. The [Rust code of conduct] applies. - -Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in the work by you, as defined in the Apache-2.0 license, shall be -licensed as above, without any additional terms or conditions. - [piet-metal]: https://github.com/linebender/piet-metal -[direct2d]: https://docs.microsoft.com/en-us/windows/win32/direct2d/direct2d-portal [`wgpu`]: https://wgpu.rs/ [Xilem]: https://github.com/linebender/xilem/ [rust code of conduct]: https://www.rust-lang.org/policies/code-of-conduct @@ -234,5 +263,4 @@ licensed as above, without any additional terms or conditions. [GhostScript tiger]: https://commons.wikimedia.org/wiki/File:Ghostscript_Tiger.svg [winit]: https://github.com/rust-windowing/winit [Bevy]: https://bevyengine.org/ -[`wgsl-analyzer`]: https://marketplace.visualstudio.com/items?itemName=wgsl-analyzer.wgsl-analyzer [Requiem for piet-gpu-hal]: https://raphlinus.github.io/rust/gpu/2023/01/07/requiem-piet-gpu-hal.html diff --git a/src/lib.rs b/src/lib.rs index 42820bd01..7461094ff 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,82 @@ #![warn(clippy::doc_markdown, clippy::semicolon_if_nothing_returned)] +//! Vello is an experimental 2d graphics rendering engine written in Rust, using [`wgpu`]. +//! It efficiently draws large 2d scenes with interactive or near-interactive performance. +//! +//! ![image](https://github.com/linebender/vello/assets/8573618/cc2b742e-2135-4b70-8051-c49aeddb5d19) +//! +//! +//! ## Motivation +//! +//! Vello is meant to fill the same place in the graphics stack as other vector graphics renderers like [Skia](https://skia.org/), [Cairo](https://www.cairographics.org/), and its predecessor project [Piet](https://www.cairographics.org/). +//! On a basic level, that means it provides tools to render shapes, images, gradients, texts, etc, using a PostScript-inspired API, the same that powers SVG files and [the browser `` element](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D). +//! +//! Vello's selling point is that it gets better performance than other renderers by better leveraging the GPU. +//! In traditional PostScript renderers, some steps of the render process like sorting and clipping either need to be handled in the CPU or done through the use of intermediary textures. +//! Vello avoids this by using prefix-scan algorithms to parallelize work that usually needs to happen in sequence, so that work can be offloaded to the GPU with minimal use of temporary buffers. +//! +//! +//! ## Getting started +//! +//! Vello is meant to be integrated deep in UI render stacks. +//! While drawing in a Vello scene is easy, actually rendering that scene to a surface setting up a wgpu context, which is a non-trivial task. +//! +//! To use Vello as the renderer for your PDF reader / GUI toolkit / etc, your code will have to look roughly like this: +//! +//! ```rust +//! // Initialize wgpu and get handles +//! let device: wgpu::Device = ...; +//! let queue: wgpu::Queue = ...; +//! let render_surface: wpg::RenderSurface<'_> = ...; +//! let texture_format: wgpu::TextureFormat = ...; +//! let mut renderer = Renderer::new( +//! &device, +//! RendererOptions { +//! surface_format: Some(texture_format), +//! use_cpu: false, +//! antialiasing_support: vello::AaSupport::all(), +//! num_init_threads: NonZeroUsize::new(1), +//! }, +//! ).expect("Failed to create renderer"); +//! +//! // Create scene and draw stuff in it +//! let mut scene = vello::Scene::new(); +//! +//! let circle = vello::Circle::new((420.0, 200.0), 120.0); +//! let circle_fill_color = vello::Color::rgb(0.9529, 0.5451, 0.6588); +//! scene.fill( +//! vello::peniko::Fill::NonZero, +//! vello::Affine::IDENTITY, +//! circle_fill_color, +//! None, +//! &circle, +//! ); +//! +//! scene.push_layer(...); +//! scene.fill(...); +//! scene.stroke(...); +//! scene.pop_layer(...); +//! +//! // Render to your window/buffer/etc. +//! let surface_texture = render_state.surface.get_current_texture() +//! .expect("failed to get surface texture"); +//! vello::block_on_wgpu( +//! &device, +//! renderer +//! .render_to_surface_async( +//! &device, +//! &queue, +//! &scene, +//! &surface_texture, +//! &render_params, +//! ), +//! ).expect("Failed to render to surface"); +//! surface_texture.present(); +//! ``` +//! +//! See the [`examples/`](https://github.com/linebender/vello/tree/main/examples) folder to see how that code integrates with frameworks like winit and bevy. + mod cpu_dispatch; mod cpu_shader; mod recording; @@ -133,7 +209,7 @@ pub struct RendererOptions { /// How many threads to use for initialisation of shaders. /// /// Use `Some(1)` to use a single thread. This is recommended when on macOS - /// (see https://github.com/bevyengine/bevy/pull/10812#discussion_r1496138004) + /// (see ) /// /// Set to `None` to use a heuristic which will use many but not all threads /// diff --git a/src/shaders/preprocess.rs b/src/shaders/preprocess.rs index a5c41dbc5..142161668 100644 --- a/src/shaders/preprocess.rs +++ b/src/shaders/preprocess.rs @@ -1,6 +1,9 @@ // Copyright 2022 the Vello Authors // SPDX-License-Identifier: Apache-2.0 OR MIT +// TODO (#467) - Remove this file and use vello_shaders crate instead, +// then update ARCHITECTURE.md. + use std::{ collections::{HashMap, HashSet}, fs, From da454dd01e975892e392d76e5abf13e5ad2ee31b Mon Sep 17 00:00:00 2001 From: Olivier FAURE Date: Mon, 26 Feb 2024 19:33:48 +0100 Subject: [PATCH 2/7] Add more documentation --- README.md | 4 +++- src/cpu_dispatch.rs | 3 +++ src/scene.rs | 24 ++++++++++++++++++++---- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 93d09090b..83feabc9d 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,9 @@ See the [`examples/`](examples) folder to see how that code integrates with fram ## Performance -Benchmarks are on their way. +We've observed 177 fps for the paris-30k test scene on an M1 Max, at a resolution of 1600 pixels square, which is excellent performance and represents something of a best case for the engine. + +More formal benchmarks are on their way. ## Integrations diff --git a/src/cpu_dispatch.rs b/src/cpu_dispatch.rs index 901f5c127..b0f48df4e 100644 --- a/src/cpu_dispatch.rs +++ b/src/cpu_dispatch.rs @@ -2,6 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 OR MIT //! Support for CPU implementations of compute shaders. +//! +//! Note that while this CPU implementation is useful for testing and debugging, +//! a full CPU fallback for targets without wgpu hasn't been implemented yet. use std::{ cell::{Ref, RefCell, RefMut}, diff --git a/src/scene.rs b/src/scene.rs index 136dc8b2c..dedfb3686 100644 --- a/src/scene.rs +++ b/src/scene.rs @@ -6,7 +6,14 @@ use peniko::{BlendMode, BrushRef, Color, Fill, Font, Image, StyleRef}; use skrifa::instance::NormalizedCoord; use vello_encoding::{Encoding, Glyph, GlyphRun, Patch, Transform}; -/// Encoded definition of a scene and associated resources. +// TODO - Document invariants and edge cases (#470) +// - What happens when we pass a transform matrix with NaN values to the Scene? +// - What happens if a push_layer isn't matched by a pop_layer? + +/// The main datatype for rendering graphics. +/// +/// A Scene stores a sequence of drawing commands, their context, and the +/// associated resources, which can later be rendered. #[derive(Clone, Default)] pub struct Scene { encoding: Encoding, @@ -18,6 +25,7 @@ impl Scene { Self::default() } + // TODO - Rename to "clear()" (see #469) /// Removes all content from the scene. pub fn reset(&mut self) { self.encoding.reset(); @@ -28,14 +36,19 @@ impl Scene { &self.encoding } - /// Pushes a new layer bound by the specified shape and composed with + /// Pushes a new layer clipped by the specified shape and composed with /// previous layers using the specified blend mode. + /// + /// Every drawing command after this call will be clipped by the shape + /// until the layer is popped. + /// + /// **However, the transforms are *not* saved or modified by the layer stack.** pub fn push_layer( &mut self, blend: impl Into, alpha: f32, transform: Affine, - shape: &impl Shape, + clip: &impl Shape, ) { let blend = blend.into(); self.encoding @@ -161,7 +174,10 @@ impl Scene { DrawGlyphs::new(&mut self.encoding, font) } - /// Appends a fragment to the scene. + /// Appends a child scene. + /// + /// The given transform is applied to every transform in the child. + /// This is an O(N) operation. pub fn append(&mut self, other: &Scene, transform: Option) { self.encoding.append( &other.encoding, From da350910e2839225cef7312269a1d7cddc5ffe88 Mon Sep 17 00:00:00 2001 From: Olivier FAURE Date: Thu, 29 Feb 2024 16:15:48 +0100 Subject: [PATCH 3/7] Fix doc problems --- .clippy.toml | 2 +- ARCHITECTURE.md | 35 ++++++++++++++++++++++++----------- README.md | 36 +++++++++++++++++++++--------------- src/lib.rs | 14 ++++++-------- src/scene.rs | 2 +- 5 files changed, 53 insertions(+), 36 deletions(-) diff --git a/.clippy.toml b/.clippy.toml index 198f214bf..0a8bf380e 100644 --- a/.clippy.toml +++ b/.clippy.toml @@ -1 +1 @@ -doc-valid-idents = ["WebGPU", ".."] +doc-valid-idents = ["WebGPU", "PostScript", ".."] diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index a80a9f067..388a725ea 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -1,12 +1,11 @@ # Architecture -This document should be update semi-regularly. Feel free to open an issue if it hasn't been updated in a few years. +This document should be updated semi-regularly. Feel free to open an issue if it hasn't been updated in more than a year. ## Goals The major goal of Vello is to provide a high quality GPU accelerated renderer suitable for a range of 2D graphics applications, including rendering for GUI applications, creative tools, and scientific visualization. -The [roadmap for 2023](doc/roadmap_2023.md) explains the goals and plans for the next few months of development Vello emerges from being a research project, which attempts to answer these hypotheses: @@ -14,34 +13,43 @@ Vello emerges from being a research project, which attempts to answer these hypo - To what extent do "advanced" GPU features (subgroups, descriptor arrays, device-scoped barriers) help? - Can we improve quality and extend the imaging model in useful ways? -Another goal of the overall project is to explain how the renderer is built, and to advance the state of building applications on GPU compute shaders more generally. +Another goal of the overall project is to explain how the renderer is built, and to advance the state of building applications on GPU compute shaders more generally. Much of the progress on Vello is documented in blog entries. See [doc/blogs.md](doc/blogs.md) for pointers to those. +## Roadmap + +The [roadmap for 2023](doc/roadmap_2023.md) is still largely applicable. +The "Semi-stable encoding format" section and most of the "CPU fallback" section can be considered implemented. + +Our current priority is to fill in missing features and to fix rendering artifacts, so that Vello can reach feature parity with other 2D graphics engines. + + ## File structure The repository is structured as such: - `crates/` - `encoding/` - Types that represent the data that needs to be rendered. - - `shaders/` - Infrastructure to compile pipelines and shaders; see "Shader templating". + - `shaders/` - Infrastructure to compile pipelines and shaders; see "Shader templating". Note that the `vello` crate doesn't currently import this crate (see #467). - `tests/` - Helper code for writing tests; current has a single smoke test and not much else. - `doc/` - Various documents detailing the vision for Vello as it was developed. This directory should probably be refactored away; adding to it not recommended. - `examples/` - Example projects using Vello. Each example is its own crate, with its own dependencies. The simplest example is the `shapes` one. -- `integrations/vello_svg` - An SVG rendered based on vello and usvg. Used in examples. May be moved to `crates/` in the future. -- `shader/` - This is where the magic happens. WGSL shaders that define the compute operations (mostly variations of prefix scan) that vello does to render a scene. +- `integrations/vello_svg` - An SVG rendered based on Vello and usvg. Used in examples. May be moved to `crates/` in the future. +- `shader/` - This is where the magic happens. WGSL shaders that define the compute operations (often variations of prefix sum) that Vello does to render a scene. - `shared/` - Shared types, functions and constants included in other shaders through non-standard `#import` preprocessor directives (see "Shader templating"). -- `src/` - Code for the main Vello crate. +- `src/` - Code for the main `vello` crate. - `shaders/` - Same as `crates/shaders/` above. The duplication should eventually be removed (see #467). - - `cpu_shader/` - Function that perform the same work as their equivalently-named WGSL shaders for the CPU fallbacks. The name is a bit loose, they're not "shaders" in any real sense. + - `cpu_shader/` - Functions that perform the same work as their equivalently-named WGSL shaders for the CPU fallbacks. The name is a bit loose; they're "shaders" in the sense that they work on resource bindings with the exact same layout as actual GPU shaders. ## Shader templating -We implement a limited, simple preprocessor for our shaders, as wgsl has insufficient code-sharing for our needs. +WGSL has no meta-programming support, which limits code-sharing. +We use a strategy common to many projects (eg Bevy) which is to implement a limited, simple preprocessor for our shaders. -This implements only classes of statements. +This preprocessor implements the following directives: 1. `import`, which imports from `shader/shared` 2. `ifdef`, `ifndef`, `else` and `endif`, as standard. @@ -55,6 +63,11 @@ Note that new imports must currently be added to `.vscode/settings.json` for thi `wgsl-analyzer` only supports imports in very few syntactic locations, so we limit their use to these places. +## Path encoding + +See [Path segment encoding](./doc/pathseg.md) document. + + ## Intermediary layers There are multiple layers of separation between "draw shape in Scene" and "commands are sent to wgpu": @@ -73,7 +86,7 @@ The code in `cpu_shader/*.rs` and `cpu_dispatch.rs` provides *some* support for - It's called through WgpuEngine, so the dependency on wgpu is still there. - Fine rasterization (the part at the end that puts pixels on screen) doesn't work in CPU yet (see #386). -- Every single wgsl shader needs a CPU equivalent, which is pretty cumbersome. +- Every single WGSL shader needs a CPU equivalent, which is pretty cumbersome. Still, it's useful for testing and debugging. diff --git a/README.md b/README.md index 83feabc9d..237c8280b 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,8 @@ -Vello is an experimental 2d graphics rendering engine written in Rust, using [`wgpu`]. -It efficiently draws large 2d scenes with interactive or near-interactive performance. +Vello is an experimental 2D graphics rendering engine written in Rust, with a focus on GPU compute. +It can draw large 2D scenes with interactive or near-interactive performance, using [`wgpu`] for GPU access. Quickstart to run an example program: ```shell @@ -24,23 +24,31 @@ cargo run -p with_winit ![image](https://github.com/linebender/vello/assets/8573618/cc2b742e-2135-4b70-8051-c49aeddb5d19) -It is used as the rendering backend for [Xilem], a native Rust GUI toolkit. +It is used as the rendering backend for [Xilem], a Rust GUI toolkit. +> [!WARNING] +> Vello can currently be considered in an alpha state. In particular, we're still working on the following: +> +> - [Major rendering artifacts when drawing more than 64k objects](https://github.com/linebender/vello/issues/334). +> - [Implementing blur and filter effects](https://github.com/linebender/vello/issues/476). +> - [Properly implenting strokes](https://github.com/linebender/vello/issues/303) and [supporting all SVG stroke caps](https://github.com/linebender/vello/issues/280). +> - [Conflations artifacts](https://github.com/linebender/vello/issues/49). +> - [GPU memory allocation strategy](https://github.com/linebender/vello/issues/366) ## Motivation -Vello is meant to fill the same place in the graphics stack as other vector graphics renderers like [Skia](https://skia.org/), [Cairo](https://www.cairographics.org/), and its predecessor project [Piet](https://www.cairographics.org/). -On a basic level, that means it provides tools to render shapes, images, gradients, texts, etc, using a PostScript-inspired API, the same that powers SVG files and [the browser `` element](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D). +Vello is meant to fill the same place in the graphics stack as other vector graphics renderers like [Skia](https://skia.org/), [Cairo](https://www.cairographics.org/), and its predecessor project [Piet](https://github.com/linebender/piet). +On a basic level, that means it provides tools to render shapes, images, gradients, text, etc, using a PostScript-inspired API, the same that powers SVG files and [the browser `` element](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D). Vello's selling point is that it gets better performance than other renderers by better leveraging the GPU. In traditional PostScript renderers, some steps of the render process like sorting and clipping either need to be handled in the CPU or done through the use of intermediary textures. -Vello avoids this by using prefix-scan algorithms to parallelize work that usually needs to happen in sequence, so that work can be offloaded to the GPU with minimal use of temporary buffers. +Vello avoids this by using prefix-sum algorithms to parallelize work that usually needs to happen in sequence, so that work can be offloaded to the GPU with minimal use of temporary buffers. ## Getting started Vello is meant to be integrated deep in UI render stacks. -While drawing in a Vello scene is easy, actually rendering that scene to a surface setting up a wgpu context, which is a non-trivial task. +While drawing in a Vello scene is easy, actually rendering that scene to a surface requires setting up a wgpu context, which is a non-trivial task. To use Vello as the renderer for your PDF reader / GUI toolkit / etc, your code will have to look roughly like this: @@ -48,7 +56,7 @@ To use Vello as the renderer for your PDF reader / GUI toolkit / etc, your code // Initialize wgpu and get handles let device: wgpu::Device = ...; let queue: wgpu::Queue = ...; -let render_surface: wpg::RenderSurface<'_> = ...; +let surface: wpgu::Surface<'_> = ...; let texture_format: wgpu::TextureFormat = ...; let mut renderer = Renderer::new( &device, @@ -62,24 +70,22 @@ let mut renderer = Renderer::new( // Create scene and draw stuff in it let mut scene = vello::Scene::new(); - -let circle = vello::Circle::new((420.0, 200.0), 120.0); -let circle_fill_color = vello::Color::rgb(0.9529, 0.5451, 0.6588); scene.fill( vello::peniko::Fill::NonZero, vello::Affine::IDENTITY, - circle_fill_color, + vello::Color::rgb8(242, 140, 168), None, - &circle, + &vello::Circle::new((420.0, 200.0), 120.0), ); +// Draw more stuff scene.push_layer(...); scene.fill(...); scene.stroke(...); scene.pop_layer(...); // Render to your window/buffer/etc. -let surface_texture = render_state.surface.get_current_texture() +let surface_texture = surface.get_current_texture() .expect("failed to get surface texture"); vello::block_on_wgpu( &device, @@ -210,7 +216,7 @@ Contributions are welcome by pull request. The [Rust code of conduct] applies. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be -licensed as above, without any additional terms or conditions. +licensed as noted in the "License" section, without any additional terms or conditions. ## History diff --git a/src/lib.rs b/src/lib.rs index 7461094ff..2ac7764c0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,11 +26,11 @@ //! //! To use Vello as the renderer for your PDF reader / GUI toolkit / etc, your code will have to look roughly like this: //! -//! ```rust +//! ```ignore //! // Initialize wgpu and get handles //! let device: wgpu::Device = ...; //! let queue: wgpu::Queue = ...; -//! let render_surface: wpg::RenderSurface<'_> = ...; +//! let surface: wpgu::Surface<'_> = ...; //! let texture_format: wgpu::TextureFormat = ...; //! let mut renderer = Renderer::new( //! &device, @@ -44,24 +44,22 @@ //! //! // Create scene and draw stuff in it //! let mut scene = vello::Scene::new(); -//! -//! let circle = vello::Circle::new((420.0, 200.0), 120.0); -//! let circle_fill_color = vello::Color::rgb(0.9529, 0.5451, 0.6588); //! scene.fill( //! vello::peniko::Fill::NonZero, //! vello::Affine::IDENTITY, -//! circle_fill_color, +//! vello::Color::rgb8(242, 140, 168), //! None, -//! &circle, +//! &vello::Circle::new((420.0, 200.0), 120.0), //! ); //! +//! // Draw more stuff //! scene.push_layer(...); //! scene.fill(...); //! scene.stroke(...); //! scene.pop_layer(...); //! //! // Render to your window/buffer/etc. -//! let surface_texture = render_state.surface.get_current_texture() +//! let surface_texture = surface.get_current_texture() //! .expect("failed to get surface texture"); //! vello::block_on_wgpu( //! &device, diff --git a/src/scene.rs b/src/scene.rs index dedfb3686..d99b9df47 100644 --- a/src/scene.rs +++ b/src/scene.rs @@ -54,7 +54,7 @@ impl Scene { self.encoding .encode_transform(Transform::from_kurbo(&transform)); self.encoding.encode_fill_style(Fill::NonZero); - if !self.encoding.encode_shape(shape, true) { + if !self.encoding.encode_shape(clip, true) { // If the layer shape is invalid, encode a valid empty path. This suppresses // all drawing until the layer is popped. self.encoding From 85a09dac572a52eaee60f95f2facbf4205e8071b Mon Sep 17 00:00:00 2001 From: Olivier FAURE Date: Thu, 29 Feb 2024 18:02:39 +0100 Subject: [PATCH 4/7] Add "clear" doc alias to "reset" method --- crates/encoding/src/encoding.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/encoding/src/encoding.rs b/crates/encoding/src/encoding.rs index 0ac663b9a..5bf7e7e69 100644 --- a/crates/encoding/src/encoding.rs +++ b/crates/encoding/src/encoding.rs @@ -69,6 +69,9 @@ impl Encoding { self.path_tags.is_empty() } + #[doc(alias = "clear")] + // This is not called "clear" because "clear" has other implications + // in graphics contexts. /// Clears the encoding. pub fn reset(&mut self) { self.transforms.clear(); @@ -472,6 +475,9 @@ pub struct Resources { #[cfg(feature = "full")] impl Resources { + #[doc(alias = "clear")] + // This is not called "clear" because "clear" has other implications + // in graphics contexts. fn reset(&mut self) { self.patches.clear(); self.color_stops.clear(); From 170ecbc0b28f61e24f9e1596918266953d34a8bc Mon Sep 17 00:00:00 2001 From: Olivier FAURE Date: Thu, 29 Feb 2024 19:52:42 +0100 Subject: [PATCH 5/7] Documentation fixes --- ARCHITECTURE.md | 8 ++++---- README.md | 22 +++++++++++----------- src/lib.rs | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 388a725ea..df0fece14 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -10,7 +10,7 @@ The major goal of Vello is to provide a high quality GPU accelerated renderer su Vello emerges from being a research project, which attempts to answer these hypotheses: - To what extent is a compute-centered approach better than rasterization ([Direct2D])? -- To what extent do "advanced" GPU features (subgroups, descriptor arrays, device-scoped barriers) help? +- To what extent do advanced GPU features (subgroups, descriptor arrays, device-scoped barriers) help? - Can we improve quality and extend the imaging model in useful ways? Another goal of the overall project is to explain how the renderer is built, and to advance the state of building applications on GPU compute shaders more generally. @@ -32,7 +32,7 @@ The repository is structured as such: - `crates/` - `encoding/` - Types that represent the data that needs to be rendered. - - `shaders/` - Infrastructure to compile pipelines and shaders; see "Shader templating". Note that the `vello` crate doesn't currently import this crate (see #467). + - `shaders/` - Infrastructure to compile pipelines and shaders; see "Shader templating". Note that the `vello` crate doesn't currently import this crate (see issue #467). - `tests/` - Helper code for writing tests; current has a single smoke test and not much else. - `doc/` - Various documents detailing the vision for Vello as it was developed. This directory should probably be refactored away; adding to it not recommended. - `examples/` - Example projects using Vello. Each example is its own crate, with its own dependencies. The simplest example is the `shapes` one. @@ -40,7 +40,7 @@ The repository is structured as such: - `shader/` - This is where the magic happens. WGSL shaders that define the compute operations (often variations of prefix sum) that Vello does to render a scene. - `shared/` - Shared types, functions and constants included in other shaders through non-standard `#import` preprocessor directives (see "Shader templating"). - `src/` - Code for the main `vello` crate. - - `shaders/` - Same as `crates/shaders/` above. The duplication should eventually be removed (see #467). + - `shaders/` - Same as `crates/shaders/` above. The duplication should eventually be removed (see issue #467). - `cpu_shader/` - Functions that perform the same work as their equivalently-named WGSL shaders for the CPU fallbacks. The name is a bit loose; they're "shaders" in the sense that they work on resource bindings with the exact same layout as actual GPU shaders. @@ -85,7 +85,7 @@ In principle, other backends could consume a `Recording`, but for now the only i The code in `cpu_shader/*.rs` and `cpu_dispatch.rs` provides *some* support for CPU-side rendering. It's in an awkward place right now: - It's called through WgpuEngine, so the dependency on wgpu is still there. -- Fine rasterization (the part at the end that puts pixels on screen) doesn't work in CPU yet (see #386). +- Fine rasterization (the part at the end that puts pixels on screen) doesn't work in CPU yet (see issue #386). - Every single WGSL shader needs a CPU equivalent, which is pretty cumbersome. Still, it's useful for testing and debugging. diff --git a/README.md b/README.md index 237c8280b..7b83975ee 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ It is used as the rendering backend for [Xilem], a Rust GUI toolkit. > > - [Major rendering artifacts when drawing more than 64k objects](https://github.com/linebender/vello/issues/334). > - [Implementing blur and filter effects](https://github.com/linebender/vello/issues/476). -> - [Properly implenting strokes](https://github.com/linebender/vello/issues/303) and [supporting all SVG stroke caps](https://github.com/linebender/vello/issues/280). +> - [Properly implementing strokes](https://github.com/linebender/vello/issues/303) and [supporting all SVG stroke caps](https://github.com/linebender/vello/issues/280). > - [Conflations artifacts](https://github.com/linebender/vello/issues/49). > - [GPU memory allocation strategy](https://github.com/linebender/vello/issues/366) @@ -56,7 +56,7 @@ To use Vello as the renderer for your PDF reader / GUI toolkit / etc, your code // Initialize wgpu and get handles let device: wgpu::Device = ...; let queue: wgpu::Queue = ...; -let surface: wpgu::Surface<'_> = ...; +let surface: wgpu::Surface<'_> = ...; let texture_format: wgpu::TextureFormat = ...; let mut renderer = Renderer::new( &device, @@ -101,7 +101,7 @@ vello::block_on_wgpu( surface_texture.present(); ``` -See the [`examples/`](examples) folder to see how that code integrates with frameworks like winit and bevy. +See the [`examples/`](https://github.com/linebender/vello/tree/main/examples) folder to see how that code integrates with frameworks like winit and bevy. ## Performance @@ -127,14 +127,14 @@ A separate integration for playing Lottie animations is available through the [` ## Examples -Our examples are provided in separate packages in the [`examples`](examples) folder. +Our examples are provided in separate packages in the [`examples`](https://github.com/linebender/vello/tree/main/examples) folder. This allows them to have independent dependencies and faster builds. Examples must be selected using the `--package` (or `-p`) Cargo flag. ### Winit -Our [winit] example ([examples/with_winit](examples/with_winit)) demonstrates rendering to a [winit] window. -By default, this renders the [GhostScript Tiger] as well as all SVG files you add in the [examples/assets/downloads/](examples/assets/downloads) directory using [`vello_svg`](#svg). +Our [winit] example ([examples/with_winit](https://github.com/linebender/vello/tree/main/examples/with_winit)) demonstrates rendering to a [winit] window. +By default, this renders the [GhostScript Tiger] as well as all SVG files you add in the [examples/assets/downloads/](https://github.com/linebender/vello/tree/main/examples/assets/downloads) directory using [`vello_svg`](#svg). 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`. @@ -153,7 +153,7 @@ cargo run -p with_winit -- download ### Bevy -The [Bevy] example ([examples/with_bevy](examples/with_bevy)) demonstrates using Vello within a [Bevy] application. +The [Bevy] example ([examples/with_bevy](https://github.com/linebender/vello/tree/main/examples/with_bevy)) demonstrates using Vello within a [Bevy] application. This currently draws to a [`wgpu`] `Texture` using `vello`, then uses that texture as the faces of a cube. ```shell @@ -228,7 +228,7 @@ This succeeded the previous prototype, [piet-metal], and included work adapted f 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](doc/vision.md) document dated December 2020 explained the longer-term goals of the project, and how we might get there. +A [vision](https://github.com/linebender/vello/tree/main/doc/vision.md) 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. ## Related projects @@ -252,13 +252,13 @@ Licensed under either of at your option. -In addition, all files in the [`shader`](shader) and [`src/cpu_shader`](src/cpu_shader) +In addition, all files in the [`shader`](https://github.com/linebender/vello/tree/main/shader) and [`src/cpu_shader`](https://github.com/linebender/vello/tree/main/src/cpu_shader) directories and subdirectories thereof are alternatively licensed under -the Unlicense ([shader/UNLICENSE](shader/UNLICENSE) or ). +the Unlicense ([shader/UNLICENSE](https://github.com/linebender/vello/tree/main/shader/UNLICENSE) or ). For clarity, these files are also licensed under either of the above licenses. The intent is for this research to be used in as broad a context as possible. -The files in subdirectories of the [`examples/assets`](examples/assets) directory are licensed solely under +The files in subdirectories of the [`examples/assets`](https://github.com/linebender/vello/tree/main/examples/assets) directory are licensed solely under their respective licenses, available in the `LICENSE` file in their directories. [piet-metal]: https://github.com/linebender/piet-metal diff --git a/src/lib.rs b/src/lib.rs index 2ac7764c0..644beae3c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,7 +30,7 @@ //! // Initialize wgpu and get handles //! let device: wgpu::Device = ...; //! let queue: wgpu::Queue = ...; -//! let surface: wpgu::Surface<'_> = ...; +//! let surface: wgpu::Surface<'_> = ...; //! let texture_format: wgpu::TextureFormat = ...; //! let mut renderer = Renderer::new( //! &device, From 3a3d69f7ac12b22346aad75d0ce07ee505d1bc0e Mon Sep 17 00:00:00 2001 From: Olivier FAURE Date: Sat, 2 Mar 2024 17:52:25 +0100 Subject: [PATCH 6/7] Add final touches to documentation --- ARCHITECTURE.md | 11 ++++++++--- README.md | 43 +++++++++++++++++++++++++------------------ src/lib.rs | 42 ++++++++++++++++++++++++------------------ 3 files changed, 57 insertions(+), 39 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index df0fece14..4d28da71c 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -17,6 +17,8 @@ Another goal of the overall project is to explain how the renderer is built, and Much of the progress on Vello is documented in blog entries. See [doc/blogs.md](doc/blogs.md) for pointers to those. +Ideally, we'd like our documentation to be more structured; we may refactor it in the future (see [#488]). + ## Roadmap @@ -32,7 +34,7 @@ The repository is structured as such: - `crates/` - `encoding/` - Types that represent the data that needs to be rendered. - - `shaders/` - Infrastructure to compile pipelines and shaders; see "Shader templating". Note that the `vello` crate doesn't currently import this crate (see issue #467). + - `shaders/` - Infrastructure to preprocess and cross-compile shaders at compile time; see "Shader templating". Note that the `vello` crate doesn't currently import this crate (see [#467]). - `tests/` - Helper code for writing tests; current has a single smoke test and not much else. - `doc/` - Various documents detailing the vision for Vello as it was developed. This directory should probably be refactored away; adding to it not recommended. - `examples/` - Example projects using Vello. Each example is its own crate, with its own dependencies. The simplest example is the `shapes` one. @@ -40,7 +42,7 @@ The repository is structured as such: - `shader/` - This is where the magic happens. WGSL shaders that define the compute operations (often variations of prefix sum) that Vello does to render a scene. - `shared/` - Shared types, functions and constants included in other shaders through non-standard `#import` preprocessor directives (see "Shader templating"). - `src/` - Code for the main `vello` crate. - - `shaders/` - Same as `crates/shaders/` above. The duplication should eventually be removed (see issue #467). + - `shaders/` - Same as `crates/shaders/` above. The duplication should eventually be removed (see [#467]). - `cpu_shader/` - Functions that perform the same work as their equivalently-named WGSL shaders for the CPU fallbacks. The name is a bit loose; they're "shaders" in the sense that they work on resource bindings with the exact same layout as actual GPU shaders. @@ -85,7 +87,7 @@ In principle, other backends could consume a `Recording`, but for now the only i The code in `cpu_shader/*.rs` and `cpu_dispatch.rs` provides *some* support for CPU-side rendering. It's in an awkward place right now: - It's called through WgpuEngine, so the dependency on wgpu is still there. -- Fine rasterization (the part at the end that puts pixels on screen) doesn't work in CPU yet (see issue #386). +- Fine rasterization (the part at the end that puts pixels on screen) doesn't work in CPU yet (see [#386]). - Every single WGSL shader needs a CPU equivalent, which is pretty cumbersome. Still, it's useful for testing and debugging. @@ -93,3 +95,6 @@ Still, it's useful for testing and debugging. [`wgsl-analyzer`]: https://marketplace.visualstudio.com/items?itemName=wgsl-analyzer.wgsl-analyzer [direct2d]: https://docs.microsoft.com/en-us/windows/win32/direct2d/direct2d-portal +[#488]: https://github.com/linebender/vello/issues/488 +[#467]: https://github.com/linebender/vello/issues/467 +[#386]: https://github.com/linebender/vello/issues/386 diff --git a/README.md b/README.md index 7b83975ee..a9baa4b8d 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ It is used as the rendering backend for [Xilem], a Rust GUI toolkit. > - [Properly implementing strokes](https://github.com/linebender/vello/issues/303) and [supporting all SVG stroke caps](https://github.com/linebender/vello/issues/280). > - [Conflations artifacts](https://github.com/linebender/vello/issues/49). > - [GPU memory allocation strategy](https://github.com/linebender/vello/issues/366) +> - [Glyph caching](https://github.com/linebender/vello/issues/204) ## Motivation @@ -41,9 +42,11 @@ Vello is meant to fill the same place in the graphics stack as other vector grap On a basic level, that means it provides tools to render shapes, images, gradients, text, etc, using a PostScript-inspired API, the same that powers SVG files and [the browser `` element](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D). Vello's selling point is that it gets better performance than other renderers by better leveraging the GPU. -In traditional PostScript renderers, some steps of the render process like sorting and clipping either need to be handled in the CPU or done through the use of intermediary textures. +In traditional PostScript-style renderers, some steps of the render process like sorting and clipping either need to be handled in the CPU or done through the use of intermediary textures. Vello avoids this by using prefix-sum algorithms to parallelize work that usually needs to happen in sequence, so that work can be offloaded to the GPU with minimal use of temporary buffers. +This means that Vello needs a GPU with support for compute shaders to run. + ## Getting started @@ -54,18 +57,19 @@ To use Vello as the renderer for your PDF reader / GUI toolkit / etc, your code ```rust // Initialize wgpu and get handles +let (width, height) = ...; let device: wgpu::Device = ...; let queue: wgpu::Queue = ...; let surface: wgpu::Surface<'_> = ...; let texture_format: wgpu::TextureFormat = ...; let mut renderer = Renderer::new( - &device, - RendererOptions { - surface_format: Some(texture_format), - use_cpu: false, - antialiasing_support: vello::AaSupport::all(), - num_init_threads: NonZeroUsize::new(1), - }, + &device, + RendererOptions { + surface_format: Some(texture_format), + use_cpu: false, + antialiasing_support: vello::AaSupport::all(), + num_init_threads: NonZeroUsize::new(1), + }, ).expect("Failed to create renderer"); // Create scene and draw stuff in it @@ -87,17 +91,20 @@ scene.pop_layer(...); // Render to your window/buffer/etc. let surface_texture = surface.get_current_texture() .expect("failed to get surface texture"); -vello::block_on_wgpu( +renderer + .render_to_surface( &device, - renderer - .render_to_surface_async( - &device, - &queue, - &scene, - &surface_texture, - &render_params, - ), -).expect("Failed to render to surface"); + &queue, + &scene, + &surface_texture, + &vello::RenderParams { + base_color: Color::BLACK, // Background color + width, + height, + antialiasing_method: AaConfig::Msaa16, + }, + ) + .expect("Failed to render to surface"); surface_texture.present(); ``` diff --git a/src/lib.rs b/src/lib.rs index 644beae3c..f96d75d71 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,9 +15,11 @@ //! On a basic level, that means it provides tools to render shapes, images, gradients, texts, etc, using a PostScript-inspired API, the same that powers SVG files and [the browser `` element](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D). //! //! Vello's selling point is that it gets better performance than other renderers by better leveraging the GPU. -//! In traditional PostScript renderers, some steps of the render process like sorting and clipping either need to be handled in the CPU or done through the use of intermediary textures. +//! In traditional PostScript-style renderers, some steps of the render process like sorting and clipping either need to be handled in the CPU or done through the use of intermediary textures. //! Vello avoids this by using prefix-scan algorithms to parallelize work that usually needs to happen in sequence, so that work can be offloaded to the GPU with minimal use of temporary buffers. //! +//! This means that Vello needs a GPU with support for compute shaders to run. +//! //! //! ## Getting started //! @@ -28,18 +30,19 @@ //! //! ```ignore //! // Initialize wgpu and get handles +//! let (width, height) = ...; //! let device: wgpu::Device = ...; //! let queue: wgpu::Queue = ...; //! let surface: wgpu::Surface<'_> = ...; //! let texture_format: wgpu::TextureFormat = ...; //! let mut renderer = Renderer::new( -//! &device, -//! RendererOptions { -//! surface_format: Some(texture_format), -//! use_cpu: false, -//! antialiasing_support: vello::AaSupport::all(), -//! num_init_threads: NonZeroUsize::new(1), -//! }, +//! &device, +//! RendererOptions { +//! surface_format: Some(texture_format), +//! use_cpu: false, +//! antialiasing_support: vello::AaSupport::all(), +//! num_init_threads: NonZeroUsize::new(1), +//! }, //! ).expect("Failed to create renderer"); //! //! // Create scene and draw stuff in it @@ -61,17 +64,20 @@ //! // Render to your window/buffer/etc. //! let surface_texture = surface.get_current_texture() //! .expect("failed to get surface texture"); -//! vello::block_on_wgpu( +//! renderer +//! .render_to_surface( //! &device, -//! renderer -//! .render_to_surface_async( -//! &device, -//! &queue, -//! &scene, -//! &surface_texture, -//! &render_params, -//! ), -//! ).expect("Failed to render to surface"); +//! &queue, +//! &scene, +//! &surface_texture, +//! &vello::RenderParams { +//! base_color: Color::BLACK, // Background color +//! width, +//! height, +//! antialiasing_method: AaConfig::Msaa16, +//! }, +//! ) +//! .expect("Failed to render to surface"); //! surface_texture.present(); //! ``` //! From 83f06c6000eaf1fe19687947748354def9f834ba Mon Sep 17 00:00:00 2001 From: Kaur Kuut Date: Sat, 2 Mar 2024 19:43:18 +0200 Subject: [PATCH 7/7] Remove stale TODO. --- src/scene.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/scene.rs b/src/scene.rs index d99b9df47..6fffd358d 100644 --- a/src/scene.rs +++ b/src/scene.rs @@ -25,7 +25,6 @@ impl Scene { Self::default() } - // TODO - Rename to "clear()" (see #469) /// Removes all content from the scene. pub fn reset(&mut self) { self.encoding.reset();