Skip to content

metal: render-target color textures must use the view's pixel format#639

Open
benface wants to merge 1 commit into
not-fl3:masterfrom
benface:metal-render-target-pixel-format
Open

metal: render-target color textures must use the view's pixel format#639
benface wants to merge 1 commit into
not-fl3:masterfrom
benface:metal-render-target-pixel-format

Conversation

@benface

@benface benface commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

new_pipeline builds each pipeline's color attachment with the view's colorPixelFormat, so Metal pipelines effectively bake in that format at creation time. Color render textures created via new_render_texture were following the requested TextureFormat instead (e.g. RGBA8RGBA8Unorm). The instant such a target was bound to that pipeline, Metal validation tripped:

For color attachment 0, the render pipeline's pixelFormat (MTLPixelFormatBGRA8Unorm) does not match the framebuffer's pixelFormat (MTLPixelFormatRGBA8Unorm).

MTKView's allowed presentable formats are all BGRA* (or RGBA16Float) — RGBA8Unorm isn't among them — so honoring TextureFormat::RGBA8 literally for color render targets silently breaks every offscreen color attachment.

Use the view's actual colorPixelFormat for color render-target textures so they round-trip through the pipeline without a format mismatch. Sampling them in a shader is unaffected: Metal's hardware swizzle returns RGBA semantics regardless of memory order.

Caught while wiring up macroquad's render_target() on the iPhone 17 simulator running iOS 27.

`new_pipeline` builds each pipeline's color attachment with the view's
`colorPixelFormat`, so Metal pipelines effectively bake in that format
at creation time. Color render textures created via
`new_render_texture` were following the requested `TextureFormat`
instead (e.g. `RGBA8` → `RGBA8Unorm`). The instant such a target was
bound to the pipeline, Metal validation tripped:

    For color attachment 0, the render pipeline's pixelFormat
    (MTLPixelFormatBGRA8Unorm) does not match the framebuffer's
    pixelFormat (MTLPixelFormatRGBA8Unorm).

MTKView's allowed presentable formats are all `BGRA*` (or
`RGBA16Float`) — `RGBA8Unorm` isn't among them — so honoring
`TextureFormat::RGBA8` literally for color render targets silently
breaks every offscreen color attachment. Use the view's actual
`colorPixelFormat` for those textures so they round-trip through the
pipeline without a format mismatch. Sampling them in a shader is
unaffected: Metal's hardware swizzle returns RGBA semantics regardless
of memory order.
@benface benface force-pushed the metal-render-target-pixel-format branch from 08402f2 to fd253ce Compare June 13, 2026 15:32
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.

1 participant