v0.5.0 is a major breaking release that upgrades wgpu-native from v27 to v29 (stable webgpu-headers) and redesigns the public API for idiomatic Go usage. This guide covers every breaking change with before/after examples.
See CHANGELOG.md for the full list of changes.
- wgpu-native Binary
- Error Returns on Create Methods
- Method Renames
- Single Import: gputypes Aliases
- Buffer Mapping API
- Queue.Submit Returns Index
- Limits Return Value (No Error)
- BindGroupLayoutEntry Pointer Sub-Layouts
- SamplerDescriptor.Anisotropy Rename
- Surface API Changes
- Removed Types
- Enum Changes
- Quick Checklist
Download the new binary from the wgpu-native releases page.
| Platform | Filename |
|---|---|
| Windows x64 | wgpu-windows-x86_64-msvc-release.zip → wgpu_native.dll |
| Linux x64 | wgpu-linux-x86_64-release.zip → libwgpu_native.so |
| macOS ARM64 | wgpu-macos-aarch64-release.zip → libwgpu_native.dylib |
Required version: v29.0.0.0. The v0.5.0 Go bindings are not compatible with v27.
All Create* methods now return (*T, error) instead of *T. This applies to every resource creation function.
// Before (v0.4.x) — nil on failure
buffer := device.CreateBuffer(&desc)
if buffer == nil {
log.Fatal("failed to create buffer")
}
defer buffer.Release()
// After (v0.5.0) — idiomatic error return
buffer, err := device.CreateBuffer(&desc)
if err != nil {
log.Fatal(err)
}
defer buffer.Release()Affected methods (all on *Device unless noted):
| Method | v0.4.x return | v0.5.0 return |
|---|---|---|
CreateBuffer |
*Buffer |
(*Buffer, error) |
CreateTexture |
*Texture |
(*Texture, error) |
CreateShaderModuleWGSL |
*ShaderModule |
(*ShaderModule, error) |
CreateRenderPipeline |
*RenderPipeline |
(*RenderPipeline, error) |
CreateComputePipeline |
*ComputePipeline |
(*ComputePipeline, error) |
CreateBindGroup |
*BindGroup |
(*BindGroup, error) |
CreateBindGroupLayout |
*BindGroupLayout |
(*BindGroupLayout, error) |
CreatePipelineLayout |
*PipelineLayout |
(*PipelineLayout, error) |
CreateCommandEncoder |
*CommandEncoder |
(*CommandEncoder, error) |
CreateSampler |
*Sampler |
(*Sampler, error) |
CreateQuerySet |
*QuerySet |
(*QuerySet, error) |
Texture.CreateView |
*TextureView |
(*TextureView, error) |
CommandEncoder.Finish |
*CommandBuffer |
(*CommandBuffer, error) |
Get prefix removed from accessor methods to follow Go naming conventions:
// Before (v0.4.x) // After (v0.5.0)
device.GetQueue() → device.Queue()
buffer.GetSize() → buffer.Size()
adapter.GetLimits() → adapter.Limits()
adapter.GetInfo() → adapter.Info()
device.GetLimits() → device.Limits()
device.GetFeatures() → device.Features()
texture.GetWidth() → texture.Width()
texture.GetHeight() → texture.Height()
texture.GetDepthOrArrayLayers() → texture.DepthOrArrayLayers()
texture.GetFormat() → texture.Format()
texture.GetDimension() → texture.Dimension()
texture.GetUsage() → texture.Usage()Additionally, Adapter.EnumerateFeatures() is now Adapter.Features(). The old name is kept as a deprecated alias until v1.0.
v0.5.0 re-exports gputypes types and constants as aliases in the wgpu package. A separate gputypes import is no longer required.
// Before (v0.4.x) — two imports required
import (
"github.com/go-webgpu/webgpu/wgpu"
"github.com/gogpu/gputypes"
)
surfaceConfig.Format = gputypes.TextureFormatBGRA8Unorm
bufferDesc.Usage = gputypes.BufferUsageVertex | gputypes.BufferUsageCopyDst// After (v0.5.0) — single import
import "github.com/go-webgpu/webgpu/wgpu"
surfaceConfig.Format = wgpu.TextureFormatBGRA8Unorm
bufferDesc.Usage = wgpu.BufferUsageVertex | wgpu.BufferUsageCopyDstThe direct gputypes import still works and produces the same types (they are aliases, not copies). Use the direct import when sharing types with other gogpu ecosystem packages.
The buffer mapping API has been redesigned to match gogpu/wgpu and support both blocking and async patterns.
// Before (v0.4.x) — MapAsync with device arg, then GetMappedRange unsafe.Pointer
if err := buffer.MapAsync(device, wgpu.MapModeRead, 0, size); err != nil {
return err
}
ptr := buffer.GetMappedRange(0, size)
data := unsafe.Slice((*byte)(ptr), size)
defer buffer.Unmap()
// After (v0.5.0) — Map blocks until done, MappedRange returns safe type
if err := buffer.Map(ctx, wgpu.MapModeRead, 0, size); err != nil {
return err
}
defer buffer.Unmap()
mr, err := buffer.MappedRange(0, size)
if err != nil {
return err
}
data := mr.Bytes() // []byte, valid until Unmap// Before (v0.4.x) — no truly async variant
if err := buffer.MapAsync(device, wgpu.MapModeRead, 0, size); err != nil {
return err
}
// After (v0.5.0) — non-blocking: returns *MapPending immediately
pending, err := buffer.MapAsync(wgpu.MapModeRead, 0, size)
if err != nil {
return err
}
// Option A: poll status manually
for {
ready, err := pending.Status()
if ready {
// err is nil on success
break
}
device.Poll(false)
}
// Option B: block with context
if err := pending.Wait(ctx); err != nil {
return err
}
// Then access mapped data as usual
mr, _ := buffer.MappedRange(0, size)
data := mr.Bytes()Buffer.GetMappedRange(offset, size) is retained for low-level access. MappedRange wraps it with type safety and buffer-state validation.
Queue.Submit now returns the submission index, useful for fence-based synchronization.
// Before (v0.4.x)
if err := queue.Submit(cmdBuf); err != nil {
return err
}
// After (v0.5.0)
subIdx, err := queue.Submit(cmdBuf)
if err != nil {
return err
}
// subIdx (uint64) can be used with Device.Poll or future fence APIs
_ = subIdxAdapter.Limits() and Device.Limits() now return Limits directly (cached at creation, no FFI call).
// Before (v0.4.x) — SupportedLimits wrapper, error return
supported, err := adapter.GetLimits()
if err != nil {
return err
}
maxBuffers := supported.Limits.MaxVertexBuffers
// After (v0.5.0) — value return, no error, no wrapper
limits := adapter.Limits()
maxBuffers := limits.MaxVertexBuffersSub-layout fields (Buffer, Sampler, Texture, StorageTexture) are now pointers. A nil pointer means "not this binding type". These types are gputypes aliases for cross-project compatibility.
// Before (v0.4.x) — value types in sub-layouts
entries := []wgpu.BindGroupLayoutEntry{
{
Binding: 0,
Visibility: wgpu.ShaderStageVertex,
Buffer: wgpu.BufferBindingLayout{
Type: wgpu.BufferBindingTypeUniform,
},
},
}
// After (v0.5.0) — pointer sub-layouts; nil = "not this type"
entries := []wgpu.BindGroupLayoutEntry{
{
Binding: 0,
Visibility: wgpu.ShaderStageVertex,
Buffer: &wgpu.BufferBindingLayout{
Type: wgpu.BufferBindingTypeUniform,
},
},
}MaxAnisotropy is renamed to Anisotropy. The old name is kept as a deprecated alias.
// Before (v0.4.x)
sampler, err := device.CreateSampler(&wgpu.SamplerDescriptor{
MaxAnisotropy: 1,
})
// After (v0.5.0)
sampler, err := device.CreateSampler(&wgpu.SamplerDescriptor{
Anisotropy: 1,
})// Before (v0.4.x)
surface.Configure(&config)
// After (v0.5.0) — device is separate first argument, returns error
if err := surface.Configure(device, &config); err != nil {
return err
}// Before (v0.4.x)
tex, err := surface.GetCurrentTexture()
// After (v0.5.0) — added suboptimal bool
tex, suboptimal, err := surface.GetCurrentTexture()
if err != nil {
return err
}
if suboptimal {
// Consider reconfiguring the surface
}// Before (v0.4.x)
if err := surface.Present(); err != nil {
return err
}
// After (v0.5.0) — takes the texture returned by GetCurrentTexture
if err := surface.Present(tex); err != nil {
return err
}SupportedLimits wrapper struct is removed. Limits is now returned directly.
// Before (v0.4.x)
supported, err := adapter.GetLimits()
maxBuffers := supported.Limits.MaxVertexBuffers
// After (v0.5.0)
limits, err := adapter.Limits()
maxBuffers := limits.MaxVertexBuffersChainedStructOut is aliased to ChainedStruct (v29 unified them). If your code references ChainedStructOut, replace with ChainedStruct.
InstanceCapabilities struct is removed. Use GetInstanceFeatures() if you need instance-level feature queries.
Status values simplified. SurfaceGetCurrentTextureStatusOutOfMemory and SurfaceGetCurrentTextureStatusDeviceLost are removed. Check WGPUError from the error return of CreateTexture instead.
InstanceFlag_Default semantic changed in v29. Use explicit flags:
// Before (v0.4.x)
desc := wgpu.InstanceDescriptor{Flags: wgpu.InstanceFlagDefault}
// After (v0.5.0)
desc := wgpu.InstanceDescriptor{Flags: wgpu.InstanceFlagNone}
// or with validation:
desc := wgpu.InstanceDescriptor{Flags: wgpu.InstanceFlagDebugging}InstanceBackendDX11 is removed from InstanceBackend flags. wgpu-native v29 uses D3D12 on Windows.
After updating to v0.5.0:
- Download wgpu-native v29.0.0.0 for your platform
- Update Go module:
go get github.com/go-webgpu/webgpu@v0.5.0 - Add
errreturn handling to allCreate*calls - Replace
GetQueue()→Queue(),GetLimits()→Limits(),GetInfo()→Info() - Replace
GetSize()→Size()on Buffer - Replace
GetWidth()/GetHeight()→Width()/Height()on Texture - Remove separate
gputypesimport if no longer needed - Replace
supported.Limits.X→limits.X(SupportedLimits removed, Limits() value return) - Update
Adapter.Limits()/Device.Limits()calls: remove error handling (returns value now) - Replace
buffer.MapAsync(device, mode, offset, size)withbuffer.Map(ctx, mode, offset, size)(blocking) orbuffer.MapAsync(mode, offset, size)(non-blocking) - Replace
unsafe.PointerfromGetMappedRangewithbuffer.MappedRange(offset, size)→.Bytes() - Update
Queue.Submitcallers: now returns(uint64, error)instead oferror - Update
BindGroupLayoutEntry: sub-layout fields now pointers (Buffer: &wgpu.BufferBindingLayout{...}) - Rename
SamplerDescriptor.MaxAnisotropy→Anisotropy - Update
surface.Configure(&config)→surface.Configure(device, &config) - Update
surface.GetCurrentTexture()callers: now returns(*SurfaceTexture, bool, error) - Update
surface.Present()→surface.Present(tex)(pass texture returned by GetCurrentTexture) - Replace
ChainedStructOut→ChainedStruct - Remove any reference to
InstanceBackendDX11 - Run
go build ./...and fix remaining compilation errors