Unified Go WebGPU — Three Backends, One API
Pure Go · Rust FFI · Browser WASM — build tag selects the stack
Part of the GoGPU ecosystem
wgpu is the unified Go WebGPU package with three independent implementations selected by build tags — like Chrome (Dawn) and Firefox (wgpu) implementing the same W3C spec.
| Category | Capabilities |
|---|---|
| Backends | Vulkan, Metal, DirectX 12, OpenGL ES, Software, Browser WebGPU, Rust FFI |
| Platforms | Windows, Linux, macOS, iOS, Browser (WASM), Android/arm64 (preview) |
| API | WebGPU-compliant (W3C specification) |
| Shaders | WGSL via gogpu/naga compiler (SPIR-V, HLSL, MSL, GLSL, DXIL) |
| Compute | Full compute shader support, GPU→CPU readback |
| Present | Damage-aware presentation — compositor dirty rects (first WebGPU implementation) |
| Debug | Leak detection, error scopes, validation layers, DRED diagnostics (DX12), structured logging (log/slog) |
| Build | Zero CGO, simple go build |
go get github.com/gogpu/wgpuRequirements: Go 1.25+
Build:
CGO_ENABLED=0 go buildNote: wgpu uses Pure Go FFI via goffi. Both
CGO_ENABLED=0(default, zero C compiler dependency) andCGO_ENABLED=1(for race detector or coexistence with CGO libraries) are supported.
The unreleased Android/arm64 Vulkan implementation is documented separately in Android Vulkan preview. It consumes canonical goffi v0.6.1 and is not yet a released support claim; the optional Rust path temporarily pins the exact merged WebGPU Android source until that dependency is released.
New surface integrations should use the explicit safe or unsafe target API
described in Surface targets. The original
two-uintptr method remains available as a compatibility adapter.
Rust FFI backend (optional, battle-tested wgpu-native drivers):
go build -tags rustRequires wgpu-native v29 binary. Set
WGPU_NATIVE_PATHor place in system PATH. See go-webgpu/webgpu for details.
Browser (WASM):
GOOS=js GOARCH=wasm go build -o app.wasm .Three implementations, one API — build tags select the stack:
Build Tag Implementation Use Case (default) Pure Go → core → HAL → Vulkan/Metal/DX12/GLES/Software Zero deps, cross-compile -tags rustgo-webgpu/webgpu → wgpu-native v29 Battle-tested GPU drivers GOOS=jssyscall/js → Browser WebGPU Web applications API consistency: The public API compiles on all build targets. HAL wrapper functions (
NewDeviceFromHAL,NewSurfaceFromHAL, etc.) return errors or nil on Rust/Browser builds where no Go HAL layer exists. UseRequestAdapter→RequestDevicefor the standard cross-backend path.
package main
import (
"fmt"
"github.com/gogpu/wgpu"
_ "github.com/gogpu/wgpu/hal/allbackends" // Auto-register platform backends
)
func main() {
// Create instance
instance, _ := wgpu.CreateInstance(nil)
defer instance.Release()
// Request high-performance GPU
adapter, _ := instance.RequestAdapter(&wgpu.RequestAdapterOptions{
PowerPreference: wgpu.PowerPreferenceHighPerformance,
})
defer adapter.Release()
// Get adapter info
info := adapter.Info()
fmt.Printf("GPU: %s (%s)\n", info.Name, info.Backend)
// Create device
device, _ := adapter.RequestDevice(nil)
defer device.Release()
// Create a GPU buffer
buffer, _ := device.CreateBuffer(&wgpu.BufferDescriptor{
Label: "My Buffer",
Size: 1024,
Usage: wgpu.BufferUsageStorage | wgpu.BufferUsageCopyDst,
})
defer buffer.Release()
// Write data to buffer
if err := device.Queue().WriteBuffer(buffer, 0, []byte{1, 2, 3, 4}); err != nil {
panic(err)
}
}// Create shader module from WGSL
shader, _ := device.CreateShaderModule(&wgpu.ShaderModuleDescriptor{
Label: "Compute Shader",
WGSL: wgslSource,
})
defer shader.Release()
// Create compute pipeline
pipeline, _ := device.CreateComputePipeline(&wgpu.ComputePipelineDescriptor{
Label: "Compute Pipeline",
Layout: pipelineLayout,
Module: shader,
EntryPoint: "main",
})
defer pipeline.Release()
// Record and submit commands
encoder, _ := device.CreateCommandEncoder(nil)
pass, _ := encoder.BeginComputePass(nil)
pass.SetPipeline(pipeline)
pass.SetBindGroup(0, bindGroup, nil)
pass.Dispatch(64, 1, 1)
pass.End()
cmdBuffer, _ := encoder.Finish()
_, _ = device.Queue().Submit(cmdBuffer) // returns (submissionIndex, error)WebGPU-spec-compliant dual-layer API. Primary path is blocking + context.Context
(idiomatic Go, zero allocation); escape hatch MapAsync + Device.Poll is for
game loops that cannot afford to block.
// Primary: blocking, idiomatic, zero-alloc.
// Map blocks until the GPU finishes writing the buffer (or ctx cancels).
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := stagingBuf.Map(ctx, wgpu.MapModeRead, 0, size); err != nil {
log.Fatal(err)
}
defer stagingBuf.Unmap()
rng, _ := stagingBuf.MappedRange(0, size)
data := rng.Bytes() // []byte view, zero copy, valid until Unmap
process(data)// Escape hatch: async, non-blocking, for render loops.
pending, _ := stagingBuf.MapAsync(wgpu.MapModeRead, 0, size)
// Continue rendering; auto-polled on next Queue.Submit.
renderFrame()
if ready, _ := pending.Status(); ready {
rng, _ := stagingBuf.MappedRange(0, size)
process(rng.Bytes())
stagingBuf.Unmap()
}Safety guarantees: UAF protection via generation counters on MappedRange,
ErrBufferDestroyed on destroy-during-pending, ErrMapCancelled on unmap-during-pending,
ErrMapRangeOverlap for overlapping MappedRange calls, MAP_ALIGNMENT = 8
validation, thread-safe concurrent Device.Poll.
See ADR-BUFFER-MAPPING-API for the full design rationale and comparison with Rust wgpu.
Guides: Getting Started | Backend Differences
Features: WGSL compute shaders, storage/uniform buffers, indirect dispatch, GPU timestamp queries (Vulkan, DX12), WebGPU-compliant Buffer.Map / MapAsync GPU→CPU readback with context.Context integration.
wgpu/
├── *.go # Public API (import "github.com/gogpu/wgpu")
├── core/ # Validation, state tracking, deferred resource destruction
├── hal/ # Hardware Abstraction Layer
│ ├── allbackends/ # Platform-specific backend auto-registration
│ ├── noop/ # No-op backend (testing)
│ ├── software/ # CPU software rasterizer (~14K LOC)
│ ├── gles/ # OpenGL ES 3.0+ (~12K LOC)
│ ├── vulkan/ # Pure Go Vulkan backend (~42K LOC)
│ ├── metal/ # Metal (~7K LOC)
│ └── dx12/ # DirectX 12 (~17K LOC)
├── examples/
│ ├── compute-copy/ # GPU buffer copy with compute shader
│ └── compute-sum/ # Parallel reduction on GPU
└── cmd/
├── vk-gen/ # Vulkan bindings generator
└── ... # Backend integration tests
The root package (import "github.com/gogpu/wgpu") provides a safe, ergonomic API aligned with the W3C WebGPU specification. It wraps core/ and hal/ into user-friendly types:
User Application
↓ import "github.com/gogpu/wgpu" ← always the same import
Root Package (public API: *Device, *Buffer, *Texture...)
↓ build tag selects implementation
├─ [default] _native.go → core/ → hal/ → vulkan/metal/dx12/gles/software
├─ [-tags rust] _rust.go → go-webgpu/webgpu → wgpu-native
└─ [js,wasm] _browser.go → syscall/js → Browser WebGPU
For the default (Pure Go) path, backends auto-register via blank imports:
import _ "github.com/gogpu/wgpu/hal/allbackends"
// Platform-specific backends auto-registered:
// - Windows: Vulkan, DX12, GLES, Software
// - Linux: Vulkan, GLES, Software
// - macOS: Metal, Vulkan, Software
// - Android/arm64 preview: Vulkan only| Backend | Windows | Linux | macOS | iOS | Android/arm64 | Notes |
|---|---|---|---|---|---|---|
| Vulkan | Yes | Yes | Yes | - | Preview | MoltenVK on macOS; Android contract |
| Metal | - | - | Yes | Yes | - | Native Apple GPU |
| DX12 | Yes | - | - | - | - | Windows 10+ |
| GLES | Yes | Yes | - | - | - | OpenGL ES 3.0+ |
| Software | Yes | Yes | Yes | Yes | - | CPU fallback |
Architectures: amd64, arm64 (including Windows ARM64 / Snapdragon X)
Pure Go Vulkan backend with:
- Auto-generated bindings from official
vk.xml - Buddy allocator for GPU memory (O(log n), minimal fragmentation)
- Dynamic rendering (VK_KHR_dynamic_rendering)
- Classic render pass fallback for Intel compatibility
- wgpu-style swapchain synchronization
- MSAA render pass with automatic resolve
- Complete resource management (Buffer, Texture, Pipeline, BindGroup)
- Surface creation: Win32, X11, Wayland, Metal (MoltenVK), and Android
ANativeWindow(preview) - Debug messenger for validation layer error capture (
VK_EXT_debug_utils) - Structured diagnostic logging via
log/slog
Native Apple GPU access via:
- Pure Go Objective-C bridge (goffi)
- Metal API via runtime message dispatch
- CAMetalLayer integration for surface presentation
- MSL shader compilation via naga
Windows GPU access via:
- Pure Go COM bindings (syscall, no CGO)
- DXGI integration for swapchain and adapters
- Flip model with VRR support
- Descriptor heap management with fence-based deferred destruction
- Encoder pool with allocator recycling (Rust wgpu-core pattern)
- In-memory shader cache (SHA-256 keyed, LRU eviction, works for both paths)
- DRED diagnostics (auto-breadcrumbs + page fault tracking on TDR)
- Dual shader compilation: HLSL→FXC (default, SM 5.1) or DXIL direct via naga (
GOGPU_DX12_DXIL=1, SM 6.0+, zero external dependencies — first Pure Go DXIL generator) - StagingBelt ring-buffer allocator for zero-allocation GPU data transfer
Cross-platform GPU access via OpenGL ES 3.0+:
- Pure Go EGL/GL bindings (goffi)
- Full rendering pipeline: VAO, FBO, MSAA, blend, stencil, depth
- WGSL shader compilation (WGSL → GLSL via naga)
- Combined texture-sampler binding via SamplerBindMap (Rust wgpu pattern)
- Text rendering with proper texture completeness handling
- CopyTextureToBuffer readback for GPU → CPU data transfer
- Platform detection: X11, Wayland, Surfaceless (headless CI)
- Works with Mesa llvmpipe for software-only environments
Full-featured CPU rasterizer for headless and windowed rendering. Always compiled — no build tags or GPU hardware required.
// Software backend auto-registers via init().
// No explicit import needed when using hal/allbackends.
// For standalone usage:
import _ "github.com/gogpu/wgpu/hal/software"
// Use cases:
// - CI/CD testing without GPU
// - Server-side image generation
// - Reference implementation
// - Fallback when GPU unavailable
// - Embedded systems without GPURasterization Features:
- Edge function triangle rasterization (Pineda algorithm)
- Perspective-correct interpolation
- Depth buffer (8 compare functions)
- Stencil buffer (8 operations)
- Blending (13 factors, 5 operations)
- 6-plane frustum clipping (Sutherland-Hodgman)
- 8x8 tile-based parallel rendering
- SPIR-V interpreter — executes vertex/fragment/compute shaders on CPU. Designed for shader debugging, CI/CD testing, and GPU-less environments — not for production rendering (interpreted, ~100× slower than JIT software renderers like SwiftShader). See ADR.
Debug & Testing:
- Render pass instrumentation:
hal.Logger().Debug()events +RenderPassStatsfor CI e2e assertions - Public
wgpu.HeadlessSurfaceTarget+Surface.ReadPixels()lifecycle for deterministic headless render verification; snapshots are owned, tightly packed RGBA8 - HAL
GetFramebuffer()remains as a compatibility alias for existing software-backend callers; new root API code should useSurface.ReadPixels() - Damage-aware partial blit with pixel-level test coverage
See Surface targets for the complete configure → acquire → render → submit → present → readback recipe and the explicit non-WebGPU support contract.
Windowed Presentation:
- Windows: DWM-safe
CreateDIBSection+BitBlt(SDL3/Qt6 pattern), zero-copy into GDI bitmap - Linux X11:
XPutImagevia goffi (Skia pattern), BGRA = X11 ZPixmap native format - macOS: CGImage +
setContents:(CALayer) or MetalnextDrawable+replaceRegion(CAMetalLayer). Contributor: @k-chimi
| Variable | Values | Description |
|---|---|---|
GOGPU_DX12_DXIL |
1 |
Enable DXIL direct compilation on DX12 (experimental). Bypasses HLSL→FXC, generates DXIL bytecode directly from naga IR. SM 6.0+, zero external dependencies. Default: off (uses HLSL→FXC). |
GOGPU_DX12_DXIL_OVERRIDE_VS |
file path | Replace vertex shader DXIL with contents of the given file. For debugging only. |
GOGPU_DX12_DXIL_OVERRIDE_PS |
file path | Replace pixel shader DXIL with contents of the given file. For debugging only. |
Note: Backend selection (
GOGPU_GRAPHICS_API) is handled bygogpu(the app framework), not bywgpudirectly. See gogpu documentation forGOGPU_GRAPHICS_API=vulkan|dx12|metal|gles|software.
wgpu is the foundation of the GoGPU ecosystem.
| Project | Description |
|---|---|
| gogpu/gogpu | GPU framework with windowing and input |
| gogpu/wgpu | Unified Go WebGPU (this repo) — Pure Go + Rust FFI + Browser |
| go-webgpu/webgpu | Rust FFI backend (wgpu-native v29) |
| gogpu/naga | Shader compiler (WGSL to SPIR-V, HLSL, MSL, GLSL, DXIL) |
| gogpu/gg | 2D graphics library with GPU SDF acceleration |
| gogpu/ui | GUI toolkit: 22+ widgets, 4 themes |
| gogpu/gputypes | Shared WebGPU type definitions |
| go-webgpu/goffi | Pure Go FFI library |
- Compute Shaders Guide — Getting started with compute
- Compute Backend Differences — Per-backend capabilities
- ARCHITECTURE.md — System architecture
- ROADMAP.md — Development milestones
- CHANGELOG.md — Release notes
- CONTRIBUTING.md — Contribution guidelines
- pkg.go.dev — API reference
- WebGPU Specification — W3C standard
- wgpu (Rust) — Reference implementation
- Dawn (C++) — Google's implementation
- Architecture Deep-Dive (Chinese) — Performance benchmarks, Snatchable pattern analysis, zero-alloc hot paths
Contributions welcome! See CONTRIBUTING.md for guidelines.
Priority areas:
- Cross-platform testing
- Performance benchmarks
- Documentation improvements
- Bug reports and fixes
MIT License — see LICENSE for details.
wgpu — WebGPU in Pure Go