Render icons as cached triangle meshes instead of rasterized textures#864
Open
nat3Github wants to merge 2 commits into
Open
Render icons as cached triangle meshes instead of rasterized textures#864nat3Github wants to merge 2 commits into
nat3Github wants to merge 2 commits into
Conversation
Replace the icon rendering path. Previously each icon was rasterized by svg2tvg's z2d backend into a CPU pixel buffer, uploaded as a GPU Texture, cached, and drawn with renderTexture. Now icons are tessellated once into a triangle mesh (svg2tvg_dvui.MeshBuilder), cached per Window keyed by (bytes, height, IconRenderOptions), and replayed each frame by duping the mesh into the frame arena, scaling/translating/rotating to the target rect, applying colormod, and submitting via renderTriangles. The result is resolution-independent and avoids per-icon texture uploads. IconRenderOptions maps onto svg2tvg's extended RenderOptions: fill_color/stroke_color/stroke_width become the *_override fields, and a fully transparent fill_color sets disable_fill. The public icon API (icon, buttonIcon, iconWidth, renderIcon, IconRenderOptions, IconWidget) is unchanged.
Owner
|
Interesting! I took a quick look at the code, haven't done any testing. Why does svg2tvg need a dvui import now? Makes sense locally for testing, but I don't get why the svg2tvg thing that dvui imports needs a dvui import? |
Collaborator
Author
|
good point, yes it's only for testing (the demo) behind a lazy gate (-Ddemo=true), not needed for the lib. i'm not sure but i think zon still fetches them currently but does not use them? i don't know if there is a cleaner way to do that without having it out of tree (maybe out of tree is cleaner with local path zon dep)? i'll be back on sunday/monday, will try that. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Note of Caution, most of this PR was vibecoded with Claude
Previously each icon was rasterized by svg2tvg's z2d backend into a CPU pixel buffer, uploaded to the GPU as a Texture, cached, and drawn with renderTexture.
This PR Replaces dvui's icon rendering path, tessellating once into a triangle mesh, cached, and replayed every frame as geometry, recached on size change. no textures, no CPU rasterization.
the triangulization happens in a branch of tvg2svg. Users who want rasterization can still use svg2tvg (which still has the rasterization code using z2d)
https://github.com/nat3Github/zig-lib-svg2tvg/tree/dvui-render, there is a option gated dvui demo in that branch
Performance:
CPU rasterization is slow compared to calculating triangles, and rendering triangles on modern gpus is cheap. in my measurements ive seen ~10x speed up (widget, did not measure gpu). when the pixel buffer is cached its faster than the mesh lookup but mesh lookup is still fast in absolute numbers and first paint reduces dramatrically which is the better behavior for immediate mode in my opinion. it should be fast enough to redraw every frame (if someone wants to do crazy animation on tvgs)
What changed
cache miss via appendTvg, anchored at (0,0). Each frame the cached mesh is
duped into the frame arena, scaled/translated to the target rect, rotated
(opts.rotation), tinted (opts.colormod), and submitted via renderTriangles.
The z2d raster path for icons is gone.
IconRenderOptions)) + icon_mesh_frame. Stale entries (untouched last frame)
evicted in begin(); meshes freed on deinit().
useTvg-guarded).
module, since it imports dvui and can't be shared across module graphs.
RenderOptions with fill_color_override / stroke_color_override /
stroke_width_override / disable_fill. IconRenderOptions maps 1:1 onto these.
Public icon API should be unchanged — icon, buttonIcon, iconWidth, renderIcon,
IconRenderOptions, IconWidget all keep their signatures.