Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement MSAA support for desktop GPUs in Vulkan #16458

Merged
merged 20 commits into from
Dec 3, 2022

Conversation

hrydgard
Copy link
Owner

@hrydgard hrydgard commented Nov 28, 2022

Partially solves #6218

This is an implementation of MSAA antialiasing, for desktop GPUs only, and Vulkan only for now.

image

There are some glitches (like the sun in Burnout Legends) but it mostly works in a lot of games.

It detects available MSAA modes and even allows runtime switching between them.

(In theory this could work on mobile but would be terribly expensive on tiler GPUs because it "stores back" the MSAA framebuffers to memory, so that it can continue rendering to the same render target when needed. On mobile, we should use STORE_OP = DONT_CARE, but then we also need to do a blit from the resolved buffer to the MSAA framebuffer in order to continue rendering, but that's work for another day.)

Remaining work before merge:

  • Correctly handle blits and copies (copies might need conversion to blits), and any related image layout transitions
    • To be safe, we might have to copy to both the msaa and the normal image of the destination framebuffer... ugh.
    • Now doing correct depth copies Not fully correct yet, but switched to raster copies, which do work, except we lose some sampling resolution.

Postponed quality setting until after merge.

@hrydgard hrydgard added Vulkan GE emulation Backend-independent GPU issues labels Nov 28, 2022
@hrydgard
Copy link
Owner Author

hrydgard commented Nov 28, 2022

Heh, getting the basics up was not so hard, but there's a lot of image layout transition logic in QueueRunner that's kinda bogus or incomplete in multisample mode. All that stuff only works because we don't do copies correctly so never transition away the msaa targets from ATTACHMENT_*_OPTIMAL :)

Doing all copies through raster might be the easy way out... Though, won't be perfect for depth buffers where we'll lose valuable resolution (by texturing from a resolved target, drawing to a multisampled one)

@hrydgard
Copy link
Owner Author

Raster copies fixes all the common cases. We do lose depth resolution which might matter in cases like Jeanne D'Arc, but mostly it works just fine.

I actually think we could get this in pretty soon. Should probably make a configuration option to select how much sample shading we want - right now we enable full per-sample shading only when DISCARD is used in a shader, which smoothes out fences and stuff very nicely.

@hrydgard
Copy link
Owner Author

Hm, there seems to be some shutdown race condition related to shader destruction, not sure why it appeared here. Doesn't always happen.

@hrydgard
Copy link
Owner Author

There's a related race between the pipeline compiler thread and forced recompilation of pipelines with the wrong msaa depth.

Think I'll have to purge the compiled pipelines completely on MSAA level switch somehow to get around this..

@hrydgard hrydgard added this to the v1.14.0 milestone Dec 1, 2022
@hrydgard hrydgard marked this pull request as ready for review December 1, 2022 22:44
@hrydgard
Copy link
Owner Author

hrydgard commented Dec 1, 2022

This seems fairly solid-ish now, and runs validation-clean throughout, switching on and off, and changing MSAA level - although there are things I want to improve (add quality setting, make actual copies work instead of raster copies), everything I throw at it seems to work, and it generally looks absolutely fantastic, at least on GPUs that support sampleRateShading. So even though it's late in the process, would be cool to get in for 1.14.

My reluctance to put multiple MSAA levels into the renderpasstype key resulted in the need for some rather ugly invalidation hacks, but I think it's worth it. There's only one additional renderpass key bit I foresee us ever needing now (#16327), while adding 3 additional more bits to represent the various MSAA levels would start to get to the point where we should switch to hashmaps or something instead of plain arrays, and it's nice to avoid that... I think.

EDIT: Actually I've found two problems:

  • Cars Race-o-Rama doesn't work, not entirely surprising
  • Ratchet & Clank's depth trickery is partially broken (never mind, seems unrelated, but should look into.. can fix by changing MSAA mode)

Hmm..

Common/GPU/Vulkan/VulkanFramebuffer.cpp Outdated Show resolved Hide resolved
caps_.multiSampleLevelsMask = (limits.framebufferColorSampleCounts & limits.framebufferDepthSampleCounts & limits.framebufferStencilSampleCounts);
// Check for depth stencil resolve. Without it, depth textures won't work, and we don't want that mess
// of compatibility reports, so we'll just disable stencil in this case for now.
// There are potential workarounds for devices that don't support it, but those are nearly non-existent now.
Copy link
Collaborator

Choose a reason for hiding this comment

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

*MSAA, not stencil. Also, meant to check resolveProperties, like supportedStencilResolveModes?

-[Unknown]

Copy link
Owner Author

Choose a reason for hiding this comment

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

Oops, yeah.

Not checking resolveModes, we just use "sample0" resolve mode for now which is required to be supported if resolve is supported at all, it's fine. It won't make very much of a difference to use the others, and I think doing average for example could result in artifacts in some casese.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Although just to be safe, I'll throw in a check for that resolve mode.

@iota97
Copy link
Contributor

iota97 commented Dec 2, 2022

This SEGFAULT on Linux, will provide a stack trace when I can :/

@hrydgard
Copy link
Owner Author

hrydgard commented Dec 2, 2022

@iota97 thanks, please do.

Getting this in 1.14 might be ambitious, I may push it to later.

@iota97
Copy link
Contributor

iota97 commented Dec 2, 2022

Ok, kinda good news is this actually work on Linux using Vulkan, but crash on OpenGL.

Thread 29 "Emu" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffc5ffb6c0 (LWP 12150)]
0x0000555555ad2e17 in GenerateVertexShader (id=..., buffer=0x7fffa05fffe0 "", compat=..., bugs=..., attrMask=0x7fffc5ffa744, uniformMask=0x7fffc5ffa748, vertexShaderFlags=0x0, errorString=0x7fffc5ffa770) at /home/iota/Documents/Git/ppsspp/GPU/Common/VertexShaderGenerator.cpp:133
133		*vertexShaderFlags = (VertexShaderFlags)0;
(gdb) bt
#0  0x0000555555ad2e17 in GenerateVertexShader (id=..., buffer=0x7fffa05fffe0 "", compat=..., bugs=..., attrMask=0x7fffc5ffa744, uniformMask=0x7fffc5ffa748, vertexShaderFlags=0x0, 
    errorString=0x7fffc5ffa770) at /home/iota/Documents/Git/ppsspp/GPU/Common/VertexShaderGenerator.cpp:133
#1  0x0000555555c1faec in ShaderManagerGLES::CompileVertexShader (this=0x7fffa0006b60, VSID=...) at /home/iota/Documents/Git/ppsspp/GPU/GLES/ShaderManagerGLES.cpp:769
#2  0x0000555555c21176 in ShaderManagerGLES::ContinuePrecompile (this=0x7fffa0006b60, sliceTime=0.0166666675) at /home/iota/Documents/Git/ppsspp/GPU/GLES/ShaderManagerGLES.cpp:1062
#3  0x0000555555c14741 in GPU_GLES::IsReady (this=0x7fffa0230310) at /home/iota/Documents/Git/ppsspp/GPU/GLES/GPU_GLES.cpp:213
#4  0x0000555555b73fbc in GPU_IsReady () at /home/iota/Documents/Git/ppsspp/GPU/GPU.cpp:57
#5  0x0000555555a695f5 in PSP_InitUpdate (error_string=0x7fffc5ffaa30) at /home/iota/Documents/Git/ppsspp/Core/System.cpp:485
#6  0x00005555556b9b91 in EmuScreen::bootGame (this=0x7fffa0002f20, filename=...) at /home/iota/Documents/Git/ppsspp/UI/EmuScreen.cpp:237
#7  0x00005555556bef9e in EmuScreen::update (this=0x7fffa0002f20) at /home/iota/Documents/Git/ppsspp/UI/EmuScreen.cpp:1037
#8  0x0000555555e0417a in ScreenManager::update (this=0x555557207ce0) at /home/iota/Documents/Git/ppsspp/Common/UI/Screen.cpp:51
#9  0x0000555555681d68 in NativeUpdate () at /home/iota/Documents/Git/ppsspp/UI/NativeApp.cpp:1279
#10 0x00005555557d6c44 in UpdateRunLoop () at /home/iota/Documents/Git/ppsspp/Core/Core.cpp:215
#11 0x0000555555e41c80 in EmuThreadFunc (graphicsContext=0x5555571dacd0) at /home/iota/Documents/Git/ppsspp/SDL/SDLMain.cpp:494
#12 0x0000555555e46b76 in std::__invoke_impl<void, void (*)(GraphicsContext*), GraphicsContext*> (__f=@0x5555572a15c0: 0x555555e41c3e <EmuThreadFunc(GraphicsContext*)>)
    at /usr/include/c++/12.2.0/bits/invoke.h:61
#13 0x0000555555e46af9 in std::__invoke<void (*)(GraphicsContext*), GraphicsContext*> (__fn=@0x5555572a15c0: 0x555555e41c3e <EmuThreadFunc(GraphicsContext*)>)
    at /usr/include/c++/12.2.0/bits/invoke.h:96
#14 0x0000555555e46a69 in std::thread::_Invoker<std::tuple<void (*)(GraphicsContext*), GraphicsContext*> >::_M_invoke<0ul, 1ul> (this=0x5555572a15b8)
    at /usr/include/c++/12.2.0/bits/std_thread.h:252
#15 0x0000555555e46a22 in std::thread::_Invoker<std::tuple<void (*)(GraphicsContext*), GraphicsContext*> >::operator() (this=0x5555572a15b8) at /usr/include/c++/12.2.0/bits/std_thread.h:259
#16 0x0000555555e46a06 in std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)(GraphicsContext*), GraphicsContext*> > >::_M_run (this=0x5555572a15b0)
    at /usr/include/c++/12.2.0/bits/std_thread.h:210
#17 0x00007ffff7b122f3 in std::execute_native_thread_routine (__p=0x5555572a15b0) at /usr/src/debug/gcc/libstdc++-v3/src/c++11/thread.cc:82
#18 0x00007ffff77d18fd in ?? () from /usr/lib/libc.so.6
#19 0x00007ffff7853a60 in ?? () from /usr/lib/libc.so.6

You removed quite a few null pointer checks there, does this crash on Windows too with OpenGL?

@hrydgard
Copy link
Owner Author

hrydgard commented Dec 2, 2022

Oops, I'll fix that up. Meant to always pass a valid pointer in, removing the need for the null checks, but apparently failed to update some of the other backends.

@hrydgard hrydgard changed the title Implement MSAA support for desktop GPUs Implement MSAA support for desktop GPUs in Vulkan Dec 3, 2022
@hrydgard
Copy link
Owner Author

hrydgard commented Dec 3, 2022

It works well enough now. I'm gonna get it in, and deal with any consequences :)

@hrydgard hrydgard merged commit 02b8bf3 into master Dec 3, 2022
@hrydgard hrydgard deleted the desktop-friendly-msaa branch December 3, 2022 10:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
GE emulation Backend-independent GPU issues Vulkan
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants