https://github.com/gogpu/gogpu
Pure Go Graphics Framework — GPU power, Go simplicity
https://github.com/gogpu/gogpu
game-development go golang gpu graphics pure-go rendering webgpu zero-cgo
Last synced: about 2 months ago
JSON representation
Pure Go Graphics Framework — GPU power, Go simplicity
- Host: GitHub
- URL: https://github.com/gogpu/gogpu
- Owner: gogpu
- License: mit
- Created: 2025-12-05T15:24:57.000Z (5 months ago)
- Default Branch: main
- Last Pushed: 2026-03-07T05:47:27.000Z (about 2 months ago)
- Last Synced: 2026-03-07T13:39:52.255Z (about 2 months ago)
- Topics: game-development, go, golang, gpu, graphics, pure-go, rendering, webgpu, zero-cgo
- Language: Go
- Size: 14.4 MB
- Stars: 178
- Watchers: 4
- Forks: 2
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Codeowners: .github/CODEOWNERS
- Security: SECURITY.md
- Roadmap: ROADMAP.md
Awesome Lists containing this project
- awesome-go - gogpu - GPU application framework with windowing, input, and rendering built on WebGPU — reduces 480+ lines of GPU code to ~20, zero CGO (GoGPU ecosystem: [gg](https://github.com/gogpu/gg), [ui](https://github.com/gogpu/ui), [wgpu](https://github.com/gogpu/wgpu), [naga](https://github.com/gogpu/naga)). (Game Development / Search and Analytic Databases)
- fucking-awesome-go - gogpu - GPU application framework with windowing, input, and rendering built on WebGPU — reduces 480+ lines of GPU code to ~20, zero CGO (GoGPU ecosystem: <b><code> 83⭐</code></b> <b><code> 2🍴</code></b> [gg](https://github.com/gogpu/gg)), <b><code> 70⭐</code></b> <b><code> 1🍴</code></b> [ui](https://github.com/gogpu/ui)), <b><code> 74⭐</code></b> <b><code> 6🍴</code></b> [wgpu](https://github.com/gogpu/wgpu)), <b><code> 29⭐</code></b> <b><code> 4🍴</code></b> [naga](https://github.com/gogpu/naga))). (Game Development / Search and Analytic Databases)
- awesome-go-with-stars - gogpu - 03-16 | (Game Development / Search and Analytic Databases)
README
GoGPU
Pure Go GPU Computing Ecosystem
GPU power, Go simplicity. Zero CGO.
---
## Overview
**GoGPU** is a GPU computing framework for Go that provides a high-level API for graphics and compute operations. It supports dual backends: a high-performance Rust backend (wgpu-native) and a pure Go backend for zero-dependency builds.
### Key Features
| Category | Capabilities |
|----------|--------------|
| **Backends** | Rust (wgpu-native) or Pure Go (gogpu/wgpu) |
| **Graphics API** | Runtime selection: Vulkan, DX12, Metal, GLES, Software |
| **Platforms** | Windows (Vulkan/DX12/GLES), Linux X11/Wayland (Vulkan/GLES), macOS (Metal) |
| **Rendering** | Event-driven three-state model (idle/animating/continuous), zero-copy surface rendering |
| **Graphics** | Windowing, input handling, texture loading |
| **Compute** | Full compute shader support |
| **Integration** | DeviceProvider, HalProvider, WindowProvider, PlatformProvider, SurfaceView |
| **Logging** | Structured logging via `log/slog`, silent by default |
| **Build** | Zero CGO with Pure Go backend |
---
## Installation
```bash
go get github.com/gogpu/gogpu
```
**Requirements:**
- Go 1.25+
- `CGO_ENABLED=0` (Pure Go FFI requires CGO disabled)
**Zero dependencies — just works:**
```bash
CGO_ENABLED=0 go run .
```
> **Note:** On macOS and some Linux distros, CGO is enabled by default. Always set `CGO_ENABLED=0` when building GoGPU projects.
---
## Quick Start
```go
package main
import (
"github.com/gogpu/gogpu"
"github.com/gogpu/gogpu/gmath"
)
func main() {
app := gogpu.NewApp(gogpu.DefaultConfig().
WithTitle("Hello GoGPU").
WithSize(800, 600))
app.OnDraw(func(dc *gogpu.Context) {
dc.DrawTriangleColor(gmath.DarkGray)
})
app.Run()
}
```
**Result:** A window with a rendered triangle in approximately 20 lines of code, compared to 480+ lines of raw WebGPU.
---
## Backend Selection
GoGPU supports two WebGPU implementations, selectable at compile time or runtime.
### Build Tags
```bash
# Pure Go backend (default, zero dependencies)
go build ./...
# Enable Rust backend (requires wgpu-native shared library)
go build -tags rust ./...
```
### Runtime Selection
```go
// Auto-select best available (default)
app := gogpu.NewApp(gogpu.DefaultConfig())
// Explicit Rust backend
app := gogpu.NewApp(gogpu.DefaultConfig().WithBackend(gogpu.BackendRust))
// Explicit Pure Go backend
app := gogpu.NewApp(gogpu.DefaultConfig().WithBackend(gogpu.BackendGo))
```
| Backend | Build Tag | Library | Use Case |
|---------|-----------|---------|----------|
| **Native Go** | (default) | gogpu/wgpu | Zero dependencies, simple deployment |
| **Rust** | `-tags rust` | wgpu-native via FFI | Maximum performance (all platforms) |
> **Note:** Rust backend requires [wgpu-native](https://github.com/gfx-rs/wgpu-native/releases) DLL.
### Graphics API Selection
Backend (Rust/Native) and Graphics API (Vulkan/DX12/Metal/GLES) are independent choices:
```go
// Force Vulkan on Windows (instead of auto-detected default)
app := gogpu.NewApp(gogpu.DefaultConfig().
WithGraphicsAPI(gogpu.GraphicsAPIVulkan))
// Force DirectX 12 on Windows
app := gogpu.NewApp(gogpu.DefaultConfig().
WithGraphicsAPI(gogpu.GraphicsAPIDX12))
// Force GLES (useful for testing or compatibility)
app := gogpu.NewApp(gogpu.DefaultConfig().
WithGraphicsAPI(gogpu.GraphicsAPIGLES))
// Software backend — no GPU required, always available
// Windows: renders to screen via GDI. Linux/macOS: headless.
app := gogpu.NewApp(gogpu.DefaultConfig().
WithGraphicsAPI(gogpu.GraphicsAPISoftware))
```
| Graphics API | Platforms | Constant |
|--------------|-----------|----------|
| **Auto** | All (default) | `gogpu.GraphicsAPIAuto` |
| **Vulkan** | Windows, Linux | `gogpu.GraphicsAPIVulkan` |
| **DX12** | Windows | `gogpu.GraphicsAPIDX12` |
| **Metal** | macOS | `gogpu.GraphicsAPIMetal` |
| **GLES** | Windows, Linux | `gogpu.GraphicsAPIGLES` |
| **Software** | All (no GPU needed) | `gogpu.GraphicsAPISoftware` |
---
## Resource Management
GPU resources are automatically cleaned up on shutdown when registered with `TrackResource`:
```go
canvas, _ := ggcanvas.New(provider, 800, 600)
app.TrackResource(canvas) // auto-closed on shutdown, no OnClose needed
```
Resources are closed in LIFO (reverse) order after GPU idle, before device destruction. The shutdown sequence is: `WaitIdle → tracked resources → OnClose → Renderer.Destroy()`.
**ggcanvas auto-registration:** When created via a provider that implements `ResourceTracker` (like `App`), ggcanvas auto-registers — no `TrackResource` call needed.
**GC safety net:** Textures use `runtime.AddCleanup` as a fallback — if you forget `Destroy()`, the GC will eventually clean up GPU resources. This is a safety net, not a replacement for explicit cleanup.
---
## Texture Loading
```go
// Load from file (PNG, JPEG)
tex, err := renderer.LoadTexture("sprite.png")
defer tex.Destroy()
// Create from Go image
img := image.NewRGBA(image.Rect(0, 0, 128, 128))
tex, err := renderer.NewTextureFromImage(img)
// With custom filtering options
opts := gogpu.TextureOptions{
MagFilter: gputypes.FilterModeNearest, // Crisp pixels
AddressModeU: gputypes.AddressModeRepeat, // Tiling
}
tex, err := renderer.LoadTextureWithOptions("tile.png", opts)
```
---
## DeviceProvider Interface
GoGPU exposes GPU resources through the `DeviceProvider` interface for integration with external libraries:
```go
type DeviceProvider interface {
Device() hal.Device // HAL GPU device (type-safe Go interface)
Queue() hal.Queue // HAL command queue
SurfaceFormat() gputypes.TextureFormat
}
// Usage
provider := app.DeviceProvider()
device := provider.Device() // hal.Device — 30+ methods with error returns
queue := provider.Queue() // hal.Queue — Submit, WriteBuffer, ReadBuffer
```
### Cross-Package Integration (gpucontext)
For integration with external libraries like [gogpu/gg](https://github.com/gogpu/gg), use the standard [gpucontext](https://github.com/gogpu/gpucontext) interfaces:
```go
import "github.com/gogpu/gpucontext"
// Get gpucontext.DeviceProvider for external libraries
provider := app.GPUContextProvider()
device := provider.Device() // gpucontext.Device interface
queue := provider.Queue() // gpucontext.Queue interface
format := provider.SurfaceFormat() // gpucontext.TextureFormat
// Get gpucontext.EventSource for UI frameworks
events := app.EventSource()
events.OnKeyPress(func(key gpucontext.Key, mods gpucontext.Modifiers) {
// Handle keyboard input
})
events.OnMousePress(func(button gpucontext.MouseButton, x, y float64) {
// Handle mouse click
})
```
This enables enterprise-grade dependency injection between packages without circular imports.
### HalProvider (Direct GPU Access)
For GPU accelerators that need low-level HAL access (compute shaders, buffer readback):
```go
import "github.com/gogpu/gpucontext"
provider := app.GPUContextProvider()
// Type-assert to HalProvider for direct HAL access
if hp, ok := provider.(gpucontext.HalProvider); ok {
halDevice := hp.HalDevice() // hal.Device for compute pipelines
halQueue := hp.HalQueue() // hal.Queue for command submission
}
```
Used by [gogpu/gg](https://github.com/gogpu/gg) GPU SDF accelerator for compute shader dispatch on shared device.
### SurfaceView (Zero-Copy Rendering)
For direct GPU rendering without CPU readback:
```go
app.OnDraw(func(dc *gogpu.Context) {
view := dc.SurfaceView() // Current frame's GPU texture view
// Pass to ggcanvas.RenderDirect() for zero-copy compositing
})
```
This eliminates the GPU→CPU→GPU round-trip when integrating with gg/ggcanvas.
### Window & Platform Integration
`App` implements `gpucontext.WindowProvider` and `gpucontext.PlatformProvider` for UI frameworks:
```go
// Window geometry and DPI
w, h := app.Size() // physical pixels
scale := app.ScaleFactor() // 1.0 = standard, 2.0 = Retina/HiDPI
// Clipboard
text, _ := app.ClipboardRead()
app.ClipboardWrite("copied text")
// Cursor management
app.SetCursor(gpucontext.CursorPointer) // hand cursor
app.SetCursor(gpucontext.CursorText) // I-beam for text input
// System preferences
if app.DarkMode() { /* switch to dark theme */ }
if app.ReduceMotion() { /* disable animations */ }
if app.HighContrast() { /* increase contrast */ }
fontMul := app.FontScale() // user's font size preference
```
### Ebiten-Style Input Polling
For game loops, use the polling-based Input API:
```go
import "github.com/gogpu/gogpu/input"
app.OnUpdate(func(dt float64) {
inp := app.Input()
// Keyboard
if inp.Keyboard().JustPressed(input.KeySpace) {
player.Jump()
}
if inp.Keyboard().Pressed(input.KeyLeft) {
player.MoveLeft(dt)
}
// Mouse
x, y := inp.Mouse().Position()
if inp.Mouse().JustPressed(input.MouseButtonLeft) {
player.Shoot(x, y)
}
})
```
All input methods are thread-safe and work with the frame-based update loop.
### Event-Driven Rendering
GoGPU uses a three-state rendering model for optimal power efficiency:
| State | Condition | CPU Usage | Latency |
|-------|-----------|-----------|---------|
| **Idle** | No activity | 0% (blocks on OS events) | <1ms wakeup |
| **Animating** | Active animation tokens | VSync (~60fps) | Smooth |
| **Continuous** | `ContinuousRender=true` | 100% (game loop) | Immediate |
```go
// Event-driven mode (default for UI apps)
app := gogpu.NewApp(gogpu.DefaultConfig().
WithContinuousRender(false))
// Start animation — renders at VSync while token is alive
token := app.StartAnimation()
// ... animation runs at 60fps ...
token.Stop() // Loop returns to idle (0% CPU)
// Request single-frame redraw from any goroutine
app.RequestRedraw()
```
Multiple animation tokens can be active simultaneously. The loop renders continuously until all tokens are stopped.
### Resource Cleanup
Use `OnClose` to release GPU resources before the renderer is destroyed:
```go
app.OnClose(func() {
if canvas != nil {
_ = canvas.Close()
canvas = nil
}
})
if err := app.Run(); err != nil {
log.Fatal(err)
}
```
`OnClose` runs on the render thread before `Renderer.Destroy()`, ensuring textures, bind groups, and pipelines are released while the device is still alive.
---
## Compute Shaders
Full compute shader support via HAL interfaces:
```go
// Create compute pipeline via HAL device
pipeline, _ := device.CreateComputePipeline(&hal.ComputePipelineDescriptor{
Layout: pipelineLayout,
Module: shaderModule,
EntryPoint: "main",
})
// Create storage buffers
inputBuffer, _ := device.CreateBuffer(&hal.BufferDescriptor{
Size: dataSize,
Usage: gputypes.BufferUsageStorage | gputypes.BufferUsageCopyDst,
})
// Dispatch compute work via command encoder
encoder, _ := device.CreateCommandEncoder()
encoder.BeginEncoding("compute")
pass := encoder.BeginComputePass(&hal.ComputePassDescriptor{})
pass.SetPipeline(pipeline)
pass.SetBindGroup(0, bindGroup, nil)
pass.Dispatch(workgroupsX, 1, 1)
pass.End()
cmdBuf := encoder.EndEncoding()
queue.Submit([]hal.CommandBuffer{cmdBuf}, nil, 0)
```
---
## Logging
GoGPU uses `log/slog` for structured logging, silent by default:
```go
import "log/slog"
// Enable info-level logging
gogpu.SetLogger(slog.Default())
// Enable debug-level logging for full diagnostics
gogpu.SetLogger(slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{
Level: slog.LevelDebug,
})))
// Get current logger
logger := gogpu.Logger()
```
Log levels: `Debug` (texture creation, pipeline state), `Info` (backend selected, adapter info), `Warn` (resource cleanup errors).
---
## Architecture
GoGPU uses **multi-thread architecture** (Ebiten/Gio pattern) for professional responsiveness:
- **Main thread:** Window events only (Win32/Cocoa/X11 message pump)
- **Render thread:** All GPU operations (device, swapchain, commands)
This ensures windows never show "Not Responding" during heavy GPU operations.
```
User Application
│
▼
┌─────────────────────────────────────────────────────────┐
│ gogpu.App │
│ Multi-Thread: Events (main) + Render (dedicated) │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ gogpu.Renderer │
│ Uses hal.Device / hal.Queue directly (Go interfaces) │
└─────────────────────────────────────────────────────────┘
│
├─────────────────┐
▼ ▼
┌─────────────┐ ┌─────────────┐
│ gogpu/wgpu │ │ Platform │
│ (Pure Go │ │ Windowing │
│ WebGPU) │ │ Win32/Cocoa │
└──────┬──────┘ └─────────────┘
│
┌─────┴─────┬─────┬─────┬─────────┐
▼ ▼ ▼ ▼ ▼
Vulkan DX12 Metal GLES Software
```
### Package Structure
| Package | Purpose |
|---------|---------|
| `gogpu` (root) | App, Config, Context, Renderer, Texture |
| `gpu/` | Backend selection (HAL-based) |
| `gpu/types/` | BackendType, GraphicsAPI enums |
| `gpu/backend/rust/` | Rust backend via wgpu-native FFI (opt-in, `-tags rust`) |
| `gpu/backend/native/` | HAL backend creation (Vulkan/Metal selection) |
| `gmath/` | Vec2, Vec3, Vec4, Mat4, Color |
| `window/` | Window configuration |
| `input/` | Keyboard and mouse input |
| `internal/platform/` | Platform-specific windowing |
| `internal/thread/` | Multi-thread rendering (RenderLoop) |
---
## Platform Support
### Windows
Native Win32 windowing with Vulkan, DirectX 12, GLES, and Software backends.
### Linux
X11 and Wayland support with Vulkan, GLES, and Software (headless) backends.
- **X11** — pure Go X11 protocol with libX11 loaded via goffi for Vulkan surface creation. Multi-touch input via XInput2 wire protocol.
- **Wayland** — pure Go Wayland protocol (object dispatch) with libwayland-client via goffi for Vulkan surfaces. Server-side decorations via `zxdg_decoration_manager_v1`. Tested on WSLg, GNOME, KDE, sway.
### macOS
Pure Go Cocoa implementation via goffi Objective-C runtime, with Metal and Software (headless) backends:
```
internal/platform/darwin/
├── application.go # NSApplication lifecycle
├── window.go # NSWindow, NSView management
├── surface.go # CAMetalLayer integration
└── objc.go # Objective-C runtime via goffi
```
**Note:** macOS Cocoa requires UI operations on the main thread. GoGPU handles this automatically.
---
## Ecosystem
| Project | Description |
|---------|-------------|
| **gogpu/gogpu** | **GPU framework (this repo)** |
| [gogpu/gpucontext](https://github.com/gogpu/gpucontext) | Shared interfaces (DeviceProvider, WindowProvider, PlatformProvider, EventSource) |
| [gogpu/gputypes](https://github.com/gogpu/gputypes) | Shared WebGPU types (TextureFormat, BufferUsage, Limits) |
| [gogpu/wgpu](https://github.com/gogpu/wgpu) | Pure Go WebGPU implementation |
| [gogpu/naga](https://github.com/gogpu/naga) | Shader compiler (WGSL to SPIR-V, MSL, GLSL) |
| [gogpu/gg](https://github.com/gogpu/gg) | 2D graphics library |
| [gogpu/ui](https://github.com/gogpu/ui) | GUI toolkit (planned) |
| [go-webgpu/webgpu](https://github.com/go-webgpu/webgpu) | wgpu-native FFI bindings |
| [go-webgpu/goffi](https://github.com/go-webgpu/goffi) | Pure Go FFI library |
---
## Documentation
- **[ARCHITECTURE.md](docs/ARCHITECTURE.md)** — System architecture
- **[ROADMAP.md](ROADMAP.md)** — Development milestones
- **[CHANGELOG.md](CHANGELOG.md)** — Release notes
- **[pkg.go.dev](https://pkg.go.dev/github.com/gogpu/gogpu)** — API reference
### Articles
- [GoGPU: From Idea to 100K Lines in Two Weeks](https://dev.to/kolkov/gogpu-from-idea-to-100k-lines-in-two-weeks-building-gos-gpu-ecosystem-3b2)
- [GoGPU Announcement](https://dev.to/kolkov/gogpu-a-pure-go-graphics-library-for-gpu-programming-2j5d)
---
## Contributing
Contributions welcome! See [GitHub Discussions](https://github.com/gogpu/gogpu/discussions) to share ideas and ask questions.
**Priority areas:**
- Platform testing (macOS, Linux X11/Wayland, Windows DX12)
- Documentation and examples
- Performance benchmarks
- Bug reports
```bash
git clone https://github.com/gogpu/gogpu
cd gogpu
go build ./...
go test ./...
```
---
## Acknowledgments
**Professor Ancha Baranova** — This project would not have been possible without her invaluable help and support.
### Inspiration
- [u/m-unknown-2025](https://www.reddit.com/user/m-unknown-2025/) — The [Reddit post](https://www.reddit.com/r/golang/comments/1pdw9i7/go_deserves_more_support_in_gui_development/) that started it all
- [born-ml/born](https://github.com/born-ml/born) — ML framework where go-webgpu bindings originated
### Contributors
| Contributor | Contributions |
|-------------|---------------|
| [@ppoage](https://github.com/ppoage) | macOS ARM64 (Apple Silicon) support — 3 merged PRs across gogpu, wgpu, and naga with ~3,500 lines of code. Made Metal backend work on M1/M4 |
| [@JanGordon](https://github.com/JanGordon) | Documentation fix (wgpu) |
### Community Champions
| Champion | Contributions |
|----------|---------------|
| [@darkliquid](https://github.com/darkliquid) · Andrew Montgomery | Linux platform hero — 3 bug reports, 13+ comments with detailed stack traces and diagnostics. His persistence uncovered the critical [goffi stack spill bug](https://github.com/go-webgpu/goffi/issues/19) affecting all Linux/macOS users |
| [@i2534](https://github.com/i2534) | Most prolific gg tester — 7 bug reports covering alpha blending, patterns, transforms, and line joins. Shaped the quality of the 2D renderer |
| [@qq1792569310](https://github.com/qq1792569310) · luomo | Early stress-tester — 3 issues and 9 comments. Found memory leak and event system bugs that improved framework stability |
| [@rcarlier](https://github.com/rcarlier) · Richard Carlier | Cross-platform tester — 4 issues across gg and ui. Active tester of text rendering, image handling, and UI on macOS Apple Silicon (M3) |
| [@amortaza](https://github.com/amortaza) · Afshin Mortazavi-Nia | Architecture contributor — deep multi-week engagement in gg+gogpu integration discussions. Author of [go-bellina](https://github.com/amortaza/go-bellina) UI library |
| [@cyberbeast](https://github.com/cyberbeast) · Sandesh Gade | macOS Tahoe debugger — thorough Metal backend debugging on Apple M2 Max with detailed diagnostics |
| [@crsolver](https://github.com/crsolver) | UI architecture advisor — significant input on the UI toolkit RFC with 8+ discussion comments |
| [@neurlang](https://github.com/neurlang) | Wayland expert — author of [neurlang/wayland](https://github.com/neurlang/wayland), provided expert consultation on Wayland protocol issues |
### Early Adopters
These developers tested GoGPU on Day 1 — when nothing worked and every platform was broken. Their bug reports shaped the project:
- [@Nickrocky](https://github.com/Nickrocky) — First macOS tester (Dec 25, 2025). The very first external user to try GoGPU
- [@facemcgee](https://github.com/facemcgee) — Early Linux tester (Dec 29, 2025)
- [@soypat](https://github.com/soypat) — Early naga interest, [gsdf](https://github.com/soypat/gsdf) integration exploration
- [@jan53n](https://github.com/jan53n) — Linux X11 testing
- [@davidmichaelkarr](https://github.com/davidmichaelkarr) — Windows 11 testing
- [@martinarisk](https://github.com/martinarisk) — Wayland testing, report that led to major protocol fixes
- [@adamsanclemente](https://github.com/adamsanclemente) — Found transform rendering bug in gg
- [@beikege](https://github.com/beikege) — Touch input advocacy, UI toolkit feedback
- [@joeblew999](https://github.com/joeblew999) — WASM/browser platform interest
---
## License
MIT License — see [LICENSE](LICENSE) for details.
---
GoGPU — Building the GPU computing ecosystem Go deserves