Releases: gogpu/wgpu
Release list
v0.30.30 — memory leak fix: validation maps pinned resources per frame
Fixed
-
Memory leak: validation maps pinned every resource per frame —
SetBindGroupcopied every bound buffer/texture into encoder maps per draw call. Maps never cleared after Submit/Release, pinning BindGroup objects indefinitely. Now tracks bind groups only; validation walksboundBuffers/boundTexturestransitively. Contributor: @samyfodil (#291) -
Validation error precedence — buffer/texture errors now deterministically beat bind group errors regardless of map iteration order. Matches Rust wgpu ordering.
v0.30.29 — hotfix: Queue.LastSubmissionIndex deadlock (atomic)
Hotfix for v0.30.28 deadlock: Submit→Triage→onZero→LastSubmissionIndex→Queue.mu. Changed lastSubmissionIndex from mutex-protected uint64 to atomic.Uint64.
v0.30.28 — unified resource lifecycle (ADR-056, Rust wgpu parity)
Fixed
-
Resource lifecycle: BindGroup/Pipeline Release() bypasses ref-counting —
Release()calleddq.Defer(lastSubmissionIndex)directly, ignoring the
ResourceRefref-counting system. On shared encoder path, this caused
use-after-free: HAL resource destroyed while GPU still processing commands.
NowRelease()callsref.Drop()— HAL destruction deferred until ALL
refs (user + GPU) are dropped. Matches Rust wgpuArc<BindGroup>pattern.
Applied to: BindGroup, RenderPipeline, ComputePipeline. (#287) -
DestroyQueue deadlock: Triage → onZero → Defer re-entry —
Triage()held mutex while executing callbacks. WhenonZerofired and
calledDefer(), it tried to acquire the same mutex → deadlock. Now
callbacks execute outside the lock. Same fix applied toFlushAll().
Tests
- 6 new lifecycle tests: refcount transitions, Release-before-Submit,
Release-without-Clone, mixed-resource TrackedSubmission, buffer binding scenario
v0.30.27 — GLES 3D rendering: MappedAtCreation flush + depth fixes
Fixed
-
GLES: MappedAtCreation buffer data silently discarded on Unmap —
UnmapBufferonly flushed shadow data to GL whenBufferUsageMapWritewas set.
Per WebGPU spec,MappedAtCreationdoes NOT requireMapWriteusage. Buffers
withUniform|CopyDst+MappedAtCreation(the standard g3d pattern) had their
data thrown away — zero MVP matrices, zero vertices, zero indices. Root cause of
invisible 3D geometry on GLES. (#284) -
GLES: depth/stencil attachment point chosen by format —
GL_DEPTH_ATTACHMENTfor depth-only formats,GL_DEPTH_STENCIL_ATTACHMENTfor
combined. Wrong attachment point caused FBO incomplete (0x506). Rust wgpu-hal
parity (command.rs:577-580). (#284) -
GLES: depth clear masked by stale pipeline state —
ClearDepthCommandnow
callsglDepthMask(true)+glClearDepth(value)beforeglClear. Prevents
staleDepthMask(false)from prior pipeline silently masking depth clear. (#284) -
GLES: viewport depth range ignored —
SetViewportCommandnow calls
glDepthRange(minDepth, maxDepth). Was ignoring depth range fields entirely.
Rust wgpu-hal parity (queue.rs:1295-1296). (#284)
Added
gl.Context.ClearDepth()andgl.Context.DepthRange()wrapper methods for
both Windows (syscall, double) and Linux (goffi, float32 for GLES).
Changed
- deps: gpucontext v0.22.0 → v0.23.0
v0.30.26 — GLES depth/stencil fix for surface render pass
Fixed
- GLES: depth/stencil not attached to swapchain FBO on surface render pass —
setupSurfaceTarget()had an early return that skipped depth/stencil attachment.
3D content with depth testing was invisible on GLES while Vulkan and DX12 worked
correctly. Now attaches depth/stencil to the swapchain FBO via
AttachDepthStencilToFBOCommand. Matches Rust wgpu-hal GLESbegin_render_pass
which uses the same draw_fbo path for both surface and offscreen targets. (#284)
Changed
- deps: gpucontext v0.22.0 → v0.23.0
v0.30.25 — deps gpucontext v0.22.0
[0.30.25] - 2026-07-29
Changed
- deps: gpucontext v0.21.1 → v0.22.0 —
FontSmoothingtype + coordinate space docs (gogpu#396, gogpu#398)
v0.30.24 — Surface API contract + Metal -race fix
Fixed
-
Browser/Rust Surface missing methods —
PresentPixels,WritePixels,
SetPrepareFrame, andSetPresentsWithTransactionnow exist on all backends.
Missing methods return clear errors or no-op, matching ADR-047 (unified public
API). Fixes WASM build failure introduced by gogpu PR #370. (#281) -
Metal checkptr abort under
-race— ObjC block callback trampolines used
unsafe.Pointer(blockPtr + 32)which violates Go's pointer provenance rules.
Replaced withunsafe.Add(unsafe.Pointer(blockPtr), 32)(Go 1.17+) at all 4
block callback locations.go test -racenow works on Metal compute. (#280)
Added
-
Compile-time Surface API contract — anonymous interface assertion
(var _ interface{...} = (*Surface)(nil)) in each backend file enforces that
all public methods exist at compile time (ADR-047 enforcement). -
CI cross-compile job —
GOOS=js GOARCH=wasm(browser) and-tags=rust
(Rust FFI) builds added to CI pipeline. Missing Surface methods now fail the
PR, not the downstream consumer.
CI
- Android SDK setup: use pre-installed SDK instead of third-party action (v3/v4 both crash on Preview license)
- goffi version check updated v0.6.1 → v0.6.2 in Android preview script
- DX12 command.go formatting fixed
v0.30.23
What's Changed
Fixed
- Device teardown GPU drain ordering —
Device.Release()drains GPU work before destroying staging buffers. Matches Rust wgpuQueue::Drop. (@besmpl #264) - Vulkan swapchain fail-closed lifecycle — transactional reconfiguration, capability validation, broken-state tracking. (@besmpl #265)
- Explicit mock adapter construction —
core.NewInstanceno longer fabricates mock adapter. Rust wgpu parity. (@besmpl #266) - Surface lifetime ownership — centralized acquisition/teardown with lease system, deterministic release ordering. (@besmpl #269)
- Vulkan nil pipeline layout guard — HAL rejects nil layouts before Vulkan call. (@besmpl #257)
- Metal autorelease pool thread pinning —
LockOSThreadprevents goroutine migration. Go 1.14+ preemption fix. (@besmpl #260) - Metal texture array copy shape —
setArrayLengthfor 1D/2D arrays instead ofsetDepth. Rust parity. (@besmpl #261) - DX12 submission-ordered state reconciliation — command-local tracking, preamble barriers, depth/stencil planes. (@besmpl #262)
- nil WritePixels receiver —
Surface.WritePixelson nil surface returnsErrReleased. (@besmpl #277) - Metal storage-mode test fixture — aligned with
isAppleGPUpolicy from v0.30.22. (@besmpl #275)
Added
- Surface-qualified adapter selection —
RequestAdapterWithSurfaceviavkGetPhysicalDeviceSurfaceSupportKHR. Ahead of Rust wgpu. (@besmpl #267) - Typed surface targets (Rust v29 parity) —
CreateSurfaceFromTarget,CreateSurfaceUnsafewith opaque constructors. (@besmpl #273) - Android arm64 Vulkan (guarded preview) — API 29+, Bionic loader via goffi v0.6.1. (@besmpl #268)
- Fixed-count indirect multi-draw —
MultiDrawIndirect/MultiDrawIndexedIndirectwith overflow-safe arithmetic. 2 improvements over Rust wgpu. (@besmpl #253) - Metal ICB optimization — indirect command buffers for large indexed multi-draws. Original optimization beyond Rust. (@besmpl #263)
- Headless surface readback —
HeadlessSurfaceTarget+Surface.ReadPixels()for golden image testing. (@besmpl #276)
Changed
- Bump naga v0.17.15 → v0.17.16 — MSL 64-bit atomics rejection (@besmpl)
- Bump goffi v0.6.1 → v0.6.2 — Windows AMD64 float returns fix (@besmpl)
- Bump webgpu v0.5.3 → v0.5.4 — Android surface, timestamp period, callbacks (@besmpl)
- DX12 lint cleanup — builtin shadow fix, struct returns, dead code removal
- CODEOWNERS — @besmpl added for Android paths
- ROADMAP + ARCHITECTURE — updated for 18 merged PRs
- CONTRIBUTING.md — Smart Coding framework, AI-assisted policy
Full Changelog: v0.30.22...v0.30.23
v0.30.22
What's Changed
Fixed
- Metal MSAA texture storage mode crash on Intel Mac — use
MTLGPUFamilyApple1detection instead ofhasUnifiedMemoryfor texture storage mode selection. Non-Apple GPU family devices (Intel/AMD) now always useMTLStorageModePrivatefor textures. Apple Silicon keepsMTLStorageModeSharedoptimization for single-sample textures. Fixes #271.
Details
Intel integrated GPUs (e.g. Iris Plus 655) report hasUnifiedMemory=true but are NOT Apple GPU family. Metal spec requires MTLStorageModePrivate for multisample textures on non-Apple-family devices. Our previous code used hasUnifiedMemory to select MTLStorageModeShared for all textures, causing SIGABRT on the first frame when creating MSAA render targets.
The fix adds isAppleGPU detection via the existing DeviceSupportsFamily(device, MTLGPUFamilyApple1) infrastructure, which is the correct semantic check for storage mode capability. This preserves our MTLStorageModeShared optimization for single-sample textures on Apple Silicon (better than Rust wgpu-hal, which uses Private for all textures unconditionally).
Thanks to @AnyCPU for the detailed bug report with root cause analysis, patch, and regression test.
Full Changelog: v0.30.21...v0.30.22
v0.30.21
What's Changed
Fixed
-
Software
CopyTextureToBufferrow stride — row-by-row copy respectingBytesPerRowfromBufferLayout. Was flatcopy(dst, src)ignoring row alignment, causing progressive row shift. -
Software
configureRasterPipelineblend state — extract blend state fromFragment.Targets[0].Blendinto the raster pipeline. Was alwaysBlendDisabled, preventing premultiplied alpha compositing. AddedconvertBlendState,convertBlendFactor,convertBlendOp. -
Software
readTexelBGRA format — swap R/B channels forBGRA8Unorm/BGRA8UnormSrgbtextures. Replaced hardcoded format constants withgputypesimports.
Full Changelog: v0.30.20...v0.30.21