gogpu/naga v0.21.0 was published on 2 November 2026. It is described as the last planned breaking release before v1.0 (ADR-010): one public API in the shape of Rust naga, with safe zero values.
The full release notes and downloads are on the GitHub release page. This is a stable release, not a prerelease. The notes point to apidiff against v0.20.5 for the complete list of API changes. Only part of the notes is covered here, and the notes text was cut off before the end.
One entry point per stage ¶
Parsing, validation and code generation now follow the same call shape. Most of the old names are gone, so expect compile errors on upgrade.
- Parsing:
wgsl.Parse(src, wgsl.ParseOptions{})returns*ir.Module,wgsl.ParseInfoand an error. Errors are*wgsl.ParseErrorwithFormatandLocation. This replacesnaga.Parseplusnaga.Lower. - Validation:
valid.Validate(m, valid.Options{...})returns avalid.ModuleInfo. A zeroOptionsmeans no optional capability. Capabilities and error types moved fromirtovalid. - Backends: every backend exposes
Compile(*ir.Module, Options) (out, TranslationInfo, error). For SPIRV that isspirv.Compile(m, spirv.Options{}).DefaultOptions()is now just the zeroOptionsin every backend. - Overrides:
naga.ProcessOverridestakes theModuleInfofrom yourvalid.Validatecall and returns a new one.
Entry point selection is unified as *backend.EntryPointSelector{Stage, Name}, used in each backend’s Options.EntryPoint and in OverrideOptions. Many ir helpers and most SPIRV and HLSL builder internals are removed or made internal. If you wrapped those, plan for rewrites rather than renames.
Safety switches are on at the zero value ¶
This is the change most likely to alter output without a compile error. The project now matches Rust naga and wgpu-hal defaults.
- Workgroup zero init is one option,
ZeroInitializeWorkgroupMemory backend.ZeroInitializeWorkgroupMemoryMode, inspirv,msl,hlsl,glslanddxil(P1-API-002). The zero value isZeroInitWorkgroupPolyfill, which stores zero from generated code.ZeroInitWorkgroupNativeis SPIRV only and an error elsewhere.ZeroInitWorkgroupNoneleaves memory as is. The oldmslandhlslbools defaulted to skipping the zeroing that WebGPU requires. ForceLoopBoundingbecomesSkipLoopBounding. SPIRVRayQueryInitTrackingbecomesSkipRayQueryInitTracking. AnOptionsliteral that leftForceLoopBoundingunset now bounds loops.spirv.UseStorageInputOutput16stays opt in, because it needs device support.- Bounds checks use
backend.BoundsCheckPolicies, where zero meansRestrict.
The tradeoff is plain. Zero value callers get safer output and may see slightly slower shaders. Callers who want the old behavior must opt out explicitly.
Missing bindings and unsupported versions are errors ¶
Two cases that used to be silently patched now fail.
A nil binding map is still the identity mapping. A non nil map, even an empty one, must list every resource. Otherwise compile fails with an error wrapping backend.ErrMissingBinding, unless FakeMissingBindings is set. Per backend details from the notes:
- SPIRV:
RequireBindingsis replaced byFakeMissingBindings. Before, a missing entry was silently kept at its WGSL binding. - MSL: a non nil
PerEntryPointMapmust cover every entry point that uses resources. Entry points left out used to get automatic slots. - GLSL: on versions with explicit bindings (desktop 4.20, ES 3.10) a missing resource was written without a binding and landed on the driver’s binding 0.
- HLSL: a resource missing from a non nil map used to land at
register(0, space0). A nilSamplerBufferBindingMapnow places group G’s index buffer atregister(tG, space255). Atexture_externalwithout anExternalTextureBindingMapentry is an error.
Target versions are no longer raised for you. A request the target cannot satisfy returns *backend.VersionError{Space, Feature, Required, Requested}, which matches errors.Is(err, backend.ErrUnsupported). Pass the device’s real version.
Readback corpus changes ¶
The test side changed too, and it is mostly of interest to people running the corpus. A new case, calls/dce-live-local-chain-rt, covers the shape where naga 0.20.4’s DXIL output dropped blend math for two of three modes. It wrote zeros and the validator accepted it. That was fixed in 0.20.5. Corpus format 2 adds "skip": true for known failures such as GPU hangs or device loss. Format 1 cases still read.
Upgrade notes ¶
- Run
apidiffagainst v0.20.5 first and work through the compile errors. - Audit every
Optionsliteral. Fields that flipped polarity compile cleanly and change behavior. - Audit non nil binding maps. Any map that omitted resources will now fail unless you set
FakeMissingBindings. - Replace
ir.SpacePushConstant(var<push_constant>) withir.SpaceImmediate(var<immediate>). Later address space values shift by one, so do not persist the numeric values. - Use
naga.Compact(m, naga.KeepUnusedYes)ornaga.KeepUnusedNoin place of their.Compact*family.
Where to get it ¶
- Release page: https://github.com/gogpu/naga/releases/tag/v0.21.0
- Repository: https://github.com/gogpu/naga
- Tag:
v0.21.0