๐Ÿ“š gogpu - Awesome Go Library for Game Development

Go Gopher mascot for 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
๐Ÿ“‚ Game Development
โญ 0 stars
View on GitHub ๐Ÿ”—

Detailed Description of gogpu

GoGPU Logo

GoGPU

Pure Go GPU Computing Ecosystem
GPU power, Go simplicity. Zero CGO.

CI codecov Go Reference Go Report Card License Latest Release Go Version Stars


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

CategoryCapabilities
BackendsRust (wgpu-native) or Pure Go (gogpu/wgpu)
Graphics APIRuntime selection: Vulkan, DX12, Metal, GLES, Software
PlatformsWindows (Vulkan/DX12/GLES), Linux X11/Wayland (Vulkan/GLES), macOS (Metal)
RenderingEvent-driven three-state model (idle/animating/continuous), zero-copy surface rendering
GraphicsWindowing, input handling, texture loading, frameless windows, mouse grab / pointer lock (SDL parity)
ComputeFull compute shader support
Window ChromeFrameless windows with custom title bars, DWM shadow, hit-test regions
HiDPIPer-monitor DPI, WM_DPICHANGED, logical/physical coordinate split
IntegrationDeviceProvider, WindowProvider, PlatformProvider, WindowChrome, SurfaceView
LoggingStructured logging via log/slog, silent by default
BuildZero CGO with Pure Go backend

Installation

go get github.com/gogpu/gogpu

Requirements:

  • Go 1.25+
  • CGO_ENABLED=0 (Pure Go FFI requires CGO disabled)

Zero dependencies โ€” just works:

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

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

# Pure Go backend (default, zero dependencies)
go build ./...

# Enable Rust backend (requires wgpu-native shared library)
go build -tags rust ./...

Runtime Selection

// 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))
BackendBuild TagLibraryUse Case
Native Go(default)gogpu/wgpuZero dependencies, simple deployment
Rust-tags rustwgpu-native via FFIMaximum performance (all platforms)

Note: Rust backend requires wgpu-native DLL.

Graphics API Selection

Backend (Rust/Native) and Graphics API (Vulkan/DX12/Metal/GLES) are independent choices:

// 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 APIPlatformsConstant
AutoAll (default)gogpu.GraphicsAPIAuto
VulkanWindows, Linuxgogpu.GraphicsAPIVulkan
DX12Windowsgogpu.GraphicsAPIDX12
MetalmacOSgogpu.GraphicsAPIMetal
GLESWindows, Linuxgogpu.GraphicsAPIGLES
SoftwareAll (no GPU needed)gogpu.GraphicsAPISoftware

Resource Management

GPU resources are automatically cleaned up on shutdown when registered with TrackResource:

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

// 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:

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, use the standard gpucontext interfaces:

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.

DeviceProvider (GPU Access)

For GPU compute and custom rendering, access the wgpu device directly:

provider := app.DeviceProvider()
device := provider.Device()   // *wgpu.Device โ€” full WebGPU API
queue := device.Queue()       // *wgpu.Queue โ€” command submission

Used for compute shaders, custom render pipelines, and by gogpu/gg GPU accelerator.

SurfaceView (Zero-Copy Rendering)

For direct GPU rendering without CPU readback:

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:

// Window geometry and DPI
w, h := app.Size()              // logical points (DIP)
fw, fh := app.PhysicalSize()    // physical pixels (framebuffer)
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

// Mouse grab / pointer lock (FPS games, 3D editors)
app.SetCursorMode(gpucontext.CursorModeLocked)   // hide + capture relative deltas (SDL parity)
app.SetCursorMode(gpucontext.CursorModeConfined)  // visible, confined to window
app.SetCursorMode(gpucontext.CursorModeNormal)    // release

// 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:

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:

StateConditionCPU UsageLatency
IdleNo activity0% (blocks on OS events)<1ms wakeup
AnimatingActive animation tokensVSync (~60fps)Smooth
ContinuousContinuousRender=true100% (game loop)Immediate
// 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:

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 wgpu public API:

device := app.DeviceProvider().Device()

// WGSL compute shader
shader, _ := device.CreateShaderModule(&wgpu.ShaderModuleDescriptor{
    WGSL: `
        @group(0) @binding(0) var<storage, read> input: array<f32>;
        @group(0) @binding(1) var<storage, read_write> output: array<f32>;

        @compute @workgroup_size(64)
        fn main(@builtin(global_invocation_id) id: vec3<u32>) {
            output[id.x] = input[id.x] * 2.0;
        }
    `,
})

// Create storage buffers
inputBuf, _ := device.CreateBuffer(&wgpu.BufferDescriptor{
    Size:  dataSize,
    Usage: wgpu.BufferUsageStorage | wgpu.BufferUsageCopyDst,
})

// Create pipeline and dispatch
pipeline, _ := device.CreateComputePipeline(&wgpu.ComputePipelineDescriptor{
    Layout: pipelineLayout, Module: shader, EntryPoint: "main",
})

encoder, _ := device.CreateCommandEncoder(nil)
pass, _ := encoder.BeginComputePass(nil)
pass.SetPipeline(pipeline)
pass.SetBindGroup(0, bindGroup, nil)
pass.Dispatch(workgroups, 1, 1)
pass.End()
cmds, _ := encoder.Finish()
_, _ = device.Queue().Submit(cmds)
device.WaitIdle()  // wait for GPU before readback

// Read results back to CPU
result := make([]byte, dataSize)
device.Queue().ReadBuffer(stagingBuf, 0, result)

See examples/particles for a full GPU particle simulation (compute + render in one window) and wgpu/examples/compute-particles for a headless compute example.


Logging

GoGPU uses log/slog for structured logging, silent by default:

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

PackagePurpose
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 โ€” single libwayland-client connection via goffi for all Wayland operations (surface, input, xdg-shell, CSD). Server-side decorations via zxdg_decoration_manager_v1, client-side decorations (CSD) with subsurface title bar when SSD unavailable. Tested on WSLg, GNOME, KDE, sway, niri, COSMIC.

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

ProjectDescription
gogpu/gogpuGPU framework (this repo)
gogpu/gpucontextShared interfaces (DeviceProvider, WindowProvider, PlatformProvider, EventSource)
gogpu/gputypesShared WebGPU types (TextureFormat, BufferUsage, Limits)
gogpu/wgpuPure Go WebGPU implementation
gogpu/nagaShader compiler (WGSL to SPIR-V, MSL, GLSL)
gogpu/gg2D graphics library
gogpu/uiGUI toolkit (planned)
go-webgpu/webgpuwgpu-native FFI bindings
go-webgpu/goffiPure Go FFI library

Documentation

Articles


Contributing

Contributions welcome! See GitHub Discussions to share ideas and ask questions.

Priority areas:

  • Platform testing (macOS, Linux X11/Wayland, Windows DX12)
  • Documentation and examples
  • Performance benchmarks
  • Bug reports
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

Contributors

ContributorContributions
@ppoagemacOS 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
@JanGordonDocumentation fix (wgpu)

Community Champions

ChampionContributions
@darkliquid ยท Andrew MontgomeryLinux platform hero โ€” 3 bug reports, 13+ comments with detailed stack traces and diagnostics. His persistence uncovered the critical goffi stack spill bug affecting all Linux/macOS users
@i2534Most prolific gg tester โ€” 7 bug reports covering alpha blending, patterns, transforms, and line joins. Shaped the quality of the 2D renderer
@qq1792569310 ยท luomoEarly stress-tester โ€” 3 issues and 9 comments. Found memory leak and event system bugs that improved framework stability
@rcarlier ยท Richard CarlierCross-platform tester โ€” 4 issues across gg and ui. Active tester of text rendering, image handling, and UI on macOS Apple Silicon (M3)
@amortaza ยท Afshin Mortazavi-NiaArchitecture contributor โ€” deep multi-week engagement in gg+gogpu integration discussions. Author of go-bellina UI library
@cyberbeast ยท Sandesh GademacOS Tahoe debugger โ€” thorough Metal backend debugging on Apple M2 Max with detailed diagnostics
@crsolverUI architecture advisor โ€” significant input on the UI toolkit RFC with 8+ discussion comments
@neurlangWayland expert โ€” author of 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 โ€” First macOS tester (Dec 25, 2025). The very first external user to try GoGPU
  • @facemcgee โ€” Early Linux tester (Dec 29, 2025)
  • @soypat โ€” Early naga interest, gsdf integration exploration
  • @jan53n โ€” Linux X11 testing
  • @davidmichaelkarr โ€” Windows 11 testing
  • @martinarisk โ€” Wayland testing, report that led to major protocol fixes
  • @adamsanclemente โ€” Found transform rendering bug in gg
  • @beikege โ€” Touch input advocacy, UI toolkit feedback
  • @joeblew999 โ€” WASM/browser platform interest

License

MIT License โ€” see LICENSE for details.


GoGPU โ€” Building the GPU computing ecosystem Go deserves