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 Viewport Window rendering is slow #7283

Closed
lailoken opened this issue Feb 1, 2024 · 3 comments
Closed

Multiple Viewport Window rendering is slow #7283

lailoken opened this issue Feb 1, 2024 · 3 comments

Comments

@lailoken
Copy link

lailoken commented Feb 1, 2024

Version/Branch of Dear ImGui:

1.90 docking

Back-ends:

imgui_impl_dx11.cpp

Compiler, OS:

VS 2017, Windows 11

Full config/build information:

Dear ImGui 1.90.0 (19000)
--------------------------------
sizeof(size_t): 8, sizeof(ImDrawIdx): 4, sizeof(ImDrawVert): 20
define: __cplusplus=199711
define: IMGUI_DISABLE_OBSOLETE_FUNCTIONS
define: IMGUI_DISABLE_OBSOLETE_KEYIO
define: _WIN32
define: _WIN64
define: _MSC_VER=1938
define: _MSVC_LANG=201402
define: IMGUI_HAS_VIEWPORT
define: IMGUI_HAS_DOCK
--------------------------------
io.BackendPlatformName: imgui_impl_win32
io.BackendRendererName: imgui_impl_dx11
io.ConfigFlags: 0x00000441
 NavEnableKeyboard
 DockingEnable
 ViewportsEnable
io.ConfigViewportsNoDecoration
io.ConfigDockingWithShift
io.ConfigInputTextCursorBlink
io.ConfigWindowsResizeFromEdges
io.ConfigWindowsMoveFromTitleBarOnly
io.ConfigMemoryCompactTimer = 60.0
io.BackendFlags: 0x00001C0E
 HasMouseCursors
 HasSetMousePos
 PlatformHasViewports
 HasMouseHoveredViewport
 RendererHasVtxOffset
 RendererHasViewports
--------------------------------
io.Fonts: 9 fonts, Flags: 0x00000000, TexSize: 2048,2048
io.DisplaySize: 1557.00,788.00
io.DisplayFramebufferScale: 1.00,1.00
--------------------------------
style.WindowPadding: 3.00,3.00
style.WindowBorderSize: 1.00
style.FramePadding: 4.00,2.00
style.FrameRounding: 0.00
style.FrameBorderSize: 1.00
style.ItemSpacing: 6.00,3.00
style.ItemInnerSpacing: 3.00,3.00

Details:

My trading application runs on multiple monitors, and I have enabled multiple viewports so that I can drag/tile relatively small windows all over the place. I have about 90 open in my test, but we aim to have over 200.

I have collapsed the windows so only the title bars are showing (no content is rendered or added to the draw lists)

This all works fine when these windows are merged to my main application viewport, but I when I tile them outside (still on the same monitor, but separate from my main application), the internal ImGui render loop goes from 1ms to about 100ms, tanking my FPS and other processes in the main loop.

The main culprit being these calls (obviously):

#ifdef IMGUI_HAS_VIEWPORT
                if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
                    ImGui::UpdatePlatformWindows();
...
                if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
                    ImGui::RenderPlatformWindowsDefault();
#endif

When I expand these windows and view their content, it slows down only a slight bit more both inside and outside the merged main viewport.

It seems directly related to the number of viewports, slowing down linearly with the number of windows not merged.

I've also set all my displays to 100% DPI in case this changes anything, but it did not.

(We have another developer running on Linux with a different backend having the same issue, I'm sure they are related)

Screenshots/Video:

Unmerged: (20FPS)
image
merged: (60FPS)
image

Minimal, Complete and Verifiable Example code:

    // create 90 collapsed dummy windows under each other:
    ImVec2 p = {10.f, 10.f};
    for (int i = 0; i < 90; ++i)
    {
        ImGui::SetNextWindowPos(p);
        ImGui::SetNextWindowSize({200.f, 200.f});
        ImGui::SetNextWindowCollapsed(true);
        ImGui::Begin(std::to_string(i).c_str());
        p.y += ImGui::GetWindowSize().y;
        ImGui::End();
    }
@ocornut
Copy link
Owner

ocornut commented Feb 2, 2024

I believe the call to ImGui_ImplDX11_SwapBuffers() may be forcefully waiting for vsync in spite of the explicit vd->SwapChain->Present(0, 0); // Present without vsync. It may depends on swap chain and drivers configuration.

@ocornut
Copy link
Owner

ocornut commented Feb 2, 2024

To clarify, on my laptop if I run your code I get about 20 ms per frame (which is very slow, but quite faster than yours) and it's all swapchain or driver overhead. I don't have resources to investigate this for you, you will need to look into DX11 related swap-chain and drivers settings for high numbers of swap chains.

@lailoken
Copy link
Author

lailoken commented Feb 2, 2024

@ocornut as per your advice I looked at the swap chains and started trying out various other suggestions I found on the web. I was able to get my FPS from 20 to over 200. Can comfortably maintain 60FPS with a reasonable amount of data visible now.

I've attempted my first PR on github, hope it's usable:
#7286

@lailoken lailoken closed this as completed Feb 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants