Repository navigation
MSAA fixes by Claude - #22472
Merged
Merged
MSAA fixes by Claude#22472
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
BlitFramebuffer drew depth with a raster copy. With MSAA that reads the single-sampled depth, which is never resolved: Silent Hill: Origins resizes its light buffer mid-frame, and with garbage depth its depth-EQUAL light passes drew nothing, so the flashlight was missing. The raster copy isn't exact without MSAA either: Burnout Dominator's recursive rendering (#11100) goes from 112k to 6k pixels off the PSP with a copy. Now depth is copied wherever the backend can copy just part of it (Vulkan). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With MSAA, a pixel that a primitive only partly covers otherwise extrapolates them to the pixel center, outside the primitive, and samples textures outside its UV range. Without MSAA nothing changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…st sample With MSAA, a framebuffer textured as CLUT indices was read resolved, so the indices along edges were averages of the samples and looked up wrong colors. Dragon Ball Z: Tenkaichi Tag Team draws its outlines from a CLUT32 lookup of its framebuffer, and they came out noisy and miscolored. Copy each pixel's first sample with texelFetch into a temporary buffer and look up that. This needs the multisampled color images to be sampled, and transitioned back to attachment layout before rendering to them again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ShiftDepthForOffsetRendering copied through a single-sampled temp buffer, so with MSAA CopyDepthRect fell back to a depth blit, which Vulkan can't do with multisampled images (PerformBlit asserts). Give the temp buffer the same samples and copy; multisampled depth is never blitted or drawn. Co-Authored-By: Claude Opus 5.5 <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.
Had it sweep the full set of framedumps and fix any MSAA issues it found.
This is all Vulkan-only, because currently only Vulkan supports MSAA.
Claude says
This PR fixes MSAA rendering bugs on Vulkan, found by rendering all the frame dumps with 4x MSAA and comparing against no MSAA. One of the fixes also helps without MSAA. MSAA is Vulkan-only, so the other backends are unaffected, apart from depth copies (see below).
Changes
--msaa=Nfor headless (0 = off, 1 = 2x, 2 = 4x, 3 = 8x), throughCommandLineOptions.Copy depth instead of drawing it.
BlitFramebuffermoved depth with a raster draw.framebufferSeparateDepthCopySupported, so Vulkan).Centroid interpolation for texture coordinates and smooth-shaded colors on Vulkan. Without it, pixels a primitive only partly covers extrapolate their UVs and sample outside the primitive's texture region. Without MSAA it makes no difference.
CLUT lookups of multisampled framebuffers read one sample. A framebuffer used as CLUT indices was read resolved, so along edges the indices were averages and looked up the wrong colors. Dragon Ball Z: Tenkaichi Tag Team draws its outlines from a CLUT32 lookup of the frame, and they came out noisy and miscolored. Now each pixel's first sample is copied into a temporary buffer with
texelFetch, and the lookup reads that. This adds:BindFramebufferSamplesAsTextureand aframebufferSampleReadSupportedcapability in thin3d;SamplerFlags::MULTISAMPLE;DRAW2D_COPY_COLOR_SAMPLE0Draw2D pipeline.A color-grade CLUT loses its edge anti-aliasing this way, which is why a few dumps get slightly worse. Exempting smooth ramps was worse overall, because the ramp detector misses some of them.
Frame dumps vs PSP
972 dumps with PSP references, Vulkan, total pixels differing from the PSP:
Without MSAA only the depth copy changes anything: 7 dumps improve and none get worse.
With 4x MSAA:
All 999 dumps render with MSAA without errors.
What's left with MSAA is expected anti-aliasing: geometry edges, and full-screen quads that stop a fraction of a pixel short of the screen edge (Metal Slug XX).
Unit tests and
test.py -g --graphics=softwarepass.🤖 Generated with Claude Code