The HTML standard states that: "the canvas element provides scripts with a resolution-dependent bitmap canvas, which can be used for rendering graphs, game graphics, art, or other visual images on the fly." Drawing on the canvas happen by way of a rendering context, which comes in various flavors, including 2d and WebGPU.
Vello is an experimental GPU compute-centric 2D renderer written in Rust.
Servo currently implements the canvas element, and supports various rendering contexts, including a 2d one, using a Rust library named Raquote, and a WebGPU context which uses our internal WebGPU capabilities. This report discusses the pros and cons of replacing Raquote with Vello for our 2d context implementation.
As described in a Servo issue, Raquote was meant as a temporary solution until another project, Pathfinder, could replace it. As it currently stands, both Raquote and Pathfinder do not see active development, hence Servo is currently relying on legacy projects. A solution would be to switch to a project with an active community of developers and a bright future ahead of itself.
Vello is actively developed. As an added bonus, Vello relies on WebGPU for it's actual GPU capabilities, making it a good potential fit for a web engine like Servo(which needs to implement WebGPU anyway).
For its WebGPU integration, Vello uses wgpu, which is also used by Servo, albeit at a different level: Servo relies on wgpu-core
inside components/webgpu
, our WebGPU "backend", whereas Vello uses the higher-level wgpu
, which corresponds to the DOM "front-end" that Servo implements in components/script
. Therefore, Vello does not do anything directly with the GPU, rather it acts more like a front-end library that uses WebGPU to build and submit a list of GPU commands using its own shaders. As a result, a Vello based canvas rendering context could run entirely inside components/script
and use the WebGPU constructs found there--this is already how servo's canvas WebGPU context works.
The pros and cons of using Vello can be summed up as:
Pros:
- Library under active development and with a vibrant community; involvement of that community in the Servo implementation.
- A simplification of Servo's architecture: the removal of the canvas rendering thread, replaced by renderer logic running in
components/script
(the canvas component remains necessary for the WebGL rendering backends).
Cons:
- Large amount of work.
- The state of Servo's current WebGPU capabilities is unclear(more work?).
This "large amount of work" would consist of two parts:
- Implement what Vello calls a
Renderer
using Servo's WebGPU DOM. This would come down to a straightforward translation of what Vello currently does withwgpu
. - Implement a canvas 2d rendering context using 1. This would come down to re-implementing what is currently done by the Raquote backend.
A user-agent like Servo does not have to support all rendering contexts: the getContext
method can return null for unsupported context types. Servo could therefore focus itself entirely on the WebGPU rendering context: it would be a rather thin wrapper around the existing WebGPU capabilities, which need to be supported anyway. Since Vello uses WebGPU, a canvas 2d rendering context could be implemented as a Wasm library(that would not be native to Servo) that would internally use Vello.