Two months ago we released gogpu/ui v0.1.0 — 22 widgets, 3 design systems, ~150K lines of pure Go. Since then we shipped 21 patch releases, and the rendering pipeline is unrecognizable.
This post covers what changed and why it matters.
The Problem
v0.1.0 re-rendered the entire widget tree every frame. A 48×48 spinner in one corner caused the GPU to redraw 800×600 of static content. Hover over a button? Full tree walk. Open a dropdown? Full tree walk. This was fine for demos, not for production.
We studied how five frameworks solve this — Flutter, Chrome, Qt6, Android HWUI, Skia — and found the same architecture everywhere: Layer Tree + boundary isolation + damage tracking .
What We Built (v0.1.14 → v0.1.21)
Layer Tree Compositor
Every RepaintBoundary widget now owns a node in a persistent Layer Tree:
OffsetLayer (root) ├── PictureLayer (toolbar — clean, reuse texture) ├── PictureLayer (sidebar — clean, reuse texture) ├── ClipRectLayer (scrollview viewport) │ └── PictureLayer (content — dirty,…