Skip to content

vulkan: work around Arm drivers ignoring negative viewport heights - #10058

Open
lexoliu wants to merge 1 commit into
gfx-rs:trunkfrom
lexoliu:mali-negative-viewport-trunk
Open

vulkan: work around Arm drivers ignoring negative viewport heights#10058
lexoliu wants to merge 1 commit into
gfx-rs:trunkfrom
lexoliu:mali-negative-viewport-trunk

Conversation

@lexoliu

@lexoliu lexoliu commented Aug 13, 2026

Copy link
Copy Markdown

Fixes #10057.

The Arm proprietary driver on a Pixel 9 Pro (Mali-G715, r54p2, Android 16) rasterizes as if the viewport height were positive even when the standard maintenance1-style negative-height viewport is submitted, so every render pass comes out vertically flipped. The submitted values were captured on the device from begin_render_pass (x=0 y=1935 w=960 h=-1935), the flip reproduces when replaying the same pipeline into an offscreen texture with presentation out of the picture, and re-issuing the viewport after the pipeline bind changes nothing, which rules out lost dynamic state. Details in the issue.

This adds Workarounds::IGNORED_NEGATIVE_VIEWPORT_HEIGHT, set for VK_DRIVER_ID_ARM_PROPRIETARY. When active:

  • naga gets ADJUST_COORDINATE_SPACE, so the Y flip moves into the vertex shader epilogue;
  • begin_render_pass and set_viewport submit positive-height viewports;
  • the pipeline's front-face winding is inverted and stencil face state swapped, since the shader-side flip inverts triangle winding.

Frag coord, scissor, and derivative semantics are unaffected: the geometry lands on the same framebuffer rows as under a honored negative viewport, so framebuffer-space values match. SPIR-V passthrough shaders would bypass the naga flip, which is a reason to keep this gated to the broken driver rather than making it the default path.

Verified on the device: previously-flipped content renders upright, culling unchanged, and the rest of the app (compute-produced textures, presentation) behaves as before. Desktop backends are untouched. I have the device on adb and can test revisions of this change.

Arm's proprietary driver (observed on r54p2, Mali-G715, Pixel 9 Pro,
Android 16) rasterizes as if the viewport height were positive even when
a negative-height viewport is submitted, so every render pass comes out
vertically flipped. The driver receives the standard maintenance1-style
viewport (y = height, height = -height); capturing the submitted values
confirms wgpu's side is correct, and replaying the same pipeline into an
offscreen texture reproduces the flip without presentation involved.

On that driver, flip Y in the vertex shader epilogue via naga's
ADJUST_COORDINATE_SPACE, submit positive-height viewports, and invert
the front-face winding (and stencil face state) to compensate.
Copilot AI lite review requested due to automatic review settings August 13, 2026 08:22

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a Vulkan backend workaround for Arm proprietary drivers that ignore negative viewport heights, causing vertically flipped render passes. It introduces a driver-gated path that moves the Y flip into shader generation and adjusts pipeline state to preserve expected rasterization behavior.

Changes:

  • Add a new Vulkan Workarounds::IGNORED_NEGATIVE_VIEWPORT_HEIGHT flag and enable it for VK_DRIVER_ID_ARM_PROPRIETARY.
  • When enabled, compile shaders with Naga spv::WriterFlags::ADJUST_COORDINATE_SPACE, submit positive-height viewports, and adjust pipeline rasterization state (front-face inversion).
  • Document the user-visible behavior change in CHANGELOG.md.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
wgpu-hal/src/vulkan/mod.rs Introduces a new Vulkan workaround bitflag with rationale.
wgpu-hal/src/vulkan/device.rs Adjusts pipeline state under the workaround (front-face and stencil facing).
wgpu-hal/src/vulkan/command.rs Switches render-pass and dynamic viewport submission to positive-height viewports under the workaround.
wgpu-hal/src/vulkan/adapter.rs Enables the workaround by driver ID and toggles Naga SPIR-V writer coordinate adjustment.
CHANGELOG.md Notes the Vulkan behavior change for affected Arm proprietary drivers.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines 2080 to +2087
let s = &ds.stencil;
let front = conv::map_stencil_face(&s.front, s.read_mask, s.write_mask);
let back = conv::map_stencil_face(&s.back, s.read_mask, s.write_mask);
let (front, back) = if flip_winding {
(back, front)
} else {
(front, back)
};
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.

Arm proprietary driver ignores negative viewport height, flipping every render pass (Mali-G715 r54p2, Pixel 9 Pro)

2 participants