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

Multiple swap chains frame lag? #279

Open
mctb32 opened this issue Jan 4, 2024 · 4 comments
Open

Multiple swap chains frame lag? #279

mctb32 opened this issue Jan 4, 2024 · 4 comments

Comments

@mctb32
Copy link

mctb32 commented Jan 4, 2024

Not sure if this is related to the Windows 11 problems I reported a while back. I'm now trying to run diligent with the imgui docking branch and I have successfully implemented the extended imgui renderer callbacks so that imgui can renderer into multiple windows with diligent. The problem I have is that the additional windows seem to lag a frame behind the main window. It looks like this:

smoke

The problem exists in all configurations on Windows 11 (dx11, dx12, vulkan backends, with and without vsync enabled), but it also exists on Windows 10 unless I disable vsync for all of the windows (which is not practical for a GUI app).

I'm closely following the code flow from the official imgui examples, which don't exhibit this problem on either W10 or W11. I'm using the imgui_impl_sdl2 platform backend (same as the examples I’m trying to mirror) so the only major difference is that I'm using Diligent and ImGuiDiligentRenderer to render the imgui data.

For example, the imgui example_sdl2_dx11 Presents the additional windows first without vsync, and finally Presents the main window with vsync and it works flawlessly on both W10 and W11. If I do the same with diligent, I get the lag problem on both W10 and W11.

@mctb32
Copy link
Author

mctb32 commented Jan 4, 2024

@TheMostDiligent Ok, so I found the sources of the problems inside diligent dx11, and now everything runs smooth and in sync just like in the imgui examples, but I'm not sure what to make of the changes I had to make...

There were actually two issues. First, if you look closely at the gif I uploaded, I had a signifficant frame drop when moving the secondary window. This was caused by the Max Frame Latency feature. At first I removed the WaitForFrame() call from the SwapChainD3D11Impl::Present, but it didn;t change anything. But then I removed the
swapChainDesc.Flags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
from the CreateDXGISwapChain function and now the frame drop when moving the windows was gone and I had a steady 60fps.

But the frame lag was still there and the windows were not in sync. To get rid of the lag, I had to change the swap chain swap effect to the legacy DXGI_SWAP_EFFECT_DISCARD (this is what imgui examples are using) and enable DXGI_SCALING_STRETCH (apparently required by the legacy swap effects). The best thing is that this not only solves the frame lag problem between windows, it also allows diligent to properly control vsync in dx11 on W11. So now I can run both with and without vsync and all the windows stay perfectly in sync.

I tried to run the imgui examples with the DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL to see if they would also display frame lag, but unfortunately they crash failing on swapchain creation. I guess this is because they use the old IDXGIFactory interface.

Anyway, I know the ms docs say that we should use the new flip model swap effects, but on my W11 system with RTX 4080 and latest nvidia studio drivers this works like crap and only the legacy swap effects work correctly.

So I think it would be great if you could expose these options to the users - allow disabling max frame latency and switching to legacy swap modes via swapchain desc. I'm not sure how prevalent those problems are for w11 users and if they are nvidia specific, but if they are common, then you could even set those options as default on w11.

I also have a laptop with w11 and integrated ati GPU and discrete nvidia GPU, so I will do some more testing tomorrow,

@TheMostDiligent
Copy link
Contributor

I had to change the swap chain swap effect to the legacy DXGI_SWAP_EFFECT_DISCARD

I am wondering how this works on Direct3D12 that does not support this mode (at least as the documentation says)

So I think it would be great if you could expose these options to the users - allow disabling max frame latency and switching to legacy swap modes via swapchain desc.

Yes, I think these options can be added to the SwapChainDesc

@mctb32
Copy link
Author

mctb32 commented Jan 4, 2024

I am wondering how this works on Direct3D12 that does not support this mode (at least as the documentation says)

That's right. I've run the imgui example_win32_dx12 and it had the same frame lag on the secondary windows. In this implementation they are using DXGI_SWAP_EFFECT_FLIP_DISCARD for both primary and secondary windows.

Interestingly the sample is not displaying any frame drops when moving the windows even though they are using the DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT and calling g_pSwapChain->SetMaximumFrameLatency(NUM_BACK_BUFFERS); just like you do in diligent.

But they are using it only for the primary window, while the diligent swapchain implementation enables it for all swapchains. Also, in their example backbuffers are set to 3, while in diligent I was testing with 2.

Another interesting thing - I tried to disable vsync in the imgui dx12 example and it sort-of succeded ;) It doubled the framerate to 120fps. When I change the backbuffers to 4, it jumps to 180fps, and so on. With 2 backbuffers it's locked to 60fps just like I experienced in diligent.

@mctb32
Copy link
Author

mctb32 commented Jan 9, 2024

I've been doing some more testing, and so far changing to legacy DXGI_SWAP_EFFECT_DISCARD and disabling frame latency feature has resulted in the app working better or the same on all configurations I tested (win10+nvda, win11+nvda, win11+amd).

I'm not 100% sure if I tested the amd version correctly though, as this was running on a laptop which has two gpus. I disabled the nvda gpu using asus crate software, but is there any API inside diligent I could use to make sure on which gpu the app is actually running? Like get the name of the gpu, or a string with the driver version? Also, if there is more than one gpu in the system, is there a way to enumerate the gpus and tell diligent on which gpu to run?

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

No branches or pull requests

2 participants