Fix FB-passthrough wallpaper upside-down with MSAA > 1#183
Merged
Conversation
port_capture_register_fb_for_subrect's MSAA branch sourced the blit from mGameFbMsaaResolved, which the interpreter creates with opengl_invertY=false (see interpreter.cpp UpdateFramebufferParameters for mGameFbMsaaResolved). The internal snapshot FB is invertY=true. CopyFramebuffer sees the invertY mismatch and applies a Y-swap during the blit, leaving the snapshot's storage row 0 holding game-bottom instead of game-top. Effect on consumers: - 1P stage-clear wallpaper (sc1pstageclear.c, top-down v0<v1 stripes): every stripe samples the wrong slice and renders upside-down. - VS results photo wipe (lbtransition.c, bottom-up v0>v1 mesh): the mesh's bottom-up authoring happens to cancel the unwanted Y-flip so the photo lands right-side-up by accident. This is the actual root cause of "1P upside-down on Linux/OpenGL" that was misdiagnosed as a GL_TEXTURE_2D vendor quirk in commit 76cda34 / libultraship 423d7a37. The May 11 doc's truth table was correct for MSAA=1 (both right-side-up with V-flip OFF) but the diagnosis ran on MSAA>1, observed 1P upside-down, and chased the wrong axis. v0.9-beta ships with V-flip OFF + MSAA path = upside-down 1P, which is what Linux users reported. Fix: source the blit from mGameFb directly. mGameFb is invertY=true (matches snap_fb) so CopyFramebuffer does a 1:1 row copy with no hidden Y-flip. When MSAA > 1, mGameFb is multi-sampled — that's fine because glBlitFramebuffer resolves MSAA→non-MSAA implicitly during an unscaled blit when dimensions match (per OpenGL spec). The previous two-step (resolve to mGameFbMsaaResolved, then blit) was unnecessary. The legacy ViewportMatchesRendererResolution+MSAA bailout is also removed: it existed because mGameFbMsaaResolved goes stale in that viewport configuration (end-of-frame resolve targets FB 0 instead). mGameFb itself is always populated mid-frame, so it's a valid blit source regardless of viewport. Tested on Linux/Fedora 43 + NVIDIA 595.58.03: - MSAA=1, 1P stage clear: right-side-up (unchanged). - MSAA=4, 1P stage clear: right-side-up (was upside-down). - MSAA=1, VS results photo wipe: right-side-up (unchanged). - MSAA=4, VS results photo wipe: right-side-up (was right-side-up by accident; now right-side-up for the right reason). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
JRickey
added a commit
that referenced
this pull request
May 15, 2026
Resolves PR #182 conflicts after main reverted #179 and merged #181 + #183 ahead of this branch: - decomp: cherry-picked PR #181's scene_curr fix (fddd2d3d5) onto stability-fixes' tip (4015e25e -> f9d608f11) so the merged tree has both the per-slot generational token + DObjDesc PortRefGfx work AND the C-Stick / D-Pad input gate fix. - port/bridge/framebuffer_capture.cpp: kept main's PR #183 MSAA fix (the variant 6 / container-smash work doesn't touch this). - port/port.cpp, port/port_dl_ranges.{cpp,h}, port/port_watchdog.cpp, port/resource/RelocPointerTable.{cpp,h}, port/bridge/lbreloc_bridge.cpp: restored stability-fixes' versions (re-applies the #179 infrastructure that variant 6a/6b builds on). - libultraship: kept stability-fixes' 7f673a5f (already 3 commits ahead of main's c16c03f0 with the GFX walker hooks). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
port_capture_register_fb_for_subrect, not a GL_TEXTURE_2D sampling-direction quirk as commit 76cda34 had concluded.mGameFbMsaaResolved(which the interpreter creates withopengl_invertY=false), while the internal snapshot FB isinvertY=true.CopyFramebuffer's invertY-mismatch path applied an unwanted Y-swap duringglBlitFramebuffer, leaving the snapshot's storage row 0 holding game-bottom instead of game-top.v0<v1stripes) ended up upside-down on screen; VS results photo wipe (bottom-upv0>v1mesh) coincidentally cancelled the same flip and looked right-side-up. That's why "1P upside-down, VS rightside-up" was the consistent v0.9-beta+MSAA>1 report.Fix
Always source the blit from
mGameFb:mGameFbisinvertY=true, matchingsnap_fb→CopyFramebufferdoes a clean 1:1 row copy.glBlitFramebufferperforms the MSAA→non-MSAA resolve implicitly during an unscaled blit with matching dimensions (OpenGL spec). The previous two-step "resolve tomGameFbMsaaResolved, then blit" was unnecessary.ViewportMatchesRendererResolution + MSAAbailout (return -4) is also removed: that case existed becausemGameFbMsaaResolvedcould be stale (end-of-frame resolve targets FB 0 instead).mGameFbitself is always populated mid-frame, so it's a valid blit source regardless of viewport.Why 76cda34's diagnosis missed this
The May 11 doc's truth table (
1P right-side-up + VS right-side-up = V-flip OFF correct) was correct for MSAA=1, which is what the doc author tested. With MSAA>1 (the failing config every Linux/OpenGL user actually saw in v0.9-beta), the truth table doesn't apply because the asymmetry isn't inFbNeedsSampleVFlip— it's inCopyFramebuffer's metadata-mismatch handling.The 76cda34 commit is not reverted here. Its premise (V-flip OFF is correct on Linux/OpenGL) holds. This PR fixes the actual MSAA bug that was masking that correctness.
Test plan
CopyFramebufferhas its own MSAA-source handling; the fix routes throughinterp->mRapi->CopyFramebufferso it should be transparent, but worth a quick check)Tested locally on Linux/Fedora 43 + NVIDIA 595.58.03.
🤖 Generated with Claude Code