wgpu v0.30.4 - Metal Stencil State Fix

   |   3 minute read   |   Using 527 words

wgpu v0.30.4 was published on June 25, 2026, with a focused Metal backend fix for stencil behavior on macOS. The main change is that CreateRenderPipeline now translates StencilFront and StencilBack into MTLDepthStencilState, so stencil tests no longer stay silently inert on the Metal path. For apps using stencil masks, clipped content, or rounded UI panels, this is the fix that changes what users actually see.

The full release notes and downloads are on the GitHub release page.

Metal stencil state now reaches the pipeline

Before this release, the Metal backend kept default stencil behavior when creating a render pipeline. That meant Always compare behavior plus Keep operations, which is a quiet way to disable the stencil test while still looking like the pipeline was configured.

The fix wires the WebGPU face states into MTLDepthStencilState. That includes compare function, stencil fail operation, depth fail operation, pass operation, and the read and write masks for StencilFront and StencilBack.

This matters because the bug did not fail loudly. Vulkan, DX12, and GLES already handled the translation, so a scene could behave correctly on one backend and fail only on macOS. The release notes call out two visible symptoms: rounded UI panels rendered as squares, and clipped or stencil masked content disappearing.

Stencil pixel formats are set explicitly

v0.30.4 also fixes how the Metal render pipeline descriptor handles stencil capable formats. The descriptor now sets stencilAttachmentPixelFormat for Depth24PlusStencil8, Depth32FloatStencil8, and Stencil8.

The release also splits depth and stencil assignment by format. That small detail matters for Stencil8, since a stencil only format should not set depthAttachmentPixelFormat. The notes say this follows the Rust wgpu-hal Metal pattern, which is a useful sign for anyone comparing behavior across implementations.

For users, the practical result is simpler: if a render pass has a stencil attachment, the Metal pipeline now tells Metal about it in the right field. That removes another case where the API level state and the backend descriptor could drift apart.

WebGPU stencil operations map to Metal values

The release adds stencilOperationToMTL, an explicit mapping from WebGPU stencil operations to Metal stencil operations. This is not just cleanup. The notes call out that enum values differ, with WebGPU Invert=4 and Metal Invert=5.

Relying on numeric enum overlap would be brittle here. An explicit conversion function makes the backend behavior easier to audit and harder to break during future edits.

The implementation came through PR #227, which the notes credit for discovering and fixing the Metal stencil state issue and verifying it on Apple Silicon M4.

Small memory management cleanup

There is also a depth and stencil descriptor cleanup. After creating the depth and stencil state, the backend now calls Release(depthStencilDesc).

The reason is simple: descriptor properties are copied into the state object, so the original descriptor can be freed after creation. This is not the headline fix, but it is the sort of backend housekeeping that matters in graphics code that creates pipeline state objects over time.

No breaking changes or migration steps are listed in the notes. Most users should treat v0.30.4 as a focused Metal correctness update.

Where to get it



denis256 at denis256.dev