Use RenderContext to own resource lifecycle outside of scene rendering#45
Use RenderContext to own resource lifecycle outside of scene rendering#45taj-p wants to merge 6 commits intoDioxusLabs:mainfrom
RenderContext to own resource lifecycle outside of scene rendering#45Conversation
RenderContext to own resource lifecycle outside of scenesRenderContext to own resource lifecycle outside of scene rendering
nicoburns
left a comment
There was a problem hiding this comment.
This is not a fully comphrensive review, but I've left some thoughts
| self.next_resource_id += 1; | ||
|
|
||
| let image_source = ImageSource::from_peniko_image_data(&image); | ||
| self.resource_map.insert(resource_id, image_source); |
There was a problem hiding this comment.
I think this ought to check whether the image is already registered (using the ImageData's id as a key). And avoid re-registering it in that case. That would save (each time an image is re-rendered):
- An expensive premultiply and reallocate for Vello CPU
- Texture upload for Vello Hybrid
- Conversion to SkImage for Skia
There was a problem hiding this comment.
That would save (each time an image is re-rendered):
This part isn't quite true. This would only occur if a caller re-registers the same image duplicately - not for every render. The caller shouldn't be calling these duplicately (and to do so might imply incorrect usage).
Happy to add in a defensive layer. From my perspective of using AnyRender for testing/benchmarking, it doesn't impact my usage.
| fn render<F: FnOnce(&mut Self::ScenePainter<'_>)>( | ||
| &mut self, | ||
| ctx: &mut Self::Context, |
There was a problem hiding this comment.
Would it make sense to have the WindowRenderer/ImageRenderer own the impl RenderContext rather than passing it in here? Then (with the current design), it wouldn't need to be in the API of these traits at all.
There was a problem hiding this comment.
Then (with the current design), it wouldn't need to be in the API of these traits at all.
Having said that, I wonder whether the "draw callback" (FnOnce(&mut Self::ScenePainter<'_>)) ought to be bounded by PaintScene + RenderContext rather than just PaintScene. Then it would be on callers to register resources rather than something handled internally by the ScenePainters...
But maybe that doesn't make sense if you then need a type that impl's PaintScene + RenderContext anyway?
Refactors
RenderContextfrom being owned by renderer internals into a standalone, consumer-owned object passed by reference. This makes resource (image) lifetime management explicit and removes the burden of managing resource maps and ID counters from consumers.Previously, Vello Hybrid would leak images. This changes enables consumers for explicitly managing image resource lifecycle.
Design Decisions
Deferred vs Eager Image Upload
There is a tension with the initial implementation and the introduction of
RenderContext. Theanyrender_svgcrate was uploading images to the GPU as soon as it encountered an image node. It is likely preferential to bulk/batch upload images to the GPU rather than creating a per-image command encoder.For now, we've stuck with the eager strategy, but I imagine there's an opportunity here to iterate the design to support deferred upload. I think this is a step in the right direction, regardless.
It should be noted that the current design supports both eager and deferred upload. To defer upload, simply
register_imagein Vello Hybrid prior to rendering some scene.