The Win32 backend currently supports MSAA swapchains with the outdated DXGI_SWAP_EFFECT_DISCARD model, and the UWP backend currently doesn't support MSAA swapchains at all.
The fix for both will look very similar, probably also an opportunity to share the new implementation between the two backend.
Have you considered switching to DXGI_SWAP_EFFECT_FLIP_DISCARD for D11? I tried it by changing:
sc_desc->SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
sc_desc->BufferCount = 2;
I think this only works in Win10? So, would need to check for that and fallback to DXGI_SWAP_EFFECT_DISCARD for Win8 if you still want to support that.
More info here: https://devblogs.microsoft.com/directx/dxgi-flip-model/ (see "What do I have to do to use flip model?")
Sorry for hijacking this issue, but the reason for my test was to test the IDXGISwapChain::GetFrameStatistics api which gives much better frame times than using QueryPerformanceFrequency. See: https://blogs.unity3d.com/2020/10/01/fixing-time-deltatime-in-unity-2020-2-for-smoother-gameplay-what-did-it-take/
There seems to be some advantages when resizing windows using FLIP_DISCARD as well. (I think you've been working on this recently?)
"Applications have control over content scaling that happens during window resize, using the DXGI_SCALING property set during swapchain creation." (from: https://docs.microsoft.com/en-us/windows/win32/direct3ddxgi/dxgi-flip-model)
Yep that's the plan, the only problem is that the FLIP modes don't automatically support MSAA.
sokol_app.h must create the MSAA surface separately, and resolve this into the swapchain surface before presentation, the same fix must be added to UWP backend. This is also how it already works in the WebGPU backend. It's not particularly complicated, it's just no longer "builtin" as before.
I don't know yet if this also helps with the memory spike problem during resize (that was the stuff I've been working on the last few days, or more specifically, calling the frame callback also during window resize and movement). It probably makes sense to rewrite the swapchain code first before investigating how the memory spike can be fixed (I have an idea there as well, but need to experiment).
PS: the current "fix" for the frame time microstutter is this new sokol_time.h function I added a little while ago:
https://github.com/floooh/sokol/blob/d5e619093996c5e11336b507753ca297625a82ea/sokol_time.h#L285-L297
...getting the timing directly from the swapchain should be much more robust, but the rounding is "platform-agnostic". Moving the frame time computation into sokol_app.h is an interesting idea though...
Yeah, I saw that function, and it's probably still going to be necessary on other platforms. Here's how to get the frame time with GetFrameStatistics on D11:
extern uint64_t sokol_ext_get_frame_time()
{
DXGI_FRAME_STATISTICS stats;
_sapp.d3d11.swap_chain->lpVtbl->GetFrameStatistics(_sapp.d3d11.swap_chain, &stats);
LARGE_INTEGER qpc_t = stats.SyncQPCTime;
uint64_t frame_time = int64_muldiv(qpc_t.QuadPart, 1000000000, _stm.freq.QuadPart);
return frame_time;
}
Hmm some minor problems:
So for Windows7 support (which I don't want to ditch yet) DXGI_SWAP_EFFECT_DISCARD must still be supported. I'll see if I can check at runtime what's supported and then decide between DXGI_SWAP_EFFECT_DISCARD (below Windows 10) and DXGI_SWAP_EFFECT_FLIP_DISCARD otherwise.
Hrmpf, trying to actually find out whether DXGI_SWAP_EFFECT_FLIP_DISCARD doesn't seem to be easy... all Win32 calls to identify the Windows version seem to be deprected:
https://docs.microsoft.com/en-us/windows/win32/sysinfo/targeting-your-application-at-windows-8-1
You probably want to avoid this manifest stuff, there's also this way:
"To obtain the full version number for the operating system, call the GetFileVersionInfo function on one of the system DLLs, such as Kernel32.dll, then call VerQueryValue to obtain the \StringFileInfo\
"Another way is to use RtlGetVersion(), NetServerGetInfo(), or NetWkstaGetInfo() instead. They all report an accurate OS version and are not subject to manifestation (yet?)."
from: https://stackoverflow.com/questions/32115255/c-how-to-detect-windows-10
I'm going with this solution from VLC:
At first it looks like a hack, but simply checking if kernel32.dll contains a function that was added in Win10 is actually quite robust IMHO, since MS can't randomly remove function entry points from kernel32.dll.
You are using GetModuleHandleA("kernel32.dll"), is there any chance this will break on unicode setups, say Chinese Win10 installs? It looks like VLC is using the unicode api. (GetModuleHandleW(L"kernel32.dll")). I don't have a chinese test setup right now, or I'd check it myself.
I think it should work anywhere because the name kernel32.dll is fixed and doesn't contain any unicode chars, but of course I can't be 100% sure :) But copying VLC in this case can't hurt I guess. I'll commit a fix.
Ok I changed it to the W function. BTW I just saw a strange artefact on my Win10 machine while resizing (while working in the debugger, so maybe it was triggered by having breakpoints within the resizing modal loop, just a guess though). The bottom and right borders were not completely covered by the framebuffer and had artefacts from previous frames in a stripe that's maybe 10 pixels wide (depends on the resizing speed).
It also happened with the "traditional" Win7 swap effect. It was gone after rebooting and now I can't get it to reproduce. Just as a heads up. Most likely this is related to the "render during resize" change, not the new swapchain code (no idea though how to do this differently or what could have caused that glitch).