ocornut / imgui

Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies
MIT License
57.69k stars 9.9k forks source link

d3d11 Multi-Viewport bug #6208

Open hebohang opened 1 year ago

hebohang commented 1 year ago

Version/Branch of Dear ImGui:

Version: 1.88 Branch: docking

Backend:

C++20, Windows10

I tried both two ways: imgui_impl_dx11 + imgui_impl_glfw imgui_impl_dx11 + imgui_impl_win32

All appear the same bug.

When I disable the Multi-Viewport, it seems only the color not right:

https://user-images.githubusercontent.com/60227429/222217711-46622290-19b9-47e6-b38f-a39b005e526c.mp4

However, when I enable Multi-Viewport with code:

ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; 

It will raise a bug:

https://user-images.githubusercontent.com/60227429/222217931-2c178606-84e4-4f34-a02a-0e9a7a2a29a2.mp4

When I put the imgui window next to the main window, the program will freeze.

I used the DXGI_SWAP_EFFECT_FLIP_DISCARD effect to create my swapchain, I find it probably related to the swapchain. And it seems I must clear my RenderTarget when imgui draw.

Some code I write:

    void DX11ImGuiLayer::OnAttach()
    {
        ImguiInit();

        Application& app = Application::GetInstance();
        GLFWwindow* window = static_cast<GLFWwindow*>(app.GetWindow().GetNativeWindow());
        HWND hWnd = glfwGetWin32Window(window);

        // Setup Platform/Renderer backends
        ImGui_ImplGlfw_InitForOther(window, true);
        //ImGui_ImplWin32_Init(hWnd);
        ImGui_ImplDX11_Init(DX11Context::Get()->GetDevice().Get(), DX11Context::Get()->GetD3D11Context().Get());

        DX11Context::Get()->OnResize();
    }

    void DX11ImGuiLayer::OnDetach()
    {
        // Cleanup
        ImGui_ImplDX11_Shutdown();
        //ImGui_ImplWin32_Shutdown();
        ImGui_ImplGlfw_Shutdown();
        ImGui::DestroyContext();
    }

    void DX11ImGuiLayer::OnImGuiRender()
    {
        //static bool pOpen = true;
        //ImGui::ShowDemoWindow(&pOpen);
    }

    void DX11ImGuiLayer::Begin()
    {
        // Start the Dear ImGui frame
        ImGui_ImplDX11_NewFrame();
        //ImGui_ImplWin32_NewFrame();
        ImGui_ImplGlfw_NewFrame();
        ImGui::NewFrame();

        ImGuizmo::BeginFrame();
    }

    void DX11ImGuiLayer::End()
    {
        ImGuiIO& io = ImGui::GetIO();
        Application& app = Application::GetInstance();
        io.DisplaySize = ImVec2((float)app.GetWindow().GetWidth(), (float)app.GetWindow().GetHeight());

        // Rendering
        ImGui::Render();
        ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
        //DX11Context::Get()->GetD3D11Context()->OMSetRenderTargets(1, DX11Context::Get()->GetBackBufferRTV().GetAddressOf(), NULL);
        ImDrawData* main_draw_data = ImGui::GetDrawData();
        ImGui_ImplDX11_RenderDrawData(main_draw_data);

        if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
        {
            GLFWwindow* backup_current_context = glfwGetCurrentContext();
            ImGui::UpdatePlatformWindows();
            ImGui::RenderPlatformWindowsDefault();
            glfwMakeContextCurrent(backup_current_context);
        }
    }

ImguiInit Function I writed:

    void ImGuiLayer::ImguiInit()
    {
        // Setup Dear ImGui context
        IMGUI_CHECKVERSION();
        ImGui::CreateContext();
        ImGuiIO& io = ImGui::GetIO(); (void)io;
        io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;       // Enable Keyboard Controls
        //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls
        io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;           // Enable Docking
        io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;         // Enable Multi-Viewport / Platform Windows
        //io.ConfigViewportsNoAutoMerge = true;
        //io.ConfigViewportsNoTaskBarIcon = true;

        ImguiInitFont();

        // Setup Dear ImGui style
        ImGui::StyleColorsDark();
        //ImGui::StyleColorsClassic();

        // When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
        ImGuiStyle& style = ImGui::GetStyle();
        if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
        {
            style.WindowRounding = 0.0f;
            style.Colors[ImGuiCol_WindowBg].w = 1.0f;
        }

        SetDarkThemeColors();
    }

Hope to get your help.

hebohang commented 1 year ago

I find the color error seems to be with the color space. I use the DXGI_FORMAT_R8G8B8A8_UNORM_SRGB as the D3D11_RENDER_TARGET_VIEW_DESC format. I fine the same issue: https://github.com/ocornut/imgui/issues/578

I still don't know how to fix the multi-view issue (When I put the imgui window next to the main window, the program will freeze) .

ocornut commented 1 year ago

Hello,

VonBismarck1986 commented 1 year ago

Error comes from imgui_impl_dx12.cpp line 906

IDXGISwapChain1* swap_chain = nullptr; res = dxgi_factory->CreateSwapChainForHwnd(vd->CommandQueue, hwnd, &sd1, nullptr, nullptr, &swap_chain); IM_ASSERT(res == S_OK);

VonBismarck1986 commented 1 year ago

I guess it goes back to using DXGI_FORMAT_R8G8B8A8_UNORM_SRGB instead of DXGI_FORMAT_R8G8B8A8_UNORM