vello_common: Generalize the command recorder abstraction and add more metadata#1746
Conversation
e868164 to
ba64412
Compare
86cb568 to
d10a407
Compare
0cf5501 to
2ee9cff
Compare
d10a407 to
3f61c40
Compare
2ee9cff to
36e4384
Compare
grebmeg
left a comment
There was a problem hiding this comment.
LGTM! I especially like the Node abstraction — it makes draw and layer ordering much clearer.
| /// Tile-aligned dimensions of the root scene. | ||
| pub scene_size: SizeU16, | ||
| /// The nodes of the root layer. | ||
| pub nodes: Vec<Node>, |
There was a problem hiding this comment.
Have you considered representing the root as a separate layer containing its own nodes? That would make the recording a more uniform tree-like structure, with the root as the tree root and all other layers as children. It might simplify traversal and remove some root-specific handling, although the root’s distinct rendering semantics may outweigh that benefit.
There was a problem hiding this comment.
Yeah, in Vello Hybrid, the root requires some specific handling (because of blending). In my rewrite branch, the special casing hasn't really been a problem, so I think it's better to keep it!
| pub root_cmds: Vec<RecordedCmd>, | ||
| /// Recorder for a scene description. | ||
| #[derive(Debug)] | ||
| pub struct CommandRecorder<D> { |
There was a problem hiding this comment.
Would SceneRecorder be a more accurate name now? CommandRecorder suggests a flat command stream, but this type records a structured scene containing root nodes, nested layers, draws, bounds, and rendering metadata. The existing doc comment already describes it as a "recorder for a scene description".
There was a problem hiding this comment.
Yes, as mentioned, I think we could even just name it SceneGraph! However, I don't want to load this PR more than necessary. I will add a TODO!
| self.bucket_commands( | ||
| &layer.nodes, | ||
| draws, | ||
| layers, | ||
| strips, | ||
| encoded_paints, | ||
| filter_ctx, | ||
| ); |
There was a problem hiding this comment.
Should we be concerned about the recursion here? Could deeply nested regular layers overflow the stack, and can we avoid that with an iterative work stack?
There was a problem hiding this comment.
I suppose for adverserial scenarios. But I don't think this is urgent, let me add a TODO! You'd probably have to go hundreds (or at least multiple dozens) of layers deep to trigger this. But good catch!
…shift_part3 # Conflicts: # sparse_strips/vello_common/src/clip.rs # sparse_strips/vello_common/src/geometry.rs # sparse_strips/vello_common/src/record.rs # sparse_strips/vello_common/src/strip.rs # sparse_strips/vello_common/src/transforms.rs # sparse_strips/vello_common/src/util.rs # sparse_strips/vello_common/src/viewport.rs # sparse_strips/vello_cpu/src/coarse/bucketer.rs # sparse_strips/vello_cpu/src/dispatch/multi_threaded.rs # sparse_strips/vello_cpu/src/dispatch/single_threaded.rs # sparse_strips/vello_cpu/src/render.rs # sparse_strips/vello_hybrid/src/scene.rs
…ebender#1744) This is the first PR in a series of three (perhaps four) PRs that serve as a preparation for the Vello Hybrid rewrite. This PR is easiest reviewed commit by commit, though there isn't that much to review in the first place. Apart from adjusting a few descriptions, it's mostly just moving some code around. The first 7 commits were done by manually copy-pasting code into the right location. The last commit that fixes compiler issues were done with AI assistance. ### PR train 1. linebender#1744 — Move some code from `vello_cpu` to `vello_common` 👈 2. linebender#1745 — Add more new/refactored code into `vello_common` 3. linebender#1746 — Generalize the command recorder abstraction and add more metadata 4. linebender#1751 — Introduce `Padding` and streamline clip handling
…bender#1745) This PR is based on linebender#1744 and introduces some actual changes, once again in preparation for the Vello Hybrid rewrite. The first commit adds some utility types like `Offset` and `Size`, which will layer on be used by Vello Hybrid (they are currently partially duplicated there, but I will just remove them later on). In theory they could just live in Vello Hybrid, but since we already have `RectU16` in vello_common I figured this is the best place. The second commit resolved a TODO and creates a new generic method that allows generating fill/alpha-fill sequences from a slice of strips. We also use this for the existing `strip_bbox` function now. I'm aware that this will result in a slight slowdown since we will do the clipping even though it isn't necessary to clip anything since we are just calculating the bbox, but I think it's better to accept this cost for less code duplication. The third commit extracts all of the transforms we currently have into a custom struct, so that, once again, they can more easily be used by Vello Hybrid. Fourth commit introduces a new `ViewportState` abstraction, that abstracts all of the complexity of handling different viewport so that Vello Hybrid can use this as well. Fifth commit adds a way of querying whether an encoded paint has any opacities directly. ### PR train 1. linebender#1744 — Move some code from `vello_cpu` to `vello_common` 2. linebender#1745 — Add more new/refactored code into `vello_common` 👈 3. linebender#1746 — Generalize the command recorder abstraction and add more metadata 4. linebender#1751 — Introduce `Padding` and streamline clip handling
This PR is based on #1745. It changes the semantics of the command recorder, turning it into something more akin to a scene graph (we should probably rename it in the future!).
Up until now, the command recorder was written in a way that is only "useful" to Vello CPU. Most notably, normal layers would be folded into their parent stream, and only filter layers had an explicit representation as an independent unit. For Vello Hybrid, this is not a suitable representation, because all layers need to be represented explicitly and be rendered independently from the other layers.
To achieve this goal, this PR implements some changes, split up into two commits.
The first commit represents a refactor of the overall representation. Most notably:
Vec<Node>, which is likely to be very small, I decided to remove theVecPoolfor this. I don't think it's worth it trying to reuse those across frames.The second commit ensures that we store some more metadata about the scene, which is needed for Vello Hybrid. Yes, we do pay some additional cost for Vello CPU here, but it's basically nothing.
PR train
vello_cputovello_common#1744 — Move some code fromvello_cputovello_commonvello_common#1745 — Add more new/refactored code intovello_commonPaddingtype and streamline clip handling #1751 — IntroducePaddingand streamline clip handling