imgui icon indicating copy to clipboard operation
imgui copied to clipboard

Resizing problem when using a glfw window with directx 11

Open Ack008 opened this issue 3 years ago • 4 comments

Hi everyone. I'm trying to create my own game engine using ImGui. I programmed in such a way that i can choose which API I can use to render the scene, I can choose between Directx 11 and Opengl, but in both cases i use a glfw window. With Opengl everything is fine, the problem comes with the second one. 2022-01-06 (1) 2022-01-06 (2) 2022-01-06 (3)

The problem comes when i resize the window while I'm using the Directx11. When I resize it resize the swap chain, so i don't think that the problem is in the directx settings itself. In order to inizialize ImGui for D3DX11 I use the following code:

  • ImGui_ImplGlfw_InitForOther(win_->GetWindow(),true);
  • ImGui_ImplDX11_Init(win_->pDevice, win_->pContext); In the frame:
  • ImGui_ImplDX11_NewFrame();
  • ImGui_ImplGlfw_NewFrame(); and for the rendering:
  • ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); (obviously I also use ImGui::New_Frame() and ImGui::Render();

Also the input coordinates are wrong after the resize, for example, also if I click outside the imgui window, imgui detect that I'm inside of it, otherwise, if I'm touching the window, ImGui doesn't detect it.

(Sorry for the bad english).

Ack008 avatar Jan 06 '22 17:01 Ack008

Check the value of io.DisplaySize and how it is updated by ImGui_ImplGlfw_NewFrame(). Perhaps some of the function there don't work with that specific setup? Also print the value of io.MousePos to see which side of the fence may be wrong.

ocornut avatar Feb 10 '22 17:02 ocornut

I have the same problem in Win32 with DX11. I checked io.DisplaySize and io.MousePos and the values are updated correctly. Nonetheless, resizing the window stretches ImGui just as shown above.

Mystixor avatar Jul 23 '24 17:07 Mystixor

For anyone still facing this issue, I believe I've come up with a solution. Here's what I did (mind you I'm using DirectX 11 with GLFW and i'm using the docking branch of version 1.90.4 so this may have already been fixed and I just don't know.

From my understanding of how DirectX works even though ImGui creates their own swapchain it doesn't in all reality make an entirely new and independent swapchain, but instead just passes a reference to the swapchain you made (if you made your own in a framebuffer class or something like that). So because of this when you resize your own framebuffer the entire windows framebuffer is resized (as it should be) and the data pulled in ImGui_ImplGlfw_NewFrame() matches exactly what it should be.

Here's where the issue comes in, even though the framebuffer size is changed the window resolution is never changed, this takes place in ImGui_ImplGlfw_UpdateMonitors().

So the solution that ended up working for me is as follows I added the following functions to the imgui_impl_glfw.h file...

imgui_impl_glfw.h:

IMGUI_IMPL_API void     ImGui_ImplGlfw_FrameBufferCallback(GLFWwindow* window, int width, int height);
IMGUI_IMPL_API void     ImGui_ImplGlfw_WindowResizeCallback(GLFWwindow* Window, int Width, int Height);

... I then added these callback types to ImGui_ImplGlfw_Data...

imgui_impl_glfw.cpp:

GLFWframebuffersizefun  PrevUserCallbackFrameBuffer;
GLFWwindowsizefun       PrevUserCallbackWindowSize;

... And I set the user call backs here in the .cpp file... imgui_impl_glfw.cpp: in ImGui_ImplGlfw_InstallCallbacks()



    bd->PrevUserCallbackFrameBuffer = glfwSetFramebufferSizeCallback(window, ImGui_ImplGlfw_FrameBufferCallback);
    bd->PrevUserCallbackWindowSize = glfwSetWindowSizeCallback(window, ImGui_ImplGlfw_WindowResizeCallback);

... And then implemented them inside of the cpp file, all that takes place there is it chain-calls my own callbacks that i set up in my window class while also calling ImGui_ImplGlfw_UpdateMonitors()

imgui_impl_glfw.cpp:


void ImGui_ImplGlfw_FrameBufferCallback(GLFWwindow* window, int width, int height)
{
    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
    ImGuiIO& io = ImGui::GetIO();
    if (bd->PrevUserCallbackChar != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
        bd->PrevUserCallbackFrameBuffer(window, width, height);

    ImGui_ImplGlfw_UpdateMonitors();
}

void ImGui_ImplGlfw_WindowResizeCallback(GLFWwindow* Window, int Width, int Height)
{
    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
    if (bd->PrevUserCallbackChar != nullptr && ImGui_ImplGlfw_ShouldChainCallback(Window))
        bd->PrevUserCallbackWindowSize(Window, Width, Height);
    ImGui_ImplGlfw_UpdateMonitors();
}

Edit: I'd like to add that this solution is contingent upon your framebuffer size (assuming you have a custom framebuffer class) matching what gflwGetFramebufferSize() returns

Tepidangler avatar Apr 09 '25 01:04 Tepidangler

For anyone facing this issue with DX11 and Win32 (@Mystixor), I fixed it by hooking the ResizeBuffers function (in addition to Present), calling the original ResizeBuffers in it, then creating the new render target. Nothing additional in WndProc (most solutions I found, including MS docs, involved checking WM_SIZE but that did not work for me). Has nothing to do with ImGui as Omar has stated in many related issues

ezio416 avatar May 09 '25 01:05 ezio416