Skip to content

vello: Keep image atlas residency across renders#1558

Merged
waywardmonkeys merged 4 commits into
linebender:mainfrom
waywardmonkeys:vello-image-residency
Apr 28, 2026
Merged

vello: Keep image atlas residency across renders#1558
waywardmonkeys merged 4 commits into
linebender:mainfrom
waywardmonkeys:vello-image-residency

Conversation

@waywardmonkeys
Copy link
Copy Markdown
Collaborator

This changes Vello’s image atlas handling from per-render rebuilds to persistent residency.

Before this series, image atlas placement was recomputed on every resolve, and the renderer recreated and rewrote the atlas texture every render. That meant even steady-state scenes that only moved already-uploaded images still paid repeated atlas upload cost. This series keeps atlas residency metadata alive in vello_encoding, keeps the atlas texture proxy alive in vello, and only uploads images that are newly inserted or dirtied by atlas growth.

What changed:

  • vello_encoding now keeps the single-atlas allocator and resident image map across resolves.
  • Resident entries are reused by blob id instead of being repacked every render.
  • Eviction uses generation-based staleness under allocation pressure before growing the atlas.
  • Atlas growth still repacks, but marks residents dirty so only required re-uploads happen afterward.
  • The renderer now keeps the atlas texture resident across renders and only recreates it when the atlas size changes.
  • Atlas logging is quieter in the steady state, but still reports creation, resize, uploads, and eviction activity.
  • Added demo scenes that make residency visible, including a large-image case that roughly fills a 4096x4096 atlas with moving images.

Use this to see the trace log messages:

RUST_LOG=vello::render=debug cargo run -p with_winit -- --test-scenes

@waywardmonkeys
Copy link
Copy Markdown
Collaborator Author

As with everything, this was done with AI assistance, but I did review it and we iterated on it some.

@waywardmonkeys waywardmonkeys requested review from dfrg and raphlinus April 3, 2026 10:42
@waywardmonkeys
Copy link
Copy Markdown
Collaborator Author

This helps address the performance problem described in #1545.

@waywardmonkeys
Copy link
Copy Markdown
Collaborator Author

We probably need a way to mark images as dirty (mainly image_override ones) (or only them?)

Copy link
Copy Markdown
Contributor

@raphlinus raphlinus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked this over fairly carefully. Generally, it looks good, but I did have some comments; my biggest single concern is the potential panic in repack_to_size.

Just sketching, there's an alternative to the dirty bool in residents. Rather, you can have a resize_gen for the atlas, incremented on each resize. Instead of dirty, track the resize_gen for which the image was last uploaded. Then in the occupied case of get_or_insert, push & update resize_gen if resize_gen doesn't match. That avoids the full map iteration in restart_resolve_pass and eliminates the need for finish_resolve. I personally find this easier to reason about: the resize_gen in a resident identifies which gen it was uploaded to. But basically comes down to a style issue; I did verify the current logic and am satisfied.

Comment thread vello_encoding/src/image_cache.rs
Comment thread vello_encoding/src/image_cache.rs
Comment thread vello_encoding/src/image_cache.rs Outdated
for (id, mut resident) in entries {
let alloc = atlas
.allocate(size2(resident.image.width as _, resident.image.height as _))
.expect("resident image must fit after atlas growth");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little worried about panics here. Does guillotiere give guarantees that allocation will succeed if size is sufficient? It seems like fragmentation etc might cause a failure under reasonable circumstances.

Comment thread vello_encoding/src/image_cache.rs Outdated
Comment thread vello_encoding/src/resolve.rs Outdated
if self.image_cache.can_fit_image(&pending_image.image)
&& self.image_cache.evict_stale_entries()
{
continue 'outer;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think continue 'outer will work here, but isn't necessarily optimal; it should be possible to retry the get_or_insert and move on. But it makes the logic a bit messier, so not sure it's worth changing.

Comment thread vello_encoding/src/resolve.rs Outdated
Comment thread vello_encoding/src/image_cache.rs Outdated
Comment thread vello_encoding/src/image_cache.rs
Keep the single-atlas allocator and residency map alive in vello_encoding::ImageCache, reuse resident entries across resolves, and use generation-based stale eviction before atlas growth under allocation pressure.
@waywardmonkeys waywardmonkeys force-pushed the vello-image-residency branch from 5e1bc79 to 2ddbc34 Compare April 24, 2026 17:35
@waywardmonkeys
Copy link
Copy Markdown
Collaborator Author

@raphlinus I've updated this per your feedback, I think. Want to take a fresh look?

@raphlinus
Copy link
Copy Markdown
Contributor

Yup, looks like you addressed all my comments. Thanks!

@waywardmonkeys waywardmonkeys added this pull request to the merge queue Apr 28, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Apr 28, 2026
@waywardmonkeys waywardmonkeys added this pull request to the merge queue Apr 28, 2026
Merged via the queue into linebender:main with commit c55a2b5 Apr 28, 2026
17 checks passed
@waywardmonkeys waywardmonkeys deleted the vello-image-residency branch April 28, 2026 07:47
nicoburns pushed a commit that referenced this pull request May 10, 2026
Followup to #1558, which caches images. There's a risk that we'll render stale cached date from dynamic external textures, so we provide a method to mark those as dirty.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C-classic Applies to the classic `vello` crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants