Repository navigation
anyrender_vello: allow windows to share one wgpu device and Vello renderer - #122
Meirdrarel wants to merge 2 commits into
Conversation
…derer Add `SharedVelloContext` and `VelloWindowRenderer::with_shared_context` so that several windows reuse the same wgpu instance, device and `vello::Renderer` instead of creating one each. `new()` / `with_options()` keep their behaviour (they use a private context). The new device is registered in the pool as soon as it is created rather than in `complete_resume`, so windows resumed before the first one completes (all startup windows) can find and reuse it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| /// and one Vello renderer per device (shaders, pipelines and Vello's internal buffers). | ||
| struct GpuState { | ||
| wgpu_context: WGPUContext, | ||
| renderers: Vec<(wgpu::Device, Rc<RefCell<VelloRenderer>>)>, |
There was a problem hiding this comment.
wgpu::Device implements Hash, so it could. I used a Vec because there's almost always one device (two on multi-GPU setups), where a linear scan is simpler and just as fast.
Happy to switch to FxHashMap if preferred.
| window_handle: Option<Arc<dyn WindowHandle>>, | ||
|
|
||
| wgpu_context: WGPUContext, | ||
| gpu: SharedVelloContext, |
There was a problem hiding this comment.
I dont think forcing user to always hold a shared context is a good idea.
There was a problem hiding this comment.
Callers don't need to hold one: new() and with_options() are unchanged and create a private context internally. Only code that wants sharing creates a SharedVelloContext.
Internally the renderer always goes through the Rc<RefCell<…>>, which costs a refcount and a borrow check per resume.
An owned/shared enum would avoid that, but it needs a match at every use site.
| self.window_handle = Some(window_handle.clone()); | ||
|
|
||
| let surface = self | ||
| let gpu = self.gpu.clone(); |
There was a problem hiding this comment.
Maybe consider a non-.clone() path here since cloning a Vec/HashMap is relatively expensive.
There was a problem hiding this comment.
SharedVelloContext is a newtype around an Rc, so this clones a pointer, not the Vec. The clone is moved into the async init so it can register the new device in the shared pool as soon as it exists.
…d_context Matches with_options (review suggestion).
|
Thanks for the review! #118 tackles the same thing for vello_hybrid. |
Fixes #121
Today every
VelloWindowRenderercreates its own wgpu instance, device andvello::Renderer, so eachextra window costs ~180 MB of GPU memory on macOS (4 windows: 802 MB). This PR adds an opt-in way to
share them.
Changes
SharedVelloContext(cheap to clone): oneWGPUContext+ onevello::Rendererper device.VelloWindowRenderer::with_options_and_shared_context(options, context).new()/with_options()are unchanged for callers: they create a private context.SurfaceRenderer(surface + intermediate texture), its scene and its custom-texture handles.complete_resume.Otherwise windows resumed before the first one completes (every startup window) can't reuse it.
Results
macOS, M2 Max, Retina windows, Blitz app with N windows (macOS physical footprint):
Tested with Blitz (
blitz-shell, severalViews):vello::Renderer(1600x1200, 1000x536,1800x1336 in the same run), visually checked;
cargo fmt,cargo clippy --workspace -- -D warnings,cargo docand the CI's wasm32 clippychecks (
--target wasm32-unknown-unknown) are clean locally. Not run in a browser; the code usesRc,which is fine with
spawn_local. Note that onwasm the device is only registered once its async init resolves, so windows created in the same tick
still get their own device there, as before.
Behaviour notes
vello::Rendererforthe device instead of building a new one. The device was already reused before, so this just
avoids recompiling pipelines.
features,limitsandpipeline_cacheare taken from the context / the first window). Per-window options like
base_colorandantialiasing_methodstill apply per window.Follow-up
anyrender_vello_hybridhas the same structure; I can do the same there if this approach is OK.