Skip to content

metal: match pipeline attachment formats to the view#635

Open
benface wants to merge 1 commit into
not-fl3:masterfrom
benface:metal-pipeline-attachments
Open

metal: match pipeline attachment formats to the view#635
benface wants to merge 1 commit into
not-fl3:masterfrom
benface:metal-pipeline-attachments

Conversation

@benface

@benface benface commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Problem

The Metal backend unconditionally configures every render pipeline state for two color attachments (for i in 0..2) plus depth + stencil at Depth32Float_Stencil8. MTKView by default exposes only color attachment 0 and depthStencilPixelFormat = MTLPixelFormatInvalid. With Metal validation on, the first draw asserts:

-[MTLDebugRenderCommandEncoder setRenderPipelineState:]:1654: failed assertion `Set Render Pipeline State Validation
For color attachment 1, the renderPipelineState pixelFormat must be MTLPixelFormatInvalid, as no texture is set.
For depth attachment, the renderPipelineState pixelFormat must be MTLPixelFormatInvalid, as no texture is set.
For stencil attachment, the renderPipelineState pixelFormat must be MTLPixelFormatInvalid, as no texture is set.

Hit this trying to switch a 2D macroquad app to the Metal backend on an iPhone 17 simulator (iOS 27 beta).

Fix

Two changes in graphics/metal.rs::new_pipeline:

  1. Loop only over color attachment 0 (for i in 0..1) — miniquad's Metal backend doesn't expose multiple render targets, so attachment 1 should remain Invalid.
  2. Read the view's depthStencilPixelFormat and pass it through to the pipeline's depth + stencil attachment formats — MTLPixelFormatInvalid when MTKView has no depth/stencil, which is the default.

After this, the pipeline state's attachment formats match whatever the encoder actually has bound, and Metal validation accepts every draw.

Tested on

iPhone 17 simulator on iOS 27 beta — Metal validation crash gone, app launches and renders into the simulator.

@not-fl3

not-fl3 commented Jun 15, 2026

Copy link
Copy Markdown
Owner

While it does make sense that the view surface doesn't have stencil and the depth, setting the format into MTLPixelFormatInvalid feels wrong to me.

Maybe we can just remove setDepthAttachmentPixelFormat and setStencilAttachmentPixelFormat calls for MTKView?

The Metal backend unconditionally configured every render pipeline
state for two color attachments (`for i in 0..2`) plus depth and
stencil at `Depth32Float_Stencil8`, while MTKView by default exposes
only color attachment 0 and `depthStencilPixelFormat = Invalid`. Metal
validation fires on the first draw:

    failed assertion `Set Render Pipeline State Validation
    For color attachment 1, the renderPipelineState pixelFormat must
    be MTLPixelFormatInvalid, as no texture is set.
    For depth attachment, the renderPipelineState pixelFormat must be
    MTLPixelFormatInvalid, as no texture is set.
    For stencil attachment, the renderPipelineState pixelFormat must
    be MTLPixelFormatInvalid, as no texture is set.

Configure only color attachment 0 (the backend has no MRT path) and
mirror the view's `depthStencilPixelFormat` onto the pipeline's depth
+ stencil formats — but only when the view actually has one. When
MTKView reports `Invalid`, skip the `set*AttachmentPixelFormat:` calls
so the descriptor keeps its `Invalid` defaults instead of having that
sentinel passed in explicitly.

Adds `MTLPixelFormat::Invalid = 0` to the binding (Apple's `MTLPixelFormatInvalid`).
@benface

benface commented Jun 15, 2026

Copy link
Copy Markdown
Contributor Author

Good catch — pushed a v2: instead of passing Invalid explicitly, the new code skips the setDepthAttachmentPixelFormat: / setStencilAttachmentPixelFormat: calls entirely when the view reports Invalid (Metal's default for the descriptor is already Invalid, so this lands at the same place without the sentinel smell). When the view does have a real depth/stencil format, the pipeline mirrors it as before. 🙏

@benface benface force-pushed the metal-pipeline-attachments branch from 7ea7ce8 to c251bbb Compare June 15, 2026 22:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants