Release (January 27, 2026): gogpu v0.12.0 + gg v0.21.0 — Enterprise architecture with
gpucontextintegration. Shared GPU interfaces enable database/sql-like dependency injection across the ecosystem.
The Problem: Circular Dependencies
As the GoGPU ecosystem grew to 300K lines of Pure Go, we hit a classic enterprise problem:
gogpu/gogpu (windowing, GPU init)
↓ depends on
gogpu/gg (2D graphics)
↓ depends on
gogpu/wgpu (WebGPU implementation)
↓ depends on
gogpu/naga (shader compiler)
The challenge: How can gg receive a GPU device from gogpu without creating circular dependencies? And how will gogpu/ui receive both GPU context AND input events?
The answer: Shared interfaces in a zero-dependency package.
Introducing gpucontext
gogpu/gpucontext is a new package with zero dependencies that defines shared GPU infrastructure:
// gpucontext v0.2.0 — Zero dependencies!
import "github.com/gogpu/gpucontext"
Core Interfaces
| Interface | Purpose | Implemented By |
|---|---|---|
DeviceProvider |
GPU device + queue access | gogpu.App |
EventSource |
Input events for UI | gogpu.App |
IMEController |
IME positioning for CJK input | gogpu.App (future) |
This follows the wgpu-types pattern from Rust — separating type definitions from implementation.
DeviceProvider: The database/sql Pattern
Just like Go's database/sql lets you swap MySQL for Postgres without changing your code, gpucontext.DeviceProvider lets libraries receive GPU resources without knowing the source:
// gpucontext/device_provider.go
type DeviceProvider interface {
Device() Device // Create GPU resources
Queue() Queue // Submit commands
SurfaceFormat() TextureFormat // Match surface format
Adapter() Adapter // GPU capabilities (optional)
}
gogpu Implements DeviceProvider
In gogpu v0.12.0, the App now provides GPU context to external libraries:
package main
import (
"github.com/gogpu/gogpu"
"github.com/gogpu/gpucontext"
)
func main() {
app := gogpu.NewApp(gogpu.DefaultConfig().
WithTitle("gpucontext Demo").
WithSize(800, 600))
app.OnDraw(func(dc *gogpu.Context) {
// Get DeviceProvider for external libraries
provider := app.GPUContextProvider()
// All non-nil — GPU is ready!
device := provider.Device() // gpucontext.Device
queue := provider.Queue() // gpucontext.Queue
adapter := provider.Adapter() // gpucontext.Adapter
format := provider.SurfaceFormat() // gpucontext.TextureFormat
// Pass to gg, ui, or any library that accepts DeviceProvider
})
app.Run()
}
Key insight: The library receiving DeviceProvider doesn't need to know it came from gogpu. It could come from born-ml/born for ML compute, or a future WebAssembly host.
EventSource: Input Events for UI
Building a GUI toolkit requires more than GPU access — you need input events. The EventSource interface provides platform-independent input delivery:
// gpucontext/events.go
type EventSource interface {
// Keyboard
OnKeyPress(func(key Key, mods Modifiers))
OnKeyRelease(func(key Key, mods Modifiers))
OnTextInput(func(text string))
// Mouse
OnMouseMove(func(x, y float64))
OnMousePress(func(button MouseButton, x, y float64))
OnMouseRelease(func(button MouseButton, x, y float64))
OnScroll(func(dx, dy float64))
// Window
OnResize(func(width, height int))
OnFocus(func(focused bool))
// IME (Chinese/Japanese/Korean input)
OnIMECompositionStart(fn func())
OnIMECompositionUpdate(fn func(state IMEState))
OnIMECompositionEnd(fn func(committed string))
}
Full IME Support for CJK Input
Enterprise applications must support international users. The IMEState struct provides everything needed for inline composition rendering:
type IMEState struct {
Composing bool // Currently composing?
CompositionText string // e.g., "nihon" → "日本"
CursorPos int // Cursor within composition
SelectionStart int // Selection range
SelectionEnd int
}
Using EventSource
app := gogpu.NewApp(gogpu.DefaultConfig())
// Get event source
events := app.EventSource()
// Register callbacks
events.OnKeyPress(func(key gpucontext.Key, mods gpucontext.Modifiers) {
if key == gpucontext.KeyEscape {
app.Quit()
}
})
events.OnMousePress(func(btn gpucontext.MouseButton, x, y float64) {
fmt.Printf("Click at (%.0f, %.0f)\n", x, y)
})
events.OnIMECompositionUpdate(func(state gpucontext.IMEState) {
// Render composition text inline
renderIMEPreview(state.CompositionText, state.CursorPos)
})
app.Run()
gg Enterprise Architecture
gg v0.21.0 introduces two new packages that leverage gpucontext:
core/ — CPU Rendering Primitives
Independent of GPU, contains pure algorithms:
gg/core/
├── fixed.go # Fixed-point math (FDot6, FDot16)
├── edge.go # Line/curve edges
├── edge_builder.go # Path → edges conversion
├── analytic_filler.go # Anti-aliased rendering
└── alpha_runs.go # RLE coverage storage
Key principle: CPU rendering code is separate from GPU code, following Skia/Vello architecture patterns.
render/ — GPU Integration Layer
Bridges gg to host applications via gpucontext:
// gg/render/device.go
type DeviceHandle = gpucontext.DeviceProvider
// gg/render/gpu_renderer.go
// gg receives device from host, doesn't create its own
func NewGPURenderer(handle DeviceHandle) (*GPURenderer, error) {
if handle == nil {
return nil, errors.New("render: nil device handle")
}
return &GPURenderer{
handle: handle,
softwareFallback: NewSoftwareRenderer(),
}, nil
}
Architecture:
User Application
│
┌──────────────┼──────────────┐
│ │ │
▼ ▼ ▼
gogpu.App gg.Context gg.Scene
(windowing) (immediate) (retained)
│ │ │
└──────────────┼──────────────┘
│
▼
gg/render package
┌──────────────┼──────────────┐
│ │ │
▼ ▼ ▼
DeviceHandle RenderTarget Renderer
(GPU access) (output) (execution)
│
▼
gg/core package
(CPU rasterization)
Building gogpu/ui: The Path Forward
With gpucontext providing GPU access AND input events, gogpu/ui can now be built as a pure consumer:
// Future gogpu/ui integration
package main
import (
"github.com/gogpu/gogpu"
"github.com/gogpu/ui"
)
func main() {
app := gogpu.NewApp(gogpu.DefaultConfig())
// ui receives BOTH GPU context AND events
uiRoot := ui.New(
app.GPUContextProvider(), // GPU for rendering
app.EventSource(), // Input for interaction
)
uiRoot.Add(
ui.Box(
ui.Text("Hello, GoGPU!").Font(ui.Title),
ui.Button("Click Me").OnClick(func() {
fmt.Println("Clicked!")
}),
).Padding(16).Gap(12),
)
app.OnDraw(func(dc *gogpu.Context) {
uiRoot.Render()
})
app.Run()
}
UI Architecture Goals
| Feature | Implementation |
|---|---|
| Signals-based reactivity | Fine-grained updates, O(affected) not O(n) |
| Tailwind-style API | Type-safe styling, AI-friendly |
| Enterprise features | Docking, virtualization, accessibility |
| Cross-platform | Desktop (gogpu), Web (WASM), Mobile (WebView) |
The Ecosystem Today
| Project | Version | LOC | Description |
|---|---|---|---|
| gogpu/gg | v0.21.0 | ~143K | 2D graphics + core/render packages |
| gogpu/wgpu | v0.10.2 | ~95K | Pure Go WebGPU |
| gogpu/naga | v0.8.4 | ~33K | Shader compiler |
| gogpu/gogpu | v0.12.0 | ~29K | GPU framework + gpucontext integration |
| gogpu/gpucontext | v0.2.0 | ~1K | Shared interfaces (zero deps) |
| gogpu/ui | — | — | GUI toolkit (in design) |
Total: ~300K lines of Pure Go. No CGO. No Rust required. Just go build.
Dependency Graph
┌─────────────────────────────────────────────────────────────┐
│ Your Application │
├─────────────────────────────────────────────────────────────┤
│ gogpu/ui (future) │ born-ml/born │ Your App │
├─────────────────────────────────────────────────────────────┤
│ gogpu/gg (2D Graphics) │
│ core/ (CPU) render/ (GPU integration) │
├─────────────────────────────────────────────────────────────┤
│ gogpu/gogpu (Graphics Framework) │
│ Windowing, Input, GPU Init, DeviceProvider │
├─────────────────────────────────────────────────────────────┤
│ gogpu/gpucontext (Shared Interfaces — ZERO DEPS) │
│ DeviceProvider, EventSource, IME, WebGPU types │
├─────────────────────────────────────────────────────────────┤
│ gogpu/wgpu (Pure Go WebGPU) │
├─────────────────────────────────────────────────────────────┤
│ Vulkan │ Metal │ DX12 │ GLES │
└─────────────────────────────────────────────────────────────┘
Try It
# Get the latest versions
go get github.com/gogpu/gogpu@v0.12.0
go get github.com/gogpu/gg@v0.21.0
go get github.com/gogpu/gpucontext@v0.2.0
Complete Example
package main
import (
"fmt"
"github.com/gogpu/gogpu"
"github.com/gogpu/gogpu/gmath"
"github.com/gogpu/gpucontext"
)
func main() {
app := gogpu.NewApp(gogpu.DefaultConfig().
WithTitle("gpucontext Integration Demo").
WithSize(800, 600))
// Setup event handling
events := app.EventSource()
events.OnKeyPress(func(key gpucontext.Key, mods gpucontext.Modifiers) {
fmt.Printf("Key: %d, Mods: %d\n", key, mods)
})
events.OnMousePress(func(btn gpucontext.MouseButton, x, y float64) {
fmt.Printf("Click at (%.0f, %.0f)\n", x, y)
})
app.OnDraw(func(dc *gogpu.Context) {
// Verify DeviceProvider
provider := app.GPUContextProvider()
if provider != nil && provider.Device() != nil {
// GPU ready — can pass to gg or other libraries
}
// Draw demo triangle (red) on CornflowerBlue background
dc.DrawTriangleColor(gmath.CornflowerBlue)
})
app.Run()
}
What's Next
Q1 2026: Stabilization
- Comprehensive benchmarks across all backends
- Memory optimization and GPU submission batching
- Documentation and tutorials
Q2 2026: gogpu/ui Foundation
- Widget system with signals-based reactivity
- Layout engine (flexbox-inspired)
- Theme system with accessibility support
Q3 2026: gogpu/ui Enterprise Features
- Docking and workspace management
- Virtualized lists for large datasets
- AccessKit integration for screen readers
Join the Discussion
We're making architectural decisions right now. Your input shapes the future of Go graphics:
- GitHub Discussions
- gogpu/ui Repository — Star and watch for updates
Links
- gogpu/gogpu: https://github.com/gogpu/gogpu/releases/tag/v0.12.0
- gogpu/gg: https://github.com/gogpu/gg/releases/tag/v0.21.0
- gogpu/gpucontext: https://github.com/gogpu/gpucontext
- Organization: https://github.com/gogpu
Enterprise-grade GPU integration. Pure Go. Zero CGO. Zero circular dependencies.
go get github.com/gogpu/gogpu@v0.12.0
Star the repos if you find them useful!
Part of the GoGPU Journey series:
- GoGPU: A Pure Go Graphics Library
- From Idea to 100K Lines in Two Weeks
- GPU Compute Shaders in Pure Go
- Enterprise GPU Backend v0.20.0
- Enterprise Architecture v0.21.0 ← You are here
Top comments (0)