From bf75bfec48fc00f532af8926130b70c0e26eb099 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 17 Sep 2025 19:05:22 +0200 Subject: [PATCH 01/39] Amend f6890ed mostly to please static analyzers. --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 22d371ad8..45c913a0a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -13431,7 +13431,7 @@ static ImVec2 ImGui::NavCalcPreferredRefPos() ImRect ref_rect; if (activated_shortcut) ref_rect = g.LastItemData.NavRect; - else + else if (window != NULL) ref_rect = WindowRectRelToAbs(window, window->NavRectRel[g.NavLayer]); // Take account of upcoming scrolling (maybe set mouse pos should be done in EndFrame?) From 03f3c8d385393676eb55c9cb46d73a813134cf35 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 18 Sep 2025 15:22:42 +0200 Subject: [PATCH 02/39] Nav: fix crash when NavCalcPreferredRefPos() hit non Mouse case with a null NavWindow (docking branch only). Amend f6890ed00. --- imgui.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 0c635c681..dfd68dfec 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -14149,8 +14149,10 @@ static ImVec2 ImGui::NavCalcPreferredRefPos() ref_rect.Translate(window->Scroll - next_scroll); } ImVec2 pos = ImVec2(ref_rect.Min.x + ImMin(g.Style.FramePadding.x * 4, ref_rect.GetWidth()), ref_rect.Max.y - ImMin(g.Style.FramePadding.y, ref_rect.GetHeight())); - ImGuiViewport* viewport = window->Viewport; - return ImTrunc(ImClamp(pos, viewport->Pos, viewport->Pos + viewport->Size)); // ImTrunc() is important because non-integer mouse position application in backend might be lossy and result in undesirable non-zero delta. + if (window != NULL) + if (ImGuiViewport* viewport = window->Viewport) + pos = ImClamp(pos, viewport->Pos, viewport->Pos + viewport->Size); + return ImTrunc(pos); // ImTrunc() is important because non-integer mouse position application in backend might be lossy and result in undesirable non-zero delta. } } From 0e7cd694ebd5472c718e818344c35346661aeb18 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 18 Sep 2025 15:38:46 +0200 Subject: [PATCH 03/39] Version 1.92.4 WIP --- docs/CHANGELOG.txt | 9 +++++++++ imgui.cpp | 2 +- imgui.h | 6 +++--- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- imgui_internal.h | 2 +- imgui_tables.cpp | 2 +- imgui_widgets.cpp | 2 +- 8 files changed, 18 insertions(+), 9 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 01df5a742..f7ae7c991 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -35,6 +35,15 @@ HOW TO UPDATE? and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users. - Please report any issue! +----------------------------------------------------------------------- + VERSION 1.92.4 WIP (In Progress) +----------------------------------------------------------------------- + +Breaking Changes: + +Other Changes: + + ----------------------------------------------------------------------- VERSION 1.92.3 (Released 2025-09-17) ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index 45c913a0a..29774fe37 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.3 +// dear imgui, v1.92.4 WIP // (main code and documentation) // Help: diff --git a/imgui.h b/imgui.h index aa44a51f3..d79a912bf 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.92.3 +// dear imgui, v1.92.4 WIP // (headers) // Help: @@ -28,8 +28,8 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') -#define IMGUI_VERSION "1.92.3" -#define IMGUI_VERSION_NUM 19230 +#define IMGUI_VERSION "1.92.4 WIP" +#define IMGUI_VERSION_NUM 19231 #define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000 #define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198 diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 27d3300b9..e3991a60e 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.3 +// dear imgui, v1.92.4 WIP // (demo code) // Help: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 8a629b44d..3beb3aa80 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.3 +// dear imgui, v1.92.4 WIP // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index ece4afbd9..f66b91f7d 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.92.3 +// dear imgui, v1.92.4 WIP // (internal structures/api) // You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility. diff --git a/imgui_tables.cpp b/imgui_tables.cpp index f5c4c25aa..21d5335c6 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.3 +// dear imgui, v1.92.4 WIP // (tables and columns code) /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 776a7135c..4709af05b 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.3 +// dear imgui, v1.92.4 WIP // (widgets code) /* From 16b2d2011526300becc163b60a37d4112c9938eb Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 18 Sep 2025 16:47:40 +0200 Subject: [PATCH 04/39] Viewports: DestroyContext() does not call DestroyPlatformWindows() anymore. (#7175, #8945) --- docs/CHANGELOG.txt | 3 +++ imgui.cpp | 8 +++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 2ac724f24..204ffc166 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -48,6 +48,9 @@ Docking+Viewports Branch: - Nav: fixed a crash that could occur when opening a popup following the processing of a global shortcut while no windows were focused (the fix done in 1.92.3 was incomplete for docking branch). +- Viewports: DestroyContext() does not call DestroyPlatformWindows() anymore at + it assumed to be unnecessary as backensd should have done it and we check that + backends have been shutdown since 1.90.4. Changed into asserts. (#7175, #8945) ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index 3bb0dcd7e..a10765d30 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4415,6 +4415,11 @@ void ImGui::Shutdown() ImGuiContext& g = *GImGui; IM_ASSERT_USER_ERROR(g.IO.BackendPlatformUserData == NULL, "Forgot to shutdown Platform backend?"); IM_ASSERT_USER_ERROR(g.IO.BackendRendererUserData == NULL, "Forgot to shutdown Renderer backend?"); + for (ImGuiViewportP* viewport : g.Viewports) + { + IM_UNUSED(viewport); + IM_ASSERT_USER_ERROR(viewport->RendererUserData == NULL && viewport->PlatformUserData == NULL && viewport->PlatformHandle == NULL, "Backend or app forgot to call DestroyPlatformWindows()?"); + } // The fonts atlas can be used prior to calling NewFrame(), so we clear it even if g.Initialized is FALSE (which would happen if we never called NewFrame) for (ImFontAtlas* atlas : g.FontAtlases) @@ -4436,9 +4441,6 @@ void ImGui::Shutdown() if (g.SettingsLoaded && g.IO.IniFilename != NULL) SaveIniSettingsToDisk(g.IO.IniFilename); - // Destroy platform windows - DestroyPlatformWindows(); - // Shutdown extensions DockContextShutdown(&g); From 3dd51651e3538aa3b836d07cc92288b3c1813d94 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 18 Sep 2025 16:51:40 +0200 Subject: [PATCH 05/39] Backends: DX12: rename internal functions to match other backends. --- backends/imgui_impl_dx12.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp index 776a7b01f..8e33af1b4 100644 --- a/backends/imgui_impl_dx12.cpp +++ b/backends/imgui_impl_dx12.cpp @@ -202,8 +202,8 @@ struct VERTEX_CONSTANT_BUFFER_DX12 }; // Forward Declarations -static void ImGui_ImplDX12_InitPlatformInterface(); -static void ImGui_ImplDX12_ShutdownPlatformInterface(); +static void ImGui_ImplDX12_InitMultiViewportSupport(); +static void ImGui_ImplDX12_ShutdownMultiViewportSupport(); // Functions static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12GraphicsCommandList* command_list, ImGui_ImplDX12_RenderBuffers* fr) @@ -932,7 +932,7 @@ bool ImGui_ImplDX12_Init(ImGui_ImplDX12_InitInfo* init_info) io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional) if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) - ImGui_ImplDX12_InitPlatformInterface(); + ImGui_ImplDX12_InitMultiViewportSupport(); // Create a dummy ImGui_ImplDX12_ViewportData holder for the main viewport, // Since this is created and managed by the application, we will only use the ->Resources[] fields. @@ -996,7 +996,7 @@ void ImGui_ImplDX12_Shutdown() } // Clean up windows and device objects - ImGui_ImplDX12_ShutdownPlatformInterface(); + ImGui_ImplDX12_ShutdownMultiViewportSupport(); ImGui_ImplDX12_InvalidateDeviceObjects(); io.BackendRendererName = nullptr; @@ -1240,7 +1240,7 @@ static void ImGui_ImplDX12_SwapBuffers(ImGuiViewport* viewport, void*) ::SwitchToThread(); } -void ImGui_ImplDX12_InitPlatformInterface() +void ImGui_ImplDX12_InitMultiViewportSupport() { ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); platform_io.Renderer_CreateWindow = ImGui_ImplDX12_CreateWindow; @@ -1250,7 +1250,7 @@ void ImGui_ImplDX12_InitPlatformInterface() platform_io.Renderer_SwapBuffers = ImGui_ImplDX12_SwapBuffers; } -void ImGui_ImplDX12_ShutdownPlatformInterface() +void ImGui_ImplDX12_ShutdownMultiViewportSupport() { ImGui::DestroyPlatformWindows(); } From d4f722d5b289d4d75b775acfb0a4b41e7df472a7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 18 Sep 2025 16:22:24 +0200 Subject: [PATCH 06/39] IO: added ImGuiPlatformIO::ClearPlatformHandlers(), ClearRendererHandlers(). Backends: call those on Shutdown(). (#8945, #2769) --- backends/imgui_impl_allegro5.cpp | 4 ++++ backends/imgui_impl_dx10.cpp | 4 ++++ backends/imgui_impl_dx11.cpp | 4 ++++ backends/imgui_impl_dx12.cpp | 4 +++- backends/imgui_impl_dx9.cpp | 4 ++++ backends/imgui_impl_glfw.cpp | 4 ++++ backends/imgui_impl_metal.mm | 6 +++++- backends/imgui_impl_opengl2.cpp | 4 ++++ backends/imgui_impl_opengl3.cpp | 4 ++++ backends/imgui_impl_osx.mm | 4 ++++ backends/imgui_impl_sdl2.cpp | 3 +++ backends/imgui_impl_sdl3.cpp | 3 +++ backends/imgui_impl_sdlgpu3.cpp | 4 ++++ backends/imgui_impl_sdlrenderer2.cpp | 3 +++ backends/imgui_impl_sdlrenderer3.cpp | 3 +++ backends/imgui_impl_vulkan.cpp | 3 +++ backends/imgui_impl_wgpu.cpp | 3 +++ backends/imgui_impl_win32.cpp | 3 +++ docs/CHANGELOG.txt | 6 ++++++ imgui.cpp | 17 +++++++++++++++++ imgui.h | 7 +++++++ 21 files changed, 95 insertions(+), 2 deletions(-) diff --git a/backends/imgui_impl_allegro5.cpp b/backends/imgui_impl_allegro5.cpp index 6c5df4b1f..bb6660d88 100644 --- a/backends/imgui_impl_allegro5.cpp +++ b/backends/imgui_impl_allegro5.cpp @@ -21,6 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-18: Call platform_io.ClearRendererHandlers() and platform_io.ClearPlatformHandlers() on shutdown. // 2025-08-12: Inputs: fixed missing support for ImGuiKey_PrintScreen under Windows, as raw Allegro 5 does not receive it. // 2025-08-12: Added ImGui_ImplAllegro5_SetDisplay() function to change current ALLEGRO_DISPLAY, as Allegro applications often need to do that. // 2025-07-07: Fixed texture update broken on some platforms where ALLEGRO_LOCK_WRITEONLY needed all texels to be rewritten. @@ -499,6 +500,7 @@ void ImGui_ImplAllegro5_Shutdown() ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData(); IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGui_ImplAllegro5_InvalidateDeviceObjects(); if (bd->VertexDecl) @@ -509,6 +511,8 @@ void ImGui_ImplAllegro5_Shutdown() io.BackendPlatformName = io.BackendRendererName = nullptr; io.BackendPlatformUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_RendererHasTextures); + platform_io.ClearRendererHandlers(); + platform_io.ClearPlatformHandlers(); IM_DELETE(bd); } diff --git a/backends/imgui_impl_dx10.cpp b/backends/imgui_impl_dx10.cpp index 5515f780c..ae6510db2 100644 --- a/backends/imgui_impl_dx10.cpp +++ b/backends/imgui_impl_dx10.cpp @@ -16,6 +16,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-06-11: DirectX10: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. // 2025-05-07: DirectX10: Honor draw_data->FramebufferScale to allow for custom backends and experiment using it (consistently with other renderer backends, even though in normal condition it is not set under Windows). // 2025-01-06: DirectX10: Expose selected render state in ImGui_ImplDX10_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks. @@ -630,13 +631,16 @@ void ImGui_ImplDX10_Shutdown() ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData(); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGui_ImplDX10_InvalidateDeviceObjects(); if (bd->pFactory) { bd->pFactory->Release(); } if (bd->pd3dDevice) { bd->pd3dDevice->Release(); } + io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures); + platform_io.ClearRendererHandlers(); IM_DELETE(bd); } diff --git a/backends/imgui_impl_dx11.cpp b/backends/imgui_impl_dx11.cpp index c71e44d06..1b3423654 100644 --- a/backends/imgui_impl_dx11.cpp +++ b/backends/imgui_impl_dx11.cpp @@ -17,6 +17,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-06-11: DirectX11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. // 2025-05-07: DirectX11: Honor draw_data->FramebufferScale to allow for custom backends and experiment using it (consistently with other renderer backends, even though in normal condition it is not set under Windows). // 2025-01-06: DirectX11: Expose VertexConstantBuffer in ImGui_ImplDX11_RenderState. Reset projection matrix in ImDrawCallback_ResetRenderState handler. @@ -649,14 +650,17 @@ void ImGui_ImplDX11_Shutdown() ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGui_ImplDX11_InvalidateDeviceObjects(); if (bd->pFactory) { bd->pFactory->Release(); } if (bd->pd3dDevice) { bd->pd3dDevice->Release(); } if (bd->pd3dDeviceContext) { bd->pd3dDeviceContext->Release(); } + io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures); + platform_io.ClearRendererHandlers(); IM_DELETE(bd); } diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp index c84c21971..86f1180ab 100644 --- a/backends/imgui_impl_dx12.cpp +++ b/backends/imgui_impl_dx12.cpp @@ -20,6 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-06-19: Fixed build on MinGW. (#8702, #4594) // 2025-06-11: DirectX12: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. // 2025-05-07: DirectX12: Honor draw_data->FramebufferScale to allow for custom backends and experiment using it (consistently with other renderer backends, even though in normal condition it is not set under Windows). @@ -905,14 +906,15 @@ void ImGui_ImplDX12_Shutdown() ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); - // Clean up windows and device objects ImGui_ImplDX12_InvalidateDeviceObjects(); delete[] bd->pFrameResources; io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures); + platform_io.ClearRendererHandlers(); IM_DELETE(bd); } diff --git a/backends/imgui_impl_dx9.cpp b/backends/imgui_impl_dx9.cpp index 94411fabe..4a8899a62 100644 --- a/backends/imgui_impl_dx9.cpp +++ b/backends/imgui_impl_dx9.cpp @@ -17,6 +17,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-06-11: DirectX9: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. // 2024-10-07: DirectX9: Changed default texture sampler to Clamp instead of Repeat/Wrap. // 2024-02-12: DirectX9: Using RGBA format when supported by the driver to avoid CPU side conversion. (#6575) @@ -351,12 +352,15 @@ void ImGui_ImplDX9_Shutdown() ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData(); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGui_ImplDX9_InvalidateDeviceObjects(); if (bd->pd3dDevice) { bd->pd3dDevice->Release(); } + io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures); + platform_io.ClearRendererHandlers(); IM_DELETE(bd); } diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 8a646b5dd..cfe5dc6d3 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -29,6 +29,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown. // 2025-09-15: Content Scales are always reported as 1.0 on Wayland. FramebufferScale are always reported as 1.0 on X11. (#8920, #8921) // 2025-07-08: Made ImGui_ImplGlfw_GetContentScaleForWindow(), ImGui_ImplGlfw_GetContentScaleForMonitor() helpers return 1.0f on Emscripten and Android platforms, matching macOS logic. (#8742, #8733) // 2025-06-18: Added support for multiple Dear ImGui contexts. (#8676, #8239, #8069) @@ -767,7 +768,9 @@ void ImGui_ImplGlfw_Shutdown() { ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?"); + ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); if (bd->InstalledCallbacks) ImGui_ImplGlfw_RestoreCallbacks(bd->Window); @@ -790,6 +793,7 @@ void ImGui_ImplGlfw_Shutdown() io.BackendPlatformName = nullptr; io.BackendPlatformUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad); + platform_io.ClearPlatformHandlers(); ImGui_ImplGlfw_ContextMap_Remove(bd->Window); IM_DELETE(bd); } diff --git a/backends/imgui_impl_metal.mm b/backends/imgui_impl_metal.mm index a1adc6c9a..81e8be6c4 100644 --- a/backends/imgui_impl_metal.mm +++ b/backends/imgui_impl_metal.mm @@ -16,6 +16,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-06-11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplMetal_CreateFontsTexture() and ImGui_ImplMetal_DestroyFontsTexture(). // 2025-02-03: Metal: Crash fix. (#8367) // 2024-01-08: Metal: Fixed memory leaks when using metal-cpp (#8276, #8166) or when using multiple contexts (#7419). @@ -148,13 +149,16 @@ void ImGui_ImplMetal_Shutdown() ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData(); IM_UNUSED(bd); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); + ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + ImGui_ImplMetal_DestroyDeviceObjects(); ImGui_ImplMetal_DestroyBackendData(); - ImGuiIO& io = ImGui::GetIO(); io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures); + platform_io.ClearRendererHandlers(); } void ImGui_ImplMetal_NewFrame(MTLRenderPassDescriptor* renderPassDescriptor) diff --git a/backends/imgui_impl_opengl2.cpp b/backends/imgui_impl_opengl2.cpp index 477e3a043..af5618fb6 100644 --- a/backends/imgui_impl_opengl2.cpp +++ b/backends/imgui_impl_opengl2.cpp @@ -25,6 +25,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-07-15: OpenGL: Set GL_UNPACK_ALIGNMENT to 1 before updating textures. (#8802) // 2025-06-11: OpenGL: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplOpenGL2_CreateFontsTexture() and ImGui_ImplOpenGL2_DestroyFontsTexture(). // 2024-10-07: OpenGL: Changed default texture sampler to Clamp instead of Repeat/Wrap. @@ -115,11 +116,14 @@ void ImGui_ImplOpenGL2_Shutdown() ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGui_ImplOpenGL2_DestroyDeviceObjects(); + io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasTextures); + platform_io.ClearRendererHandlers(); IM_DELETE(bd); } diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index 5ab43a406..3e0e265b1 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -23,6 +23,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-07-22: OpenGL: Add and call embedded loader shutdown during ImGui_ImplOpenGL3_Shutdown() to facilitate multiple init/shutdown cycles in same process. (#8792) // 2025-07-15: OpenGL: Set GL_UNPACK_ALIGNMENT to 1 before updating textures (#8802) + restore non-WebGL/ES update path that doesn't require a CPU-side copy. // 2025-06-11: OpenGL: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplOpenGL3_CreateFontsTexture() and ImGui_ImplOpenGL3_DestroyFontsTexture(). @@ -421,11 +422,14 @@ void ImGui_ImplOpenGL3_Shutdown() ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGui_ImplOpenGL3_DestroyDeviceObjects(); + io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures); + platform_io.ClearRendererHandlers(); IM_DELETE(bd); #ifdef IMGUI_IMPL_OPENGL_LOADER_IMGL3W diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index 06a6aff8b..189dd53e6 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -29,6 +29,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown. // 2025-06-27: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support. // 2025-06-12: ImGui_ImplOSX_HandleEvent() only process event for window containing our view. (#8644) // 2025-03-21: Fill gamepad inputs and set ImGuiBackendFlags_HasGamepad regardless of ImGuiConfigFlags_NavEnableGamepad being set. @@ -514,9 +515,12 @@ void ImGui_ImplOSX_Shutdown() ImGui_ImplOSX_DestroyBackendData(); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + io.BackendPlatformName = nullptr; io.BackendPlatformUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasGamepad); + platform_io.ClearPlatformHandlers(); } static void ImGui_ImplOSX_UpdateMouseCursor() diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index 08e7988e2..acd98f641 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -21,6 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown. // 2025-09-15: Content Scales are always reported as 1.0 on Wayland. (#8921) // 2025-07-08: Made ImGui_ImplSDL2_GetContentScaleForWindow(), ImGui_ImplSDL2_GetContentScaleForDisplay() helpers return 1.0f on Emscripten and Android platforms, matching macOS logic. (#8742, #8733) // 2025-06-11: Added ImGui_ImplSDL2_GetContentScaleForWindow(SDL_Window* window) and ImGui_ImplSDL2_GetContentScaleForDisplay(int display_index) helper to facilitate making DPI-aware apps. @@ -629,6 +630,7 @@ void ImGui_ImplSDL2_Shutdown() ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); if (bd->ClipboardTextData) SDL_free(bd->ClipboardTextData); @@ -639,6 +641,7 @@ void ImGui_ImplSDL2_Shutdown() io.BackendPlatformName = nullptr; io.BackendPlatformUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad); + platform_io.ClearPlatformHandlers(); IM_DELETE(bd); } diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 17613d30a..83dc93282 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -20,6 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown. // 2025-09-15: Use SDL_GetWindowDisplayScale() on Mac to output DisplayFrameBufferScale. The function is more reliable during resolution changes e.g. going fullscreen. (#8703, #4414) // 2025-06-27: IME: avoid calling SDL_StartTextInput() again if already active. (#8727) // 2025-04-22: IME: honor ImGuiPlatformImeData->WantTextInput as an alternative way to call SDL_StartTextInput(), without IME being necessarily visible. @@ -590,6 +591,7 @@ void ImGui_ImplSDL3_Shutdown() ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData(); IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); if (bd->ClipboardTextData) SDL_free(bd->ClipboardTextData); @@ -600,6 +602,7 @@ void ImGui_ImplSDL3_Shutdown() io.BackendPlatformName = nullptr; io.BackendPlatformUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad); + platform_io.ClearPlatformHandlers(); IM_DELETE(bd); } diff --git a/backends/imgui_impl_sdlgpu3.cpp b/backends/imgui_impl_sdlgpu3.cpp index 0f8d5fa1a..3afbf3db6 100644 --- a/backends/imgui_impl_sdlgpu3.cpp +++ b/backends/imgui_impl_sdlgpu3.cpp @@ -22,6 +22,7 @@ // Calling the function is MANDATORY, otherwise the ImGui will not upload neither the vertex nor the index buffer for the GPU. See imgui_impl_sdlgpu3.cpp for more info. // CHANGELOG +// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-08-20: Added ImGui_ImplSDLGPU3_InitInfo::SwapchainComposition and ImGui_ImplSDLGPU3_InitInfo::PresentMode to configure how secondary viewports are created. // 2025-08-08: *BREAKING* Changed ImTextureID type from SDL_GPUTextureSamplerBinding* to SDL_GPUTexture*, which is more natural and easier for user to manage. If you need to change the current sampler, you can access the ImGui_ImplSDLGPU3_RenderState struct. (#8866, #8163, #7998, #7988) // 2025-08-08: Expose SamplerDefault and SamplerCurrent in ImGui_ImplSDLGPU3_RenderState. Allow callback to change sampler. @@ -641,11 +642,14 @@ void ImGui_ImplSDLGPU3_Shutdown() ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGui_ImplSDLGPU3_DestroyDeviceObjects(); + io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures); + platform_io.ClearRendererHandlers(); IM_DELETE(bd); } diff --git a/backends/imgui_impl_sdlrenderer2.cpp b/backends/imgui_impl_sdlrenderer2.cpp index 3a47f80bf..fa1e802b1 100644 --- a/backends/imgui_impl_sdlrenderer2.cpp +++ b/backends/imgui_impl_sdlrenderer2.cpp @@ -24,6 +24,7 @@ // - Introduction, links and more at the top of imgui.cpp // CHANGELOG +// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-06-11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplSDLRenderer2_CreateFontsTexture() and ImGui_ImplSDLRenderer2_DestroyFontsTexture(). // 2025-01-18: Use endian-dependent RGBA32 texture format, to match SDL_Color. // 2024-10-09: Expose selected render state in ImGui_ImplSDLRenderer2_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks. @@ -94,12 +95,14 @@ void ImGui_ImplSDLRenderer2_Shutdown() ImGui_ImplSDLRenderer2_Data* bd = ImGui_ImplSDLRenderer2_GetBackendData(); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGui_ImplSDLRenderer2_DestroyDeviceObjects(); io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures); + platform_io.ClearRendererHandlers(); IM_DELETE(bd); } diff --git a/backends/imgui_impl_sdlrenderer3.cpp b/backends/imgui_impl_sdlrenderer3.cpp index 42c173888..abf636b8d 100644 --- a/backends/imgui_impl_sdlrenderer3.cpp +++ b/backends/imgui_impl_sdlrenderer3.cpp @@ -24,6 +24,7 @@ // - Introduction, links and more at the top of imgui.cpp // CHANGELOG +// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-06-11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplSDLRenderer3_CreateFontsTexture() and ImGui_ImplSDLRenderer3_DestroyFontsTexture(). // 2025-01-18: Use endian-dependent RGBA32 texture format, to match SDL_Color. // 2024-10-09: Expose selected render state in ImGui_ImplSDLRenderer3_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks. @@ -92,12 +93,14 @@ void ImGui_ImplSDLRenderer3_Shutdown() ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData(); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGui_ImplSDLRenderer3_DestroyDeviceObjects(); io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures); + platform_io.ClearRendererHandlers(); IM_DELETE(bd); } diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index e56902254..4a0a5a947 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -27,6 +27,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-09-04: Vulkan: Added ImGui_ImplVulkan_CreateMainPipeline(). (#8110, #8111) // 2025-07-27: Vulkan: Fixed texture update corruption introduced on 2025-06-11. (#8801, #8755, #8840) // 2025-07-07: Vulkan: Fixed texture synchronization issue introduced on 2025-06-11. (#8772) @@ -1315,12 +1316,14 @@ void ImGui_ImplVulkan_Shutdown() ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGui_ImplVulkan_DestroyDeviceObjects(); io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures); + platform_io.ClearRendererHandlers(); IM_DELETE(bd); } diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index d20028d55..1f997a10a 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -18,6 +18,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-06-12: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. (#8465) // 2025-02-26: Recreate image bind groups during render. (#8426, #8046, #7765, #8027) + Update for latest webgpu-native changes. // 2024-10-14: Update Dawn support for change of string usages. (#8082, #8083) @@ -880,6 +881,7 @@ void ImGui_ImplWGPU_Shutdown() ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData(); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGui_ImplWGPU_InvalidateDeviceObjects(); delete[] bd->pFrameResources; @@ -892,6 +894,7 @@ void ImGui_ImplWGPU_Shutdown() io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures); + platform_io.ClearRendererHandlers(); IM_DELETE(bd); } diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index d7206b970..20dce139e 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -21,6 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown. // 2025-04-30: Inputs: Fixed an issue where externally losing mouse capture (due to e.g. focus loss) would fail to claim it again the next subsequent click. (#8594) // 2025-03-10: When dealing with OEM keys, use scancodes instead of translated keycodes to choose ImGuiKey values. (#7136, #7201, #7206, #7306, #7670, #7672, #8468) // 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support. @@ -222,6 +223,7 @@ void ImGui_ImplWin32_Shutdown() ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); // Unload XInput library #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD @@ -232,6 +234,7 @@ void ImGui_ImplWin32_Shutdown() io.BackendPlatformName = nullptr; io.BackendPlatformUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad); + platform_io.ClearPlatformHandlers(); IM_DELETE(bd); } diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f7ae7c991..ebb60f9a9 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,12 @@ Breaking Changes: Other Changes: +- IO: added ImGuiPlatformIO::ClearPlatformHandlers(), ClearRendererHandlers() + helpers to null all handlers. (#8945, #2769) +- Backends: all backends call ImGuiPlatformIO::ClearPlatformHandlers() and + ClearRendererHandlers() on shutdown, so as not to leave function pointers + which may be dangling when using backend in e.g. DLL. (#8945, #2769) + ----------------------------------------------------------------------- VERSION 1.92.3 (Released 2025-09-17) diff --git a/imgui.cpp b/imgui.cpp index 29774fe37..0c61f9ee1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -15453,6 +15453,23 @@ void ImGui::LocalizeRegisterEntries(const ImGuiLocEntry* entries, int count) // (this section is more complete in the 'docking' branch) //----------------------------------------------------------------------------- +void ImGuiPlatformIO::ClearPlatformHandlers() +{ + Platform_GetClipboardTextFn = NULL; + Platform_SetClipboardTextFn = NULL; + Platform_ClipboardUserData = NULL; + Platform_OpenInShellFn = NULL; + Platform_OpenInShellUserData = NULL; + Platform_SetImeDataFn = NULL; + Platform_ImeUserData = NULL; +} + +void ImGuiPlatformIO::ClearRendererHandlers() +{ + Renderer_TextureMaxWidth = Renderer_TextureMaxHeight = 0; + Renderer_RenderState = NULL; +} + ImGuiViewport* ImGui::GetMainViewport() { ImGuiContext& g = *GImGui; diff --git a/imgui.h b/imgui.h index d79a912bf..682364004 100644 --- a/imgui.h +++ b/imgui.h @@ -3970,6 +3970,13 @@ struct ImGuiPlatformIO // Textures list (the list is updated by calling ImGui::EndFrame or ImGui::Render) // The ImGui_ImplXXXX_RenderDrawData() function of each backend generally access this via ImDrawData::Textures which points to this. The array is available here mostly because backends will want to destroy textures on shutdown. ImVector Textures; // List of textures used by Dear ImGui (most often 1) + contents of external texture list is automatically appended into this. + + //------------------------------------------------------------------ + // Functions + //------------------------------------------------------------------ + + void ClearPlatformHandlers(); // Clear all Platform_XXX fields. Typically called on Platform Backend shutdown. + void ClearRendererHandlers(); // Clear all Renderer_XXX fields. Typically called on Renderer Backend shutdown. }; // (Optional) Support for IME (Input Method Editor) via the platform_io.Platform_SetImeDataFn() function. Handler is called during EndFrame(). From aa9476a38a4c4a51c65206df5a34d5f521361b9f Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 18 Sep 2025 16:22:24 +0200 Subject: [PATCH 07/39] IO: added ImGuiPlatformIO::ClearPlatformHandlers(), ClearRendererHandlers(). Backends: call those on Shutdown(). (#8945, #2769) # Conflicts: # backends/imgui_impl_dx10.cpp # backends/imgui_impl_dx11.cpp # backends/imgui_impl_dx12.cpp # backends/imgui_impl_dx9.cpp # backends/imgui_impl_glfw.cpp # backends/imgui_impl_metal.mm # backends/imgui_impl_opengl2.cpp # backends/imgui_impl_opengl3.cpp # backends/imgui_impl_osx.mm # backends/imgui_impl_sdl2.cpp # backends/imgui_impl_sdl3.cpp # backends/imgui_impl_sdlgpu3.cpp # backends/imgui_impl_vulkan.cpp # backends/imgui_impl_win32.cpp # docs/CHANGELOG.txt # imgui.h --- backends/imgui_impl_allegro5.cpp | 4 ++++ backends/imgui_impl_dx10.cpp | 4 ++++ backends/imgui_impl_dx11.cpp | 4 ++++ backends/imgui_impl_dx12.cpp | 3 +++ backends/imgui_impl_dx9.cpp | 4 ++++ backends/imgui_impl_glfw.cpp | 4 ++++ backends/imgui_impl_metal.mm | 6 +++++- backends/imgui_impl_opengl2.cpp | 4 ++++ backends/imgui_impl_opengl3.cpp | 4 ++++ backends/imgui_impl_osx.mm | 4 ++++ backends/imgui_impl_sdl2.cpp | 3 +++ backends/imgui_impl_sdl3.cpp | 3 +++ backends/imgui_impl_sdlgpu3.cpp | 4 ++++ backends/imgui_impl_sdlrenderer2.cpp | 3 +++ backends/imgui_impl_sdlrenderer3.cpp | 3 +++ backends/imgui_impl_vulkan.cpp | 3 +++ backends/imgui_impl_wgpu.cpp | 3 +++ backends/imgui_impl_win32.cpp | 3 +++ docs/CHANGELOG.txt | 6 ++++++ imgui.cpp | 17 +++++++++++++++++ imgui.h | 7 +++++++ 21 files changed, 95 insertions(+), 1 deletion(-) diff --git a/backends/imgui_impl_allegro5.cpp b/backends/imgui_impl_allegro5.cpp index 837fdc8d9..4ce8084cf 100644 --- a/backends/imgui_impl_allegro5.cpp +++ b/backends/imgui_impl_allegro5.cpp @@ -22,6 +22,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-18: Call platform_io.ClearRendererHandlers() and platform_io.ClearPlatformHandlers() on shutdown. // 2025-08-12: Inputs: fixed missing support for ImGuiKey_PrintScreen under Windows, as raw Allegro 5 does not receive it. // 2025-08-12: Added ImGui_ImplAllegro5_SetDisplay() function to change current ALLEGRO_DISPLAY, as Allegro applications often need to do that. // 2025-07-07: Fixed texture update broken on some platforms where ALLEGRO_LOCK_WRITEONLY needed all texels to be rewritten. @@ -500,6 +501,7 @@ void ImGui_ImplAllegro5_Shutdown() ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData(); IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGui_ImplAllegro5_InvalidateDeviceObjects(); if (bd->VertexDecl) @@ -510,6 +512,8 @@ void ImGui_ImplAllegro5_Shutdown() io.BackendPlatformName = io.BackendRendererName = nullptr; io.BackendPlatformUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_RendererHasTextures); + platform_io.ClearRendererHandlers(); + platform_io.ClearPlatformHandlers(); IM_DELETE(bd); } diff --git a/backends/imgui_impl_dx10.cpp b/backends/imgui_impl_dx10.cpp index 1954be6dd..dd427d335 100644 --- a/backends/imgui_impl_dx10.cpp +++ b/backends/imgui_impl_dx10.cpp @@ -18,6 +18,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-06-11: DirectX10: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. // 2025-05-07: DirectX10: Honor draw_data->FramebufferScale to allow for custom backends and experiment using it (consistently with other renderer backends, even though in normal condition it is not set under Windows). // 2025-01-06: DirectX10: Expose selected render state in ImGui_ImplDX10_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks. @@ -639,14 +640,17 @@ void ImGui_ImplDX10_Shutdown() ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData(); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGui_ImplDX10_ShutdownMultiViewportSupport(); ImGui_ImplDX10_InvalidateDeviceObjects(); if (bd->pFactory) { bd->pFactory->Release(); } if (bd->pd3dDevice) { bd->pd3dDevice->Release(); } + io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures | ImGuiBackendFlags_RendererHasViewports); + platform_io.ClearRendererHandlers(); IM_DELETE(bd); } diff --git a/backends/imgui_impl_dx11.cpp b/backends/imgui_impl_dx11.cpp index 9e6932e66..a50207749 100644 --- a/backends/imgui_impl_dx11.cpp +++ b/backends/imgui_impl_dx11.cpp @@ -19,6 +19,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-06-11: DirectX11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. // 2025-05-07: DirectX11: Honor draw_data->FramebufferScale to allow for custom backends and experiment using it (consistently with other renderer backends, even though in normal condition it is not set under Windows). // 2025-02-24: [Docking] Added undocumented ImGui_ImplDX11_SetSwapChainDescs() to configure swap chain creation for secondary viewports. @@ -660,15 +661,18 @@ void ImGui_ImplDX11_Shutdown() ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGui_ImplDX11_ShutdownMultiViewportSupport(); ImGui_ImplDX11_InvalidateDeviceObjects(); if (bd->pFactory) { bd->pFactory->Release(); } if (bd->pd3dDevice) { bd->pd3dDevice->Release(); } if (bd->pd3dDeviceContext) { bd->pd3dDeviceContext->Release(); } + io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures | ImGuiBackendFlags_RendererHasViewports); + platform_io.ClearRendererHandlers(); IM_DELETE(bd); } diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp index 8e33af1b4..4b09c63b7 100644 --- a/backends/imgui_impl_dx12.cpp +++ b/backends/imgui_impl_dx12.cpp @@ -23,6 +23,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-06-19: Fixed build on MinGW. (#8702, #4594) // 2025-06-11: DirectX12: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. // 2025-05-07: DirectX12: Honor draw_data->FramebufferScale to allow for custom backends and experiment using it (consistently with other renderer backends, even though in normal condition it is not set under Windows). @@ -983,6 +984,7 @@ void ImGui_ImplDX12_Shutdown() ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); // Manually delete main viewport render resources in-case we haven't initialized for viewports ImGuiViewport* main_viewport = ImGui::GetMainViewport(); @@ -1002,6 +1004,7 @@ void ImGui_ImplDX12_Shutdown() io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures | ImGuiBackendFlags_RendererHasViewports); + platform_io.ClearRendererHandlers(); IM_DELETE(bd); } diff --git a/backends/imgui_impl_dx9.cpp b/backends/imgui_impl_dx9.cpp index 2dde884d3..a6126e3c0 100644 --- a/backends/imgui_impl_dx9.cpp +++ b/backends/imgui_impl_dx9.cpp @@ -19,6 +19,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-06-11: DirectX9: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. // 2024-10-07: DirectX9: Changed default texture sampler to Clamp instead of Repeat/Wrap. // 2024-02-12: DirectX9: Using RGBA format when supported by the driver to avoid CPU side conversion. (#6575) @@ -367,13 +368,16 @@ void ImGui_ImplDX9_Shutdown() ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData(); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGui_ImplDX9_ShutdownMultiViewportSupport(); ImGui_ImplDX9_InvalidateDeviceObjects(); if (bd->pd3dDevice) { bd->pd3dDevice->Release(); } + io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures | ImGuiBackendFlags_RendererHasViewports); + platform_io.ClearRendererHandlers(); IM_DELETE(bd); } diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index c0f90b96d..22ab49b04 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -32,6 +32,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown. // 2025-09-15: Content Scales are always reported as 1.0 on Wayland. FramebufferScale are always reported as 1.0 on X11. (#8920, #8921) // 2025-09-10: [Docking] Improve multi-viewport behavior in tiling WMs on X11 via the ImGui_ImplGlfw_SetWindowFloating() function. Note: using GLFW backend on Linux/BSD etc. requires linking with -lX11. (#8884, #8474, #8289) // 2025-07-08: Made ImGui_ImplGlfw_GetContentScaleForWindow(), ImGui_ImplGlfw_GetContentScaleForMonitor() helpers return 1.0f on Emscripten and Android platforms, matching macOS logic. (#8742, #8733) @@ -816,7 +817,9 @@ void ImGui_ImplGlfw_Shutdown() { ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?"); + ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGui_ImplGlfw_ShutdownMultiViewportSupport(); @@ -841,6 +844,7 @@ void ImGui_ImplGlfw_Shutdown() io.BackendPlatformName = nullptr; io.BackendPlatformUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad | ImGuiBackendFlags_PlatformHasViewports | ImGuiBackendFlags_HasMouseHoveredViewport); + platform_io.ClearPlatformHandlers(); ImGui_ImplGlfw_ContextMap_Remove(bd->Window); IM_DELETE(bd); } diff --git a/backends/imgui_impl_metal.mm b/backends/imgui_impl_metal.mm index 3b57422b8..d1ac7a496 100644 --- a/backends/imgui_impl_metal.mm +++ b/backends/imgui_impl_metal.mm @@ -18,6 +18,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2025-XX-XX: Metal: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-06-11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplMetal_CreateFontsTexture() and ImGui_ImplMetal_DestroyFontsTexture(). // 2025-02-03: Metal: Crash fix. (#8367) // 2025-01-08: Metal: Fixed memory leaks when using metal-cpp (#8276, #8166) or when using multiple contexts (#7419). @@ -159,14 +160,17 @@ void ImGui_ImplMetal_Shutdown() ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData(); IM_UNUSED(bd); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); + ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + ImGui_ImplMetal_ShutdownMultiViewportSupport(); ImGui_ImplMetal_DestroyDeviceObjects(); ImGui_ImplMetal_DestroyBackendData(); - ImGuiIO& io = ImGui::GetIO(); io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures | ImGuiBackendFlags_RendererHasViewports); + platform_io.ClearRendererHandlers(); } void ImGui_ImplMetal_NewFrame(MTLRenderPassDescriptor* renderPassDescriptor) diff --git a/backends/imgui_impl_opengl2.cpp b/backends/imgui_impl_opengl2.cpp index d339218fc..c89b83c97 100644 --- a/backends/imgui_impl_opengl2.cpp +++ b/backends/imgui_impl_opengl2.cpp @@ -27,6 +27,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-07-15: OpenGL: Set GL_UNPACK_ALIGNMENT to 1 before updating textures. (#8802) // 2025-06-11: OpenGL: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplOpenGL2_CreateFontsTexture() and ImGui_ImplOpenGL2_DestroyFontsTexture(). // 2024-10-07: OpenGL: Changed default texture sampler to Clamp instead of Repeat/Wrap. @@ -124,12 +125,15 @@ void ImGui_ImplOpenGL2_Shutdown() ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGui_ImplOpenGL2_ShutdownMultiViewportSupport(); ImGui_ImplOpenGL2_DestroyDeviceObjects(); + io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasTextures | ImGuiBackendFlags_RendererHasViewports); + platform_io.ClearRendererHandlers(); IM_DELETE(bd); } diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index 3e8c65eb9..4ef9fb3d0 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -25,6 +25,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-07-22: OpenGL: Add and call embedded loader shutdown during ImGui_ImplOpenGL3_Shutdown() to facilitate multiple init/shutdown cycles in same process. (#8792) // 2025-07-15: OpenGL: Set GL_UNPACK_ALIGNMENT to 1 before updating textures (#8802) + restore non-WebGL/ES update path that doesn't require a CPU-side copy. // 2025-06-11: OpenGL: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplOpenGL3_CreateFontsTexture() and ImGui_ImplOpenGL3_DestroyFontsTexture(). @@ -430,12 +431,15 @@ void ImGui_ImplOpenGL3_Shutdown() ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGui_ImplOpenGL3_ShutdownMultiViewportSupport(); ImGui_ImplOpenGL3_DestroyDeviceObjects(); + io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures | ImGuiBackendFlags_RendererHasViewports); + platform_io.ClearRendererHandlers(); IM_DELETE(bd); #ifdef IMGUI_IMPL_OPENGL_LOADER_IMGL3W diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index a07f20e9f..a18d1aebd 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -34,6 +34,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2025-XX-XX: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown. // 2025-07-08: [Docking] Fixed multi-viewport handling broken on 2025-06-02. (#8644, #8777) // 2025-06-27: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support. // 2025-06-12: ImGui_ImplOSX_HandleEvent() only process event for window containing our view. (#8644) @@ -550,9 +551,12 @@ void ImGui_ImplOSX_Shutdown() ImGui_ImplOSX_ShutdownMultiViewportSupport(); ImGui_ImplOSX_DestroyBackendData(); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + io.BackendPlatformName = nullptr; io.BackendPlatformUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasGamepad | ImGuiBackendFlags_PlatformHasViewports); + platform_io.ClearPlatformHandlers(); } static void ImGui_ImplOSX_UpdateMouseCursor() diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index 26a8ad706..b49748b07 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -26,6 +26,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown. // 2025-09-15: Content Scales are always reported as 1.0 on Wayland. (#8921) // 2025-07-08: Made ImGui_ImplSDL2_GetContentScaleForWindow(), ImGui_ImplSDL2_GetContentScaleForDisplay() helpers return 1.0f on Emscripten and Android platforms, matching macOS logic. (#8742, #8733) // 2025-06-11: Added ImGui_ImplSDL2_GetContentScaleForWindow(SDL_Window* window) and ImGui_ImplSDL2_GetContentScaleForDisplay(int display_index) helper to facilitate making DPI-aware apps. @@ -702,6 +703,7 @@ void ImGui_ImplSDL2_Shutdown() ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGui_ImplSDL2_ShutdownMultiViewportSupport(); @@ -714,6 +716,7 @@ void ImGui_ImplSDL2_Shutdown() io.BackendPlatformName = nullptr; io.BackendPlatformUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad | ImGuiBackendFlags_PlatformHasViewports | ImGuiBackendFlags_HasMouseHoveredViewport); + platform_io.ClearPlatformHandlers(); IM_DELETE(bd); } diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 52370558a..aae620ea5 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -24,6 +24,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown. // 2025-09-15: Use SDL_GetWindowDisplayScale() on Mac to output DisplayFrameBufferScale. The function is more reliable during resolution changes e.g. going fullscreen. (#8703, #4414) // 2025-06-27: IME: avoid calling SDL_StartTextInput() again if already active. (#8727) // 2025-05-15: [Docking] Add Platform_GetWindowFramebufferScale() handler, to allow varying Retina display density on multiple monitors. @@ -662,6 +663,7 @@ void ImGui_ImplSDL3_Shutdown() ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData(); IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGui_ImplSDL3_ShutdownMultiViewportSupport(); @@ -674,6 +676,7 @@ void ImGui_ImplSDL3_Shutdown() io.BackendPlatformName = nullptr; io.BackendPlatformUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad | ImGuiBackendFlags_PlatformHasViewports | ImGuiBackendFlags_HasMouseHoveredViewport); + platform_io.ClearPlatformHandlers(); IM_DELETE(bd); } diff --git a/backends/imgui_impl_sdlgpu3.cpp b/backends/imgui_impl_sdlgpu3.cpp index 319cc747b..6523210fb 100644 --- a/backends/imgui_impl_sdlgpu3.cpp +++ b/backends/imgui_impl_sdlgpu3.cpp @@ -24,6 +24,7 @@ // CHANGELOG // 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-08-20: Added ImGui_ImplSDLGPU3_InitInfo::SwapchainComposition and ImGui_ImplSDLGPU3_InitInfo::PresentMode to configure how secondary viewports are created. // 2025-08-08: *BREAKING* Changed ImTextureID type from SDL_GPUTextureSamplerBinding* to SDL_GPUTexture*, which is more natural and easier for user to manage. If you need to change the current sampler, you can access the ImGui_ImplSDLGPU3_RenderState struct. (#8866, #8163, #7998, #7988) // 2025-08-08: Expose SamplerDefault and SamplerCurrent in ImGui_ImplSDLGPU3_RenderState. Allow callback to change sampler. @@ -649,12 +650,15 @@ void ImGui_ImplSDLGPU3_Shutdown() ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGui_ImplSDLGPU3_ShutdownMultiViewportSupport(); ImGui_ImplSDLGPU3_DestroyDeviceObjects(); + io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures | ImGuiBackendFlags_RendererHasViewports); + platform_io.ClearRendererHandlers(); IM_DELETE(bd); } diff --git a/backends/imgui_impl_sdlrenderer2.cpp b/backends/imgui_impl_sdlrenderer2.cpp index 6019b5e71..875cf92ea 100644 --- a/backends/imgui_impl_sdlrenderer2.cpp +++ b/backends/imgui_impl_sdlrenderer2.cpp @@ -26,6 +26,7 @@ // - Introduction, links and more at the top of imgui.cpp // CHANGELOG +// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-06-11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplSDLRenderer2_CreateFontsTexture() and ImGui_ImplSDLRenderer2_DestroyFontsTexture(). // 2025-01-18: Use endian-dependent RGBA32 texture format, to match SDL_Color. // 2024-10-09: Expose selected render state in ImGui_ImplSDLRenderer2_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks. @@ -96,12 +97,14 @@ void ImGui_ImplSDLRenderer2_Shutdown() ImGui_ImplSDLRenderer2_Data* bd = ImGui_ImplSDLRenderer2_GetBackendData(); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGui_ImplSDLRenderer2_DestroyDeviceObjects(); io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures); + platform_io.ClearRendererHandlers(); IM_DELETE(bd); } diff --git a/backends/imgui_impl_sdlrenderer3.cpp b/backends/imgui_impl_sdlrenderer3.cpp index b2623976b..ea2bf56e4 100644 --- a/backends/imgui_impl_sdlrenderer3.cpp +++ b/backends/imgui_impl_sdlrenderer3.cpp @@ -26,6 +26,7 @@ // - Introduction, links and more at the top of imgui.cpp // CHANGELOG +// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-06-11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplSDLRenderer3_CreateFontsTexture() and ImGui_ImplSDLRenderer3_DestroyFontsTexture(). // 2025-01-18: Use endian-dependent RGBA32 texture format, to match SDL_Color. // 2024-10-09: Expose selected render state in ImGui_ImplSDLRenderer3_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks. @@ -94,12 +95,14 @@ void ImGui_ImplSDLRenderer3_Shutdown() ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData(); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGui_ImplSDLRenderer3_DestroyDeviceObjects(); io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures); + platform_io.ClearRendererHandlers(); IM_DELETE(bd); } diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index d2554a402..be303ca6e 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -29,6 +29,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-09-04: Vulkan: Added ImGui_ImplVulkan_CreateMainPipeline(). (#8110, #8111) // 2025-07-27: Vulkan: Fixed texture update corruption introduced on 2025-06-11. (#8801, #8755, #8840) // 2025-07-07: Vulkan: Fixed texture synchronization issue introduced on 2025-06-11. (#8772) @@ -1352,6 +1353,7 @@ void ImGui_ImplVulkan_Shutdown() ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); // First destroy objects in all viewports ImGui_ImplVulkan_DestroyDeviceObjects(); @@ -1368,6 +1370,7 @@ void ImGui_ImplVulkan_Shutdown() io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures | ImGuiBackendFlags_RendererHasViewports); + platform_io.ClearRendererHandlers(); IM_DELETE(bd); } diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index f79ff17e5..90d413147 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -20,6 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-06-12: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. (#8465) // 2025-02-26: Recreate image bind groups during render. (#8426, #8046, #7765, #8027) + Update for latest webgpu-native changes. // 2024-10-14: Update Dawn support for change of string usages. (#8082, #8083) @@ -882,6 +883,7 @@ void ImGui_ImplWGPU_Shutdown() ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData(); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGui_ImplWGPU_InvalidateDeviceObjects(); delete[] bd->pFrameResources; @@ -894,6 +896,7 @@ void ImGui_ImplWGPU_Shutdown() io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures); + platform_io.ClearRendererHandlers(); IM_DELETE(bd); } diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index 4bc9c8f27..3b33169da 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -23,6 +23,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown. // 2025-06-02: [Docking] WM_DPICHANGED also apply io.ConfigDpiScaleViewports for main viewport instead of letting it be done by application code. // 2025-04-30: Inputs: Fixed an issue where externally losing mouse capture (due to e.g. focus loss) would fail to claim it again the next subsequent click. (#8594) // 2025-03-26: [Docking] Viewports: fixed an issue when closing a window from the OS close button (with io.ConfigViewportsNoDecoration = false) while user code was discarding the 'bool* p_open = false' output from Begin(). Because we allowed the Win32 window to close early, Windows destroyed it and our imgui window became not visible even though user code was still submitting it. @@ -245,6 +246,7 @@ void ImGui_ImplWin32_Shutdown() ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ::SetPropA(bd->hWnd, "IMGUI_CONTEXT", nullptr); ImGui_ImplWin32_ShutdownMultiViewportSupport(); @@ -258,6 +260,7 @@ void ImGui_ImplWin32_Shutdown() io.BackendPlatformName = nullptr; io.BackendPlatformUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad | ImGuiBackendFlags_PlatformHasViewports | ImGuiBackendFlags_HasMouseHoveredViewport); + platform_io.ClearPlatformHandlers(); IM_DELETE(bd); } diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 204ffc166..36c075eed 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,12 @@ Breaking Changes: Other Changes: +- IO: added ImGuiPlatformIO::ClearPlatformHandlers(), ClearRendererHandlers() + helpers to null all handlers. (#8945, #2769) +- Backends: all backends call ImGuiPlatformIO::ClearPlatformHandlers() and + ClearRendererHandlers() on shutdown, so as not to leave function pointers + which may be dangling when using backend in e.g. DLL. (#8945, #2769) + Docking+Viewports Branch: - Nav: fixed a crash that could occur when opening a popup following the processing diff --git a/imgui.cpp b/imgui.cpp index a10765d30..2c2b6c314 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -16224,6 +16224,23 @@ void ImGui::LocalizeRegisterEntries(const ImGuiLocEntry* entries, int count) // - DestroyPlatformWindows() //----------------------------------------------------------------------------- +void ImGuiPlatformIO::ClearPlatformHandlers() +{ + Platform_GetClipboardTextFn = NULL; + Platform_SetClipboardTextFn = NULL; + Platform_ClipboardUserData = NULL; + Platform_OpenInShellFn = NULL; + Platform_OpenInShellUserData = NULL; + Platform_SetImeDataFn = NULL; + Platform_ImeUserData = NULL; +} + +void ImGuiPlatformIO::ClearRendererHandlers() +{ + Renderer_TextureMaxWidth = Renderer_TextureMaxHeight = 0; + Renderer_RenderState = NULL; +} + ImGuiViewport* ImGui::GetMainViewport() { ImGuiContext& g = *GImGui; diff --git a/imgui.h b/imgui.h index 4d47b5e14..67c41b874 100644 --- a/imgui.h +++ b/imgui.h @@ -4219,6 +4219,13 @@ struct ImGuiPlatformIO // Viewports list (the list is updated by calling ImGui::EndFrame or ImGui::Render) // (in the future we will attempt to organize this feature to remove the need for a "main viewport") ImVector Viewports; // Main viewports, followed by all secondary viewports. + + //------------------------------------------------------------------ + // Functions + //------------------------------------------------------------------ + + void ClearPlatformHandlers(); // Clear all Platform_XXX fields. Typically called on Platform Backend shutdown. + void ClearRendererHandlers(); // Clear all Renderer_XXX fields. Typically called on Renderer Backend shutdown. }; // (Optional) This is required when enabling multi-viewport. Represent the bounds of each connected monitor/display and their DPI. From 1ad9de5aae5a7508f1bd7eb024b8f045c5844d34 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 18 Sep 2025 17:07:21 +0200 Subject: [PATCH 08/39] IO: amend ImGuiPlatformIO::ClearPlatformHandlers(), ClearRendererHandlers(). (#8945, #2769) --- imgui.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2c2b6c314..4bc16f9e1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -16228,17 +16228,31 @@ void ImGuiPlatformIO::ClearPlatformHandlers() { Platform_GetClipboardTextFn = NULL; Platform_SetClipboardTextFn = NULL; - Platform_ClipboardUserData = NULL; Platform_OpenInShellFn = NULL; - Platform_OpenInShellUserData = NULL; Platform_SetImeDataFn = NULL; - Platform_ImeUserData = NULL; + Platform_ClipboardUserData = Platform_OpenInShellUserData = Platform_ImeUserData = NULL; + Platform_CreateWindow = Platform_DestroyWindow = Platform_ShowWindow = NULL; + Platform_SetWindowPos = Platform_SetWindowSize = NULL; + Platform_GetWindowPos = Platform_GetWindowSize = Platform_GetWindowFramebufferScale = NULL; + Platform_SetWindowFocus = NULL; + Platform_GetWindowFocus = Platform_GetWindowMinimized = NULL; + Platform_SetWindowTitle = NULL; + Platform_SetWindowAlpha = NULL; + Platform_UpdateWindow = NULL; + Platform_RenderWindow = Platform_SwapBuffers = NULL; + Platform_GetWindowDpiScale = NULL; + Platform_OnChangedViewport = NULL; + Platform_GetWindowWorkAreaInsets = NULL; + Platform_CreateVkSurface = NULL; } void ImGuiPlatformIO::ClearRendererHandlers() { Renderer_TextureMaxWidth = Renderer_TextureMaxHeight = 0; Renderer_RenderState = NULL; + Renderer_CreateWindow = Renderer_DestroyWindow = NULL; + Renderer_SetWindowSize = NULL; + Renderer_RenderWindow = Renderer_SwapBuffers = NULL; } ImGuiViewport* ImGui::GetMainViewport() From 087fbf08f600d061de7531a14c496145262e7319 Mon Sep 17 00:00:00 2001 From: David Mentler Date: Mon, 22 Sep 2025 12:20:15 +0200 Subject: [PATCH 09/39] Added type formatters for the LLDB debuggers (e.g. Xcode) (#8950) --- misc/debuggers/README.txt | 4 + misc/debuggers/imgui_lldb.py | 187 +++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100644 misc/debuggers/imgui_lldb.py diff --git a/misc/debuggers/README.txt b/misc/debuggers/README.txt index 3f4ba83e3..77a78b9e5 100644 --- a/misc/debuggers/README.txt +++ b/misc/debuggers/README.txt @@ -14,3 +14,7 @@ imgui.natvis With this, types like ImVector<> will be displayed nicely in the debugger. (read comments inside file for details) +imgui_lldb.py + LLDB: synthetic children provider and summaries for Dear ImGui types. + With this, types like ImVector<> will be displayed nicely in the debugger. + (read comments inside file for details) diff --git a/misc/debuggers/imgui_lldb.py b/misc/debuggers/imgui_lldb.py new file mode 100644 index 000000000..336d3f513 --- /dev/null +++ b/misc/debuggers/imgui_lldb.py @@ -0,0 +1,187 @@ +# This file implements synthetic children providers and summaries for various ImGui types for LLDB. +# +# Useful links/documentation related to the feature: +# - https://lldb.llvm.org/use/variable.html#summary-strings +# - https://lldb.llvm.org/use/variable.html#synthetic-children +# - https://lldb.llvm.org/python_reference/lldb-module.html +# +# To use it in a debug session: +# > (lldb) command script import +# +# Alternatively you may include the above command in your ~/.lldbinit file to have the formatters +# available in all future sessions + +import lldb + +class ArraySynthBase(object): + """ + Helper baseclass aimed to reduce the boilerplate needed for "array-like" containers + """ + + def __init__(self, valobj, internal_dict): + self.valobj = valobj + + def bind_to(self, pointer, size): + array_p = pointer.GetType().GetPointeeType().GetArrayType(size).GetPointerType() + self.array = pointer.Cast(array_p).Dereference() + + def update(self): + self.array = self.valobj + + def num_children(self, max_children): + return self.array.GetNumChildren(max_children) + + def get_child_index(self, name): + return self.array.GetIndexOfChildWithName(name) + + def get_child_at_index(self, index): + return self.array.GetChildAtIndex(index) + + def has_children(self): + return self.array.MightHaveChildren() + + def get_value(self): + return self.array + +class ImVectorSynth(ArraySynthBase): + def update(self): + self.size = self.valobj.GetChildMemberWithName("Size").GetValueAsUnsigned() + self.capacity = self.valobj.GetChildMemberWithName("Capacity").GetValueAsUnsigned() + + data = self.valobj.GetChildMemberWithName("Data") + + self.bind_to(data, self.size) + + def get_summary(self): + return f"Size={self.size} Capacity={self.capacity}" + +class ImSpanSynth(ArraySynthBase): + def update(self): + data = self.valobj.GetChildMemberWithName("Data") + end = self.valobj.GetChildMemberWithName("DataEnd") + + element_size = data.GetType().GetPointeeType().GetByteSize() + array_size = end.GetValueAsUnsigned() - data.GetValueAsUnsigned() + + self.size = int(array_size / element_size) + + self.bind_to(data, self.size) + + def get_summary(self): + return f"Size={self.size}" + +class ImRectSummary(object): + def __init__(self, valobj, internal_dict): + self.valobj = valobj + + def update(self): + pass + + def get_summary(self): + min = self.valobj.GetChildMemberWithName("Min") + max = self.valobj.GetChildMemberWithName("Max") + + minX = float(min.GetChildMemberWithName("x").GetValue()) + minY = float(min.GetChildMemberWithName("y").GetValue()) + + maxX = float(max.GetChildMemberWithName("x").GetValue()) + maxY = float(max.GetChildMemberWithName("y").GetValue()) + + return f"Min=({minX}, {minY}) Max=({maxX}, {maxY}) Size=({maxX - minX}, {maxY - minY})" + +def get_active_enum_flags(valobj): + flag_set = set() + + enum_name = valobj.GetType().GetName() + "_" + enum_type = valobj.GetTarget().FindFirstType(enum_name) + + if not enum_type.IsValid(): + return flag_set + + enum_members = enum_type.GetEnumMembers() + value = valobj.GetValueAsUnsigned() + + for i in range(0, enum_members.GetSize()): + member = enum_members.GetTypeEnumMemberAtIndex(i) + + if value & member.GetValueAsUnsigned(): + flag_set.add(member.GetName().removeprefix(enum_name)) + + return flag_set + +class ImGuiWindowSummary(object): + def __init__(self, valobj, internal_dict): + self.valobj = valobj + + def update(self): + pass + + def get_summary(self): + name = self.valobj.GetChildMemberWithName("Name").GetSummary() + + active = self.valobj.GetChildMemberWithName("Active").GetValueAsUnsigned() != 0 + was_active = self.valobj.GetChildMemberWithName("WasActive").GetValueAsUnsigned() != 0 + hidden = self.valobj.GetChildMemberWithName("Hidden") != 0 + + flags = get_active_enum_flags(self.valobj.GetChildMemberWithName("Flags")) + + active = 1 if active or was_active else 0 + child = 1 if "ChildWindow" in flags else 0 + popup = 1 if "Popup" in flags else 0 + hidden = 1 if hidden else 0 + + return f"Name {name} Active {active} Child {child} Popup {popup} Hidden {hidden}" + + +def __lldb_init_module(debugger, internal_dict): + """ + This function will be automatically called by LLDB when the module is loaded, here + we register the various synthetics/summaries we have build before + """ + + category_name = "imgui" + category = debugger.GetCategory(category_name) + + # Make sure we don't accidentally keep accumulating languages or override the user's + # category enablement in Xcode, where lldb-rpc-server loads this file once for eac + # debugging session + if not category.IsValid(): + category = debugger.CreateCategory(category_name) + category.AddLanguage(lldb.eLanguageTypeC_plus_plus) + category.SetEnabled(True) + + def add_summary(typename, impl): + summary = None + + if isinstance(impl, str): + summary = lldb.SBTypeSummary.CreateWithSummaryString(impl) + summary.SetOptions(lldb.eTypeOptionCascade) + else: + # Unfortunately programmatic summary string generation is an entirely different codepath + # in LLDB. Register a convenient trampoline function which makes it look like it's part + # of the SyntheticChildrenProvider contract + summary = lldb.SBTypeSummary.CreateWithScriptCode(f''' + synth = {impl.__module__}.{impl.__qualname__}(valobj.GetNonSyntheticValue(), internal_dict) + synth.update() + + return synth.get_summary() + ''') + summary.SetOptions(lldb.eTypeOptionCascade | lldb.eTypeOptionFrontEndWantsDereference) + + category.AddTypeSummary(lldb.SBTypeNameSpecifier(typename, True), summary) + + def add_synthetic(typename, impl): + add_summary(typename, impl) + + synthetic = lldb.SBTypeSynthetic.CreateWithClassName(f"{impl.__module__}.{impl.__qualname__}") + synthetic.SetOptions(lldb.eTypeOptionCascade | lldb.eTypeOptionFrontEndWantsDereference) + + category.AddTypeSynthetic(lldb.SBTypeNameSpecifier(typename, True), synthetic) + + add_synthetic("^ImVector<.+>$", ImVectorSynth) + add_synthetic("^ImSpan<.+>$", ImSpanSynth) + + add_summary("^ImVec2$", "x=${var.x} y=${var.y}") + add_summary("^ImVec4$", "x=${var.x} y=${var.y} z=${var.z} w=${var.w}") + add_summary("^ImRect$", ImRectSummary) + add_summary("^ImGuiWindow$", ImGuiWindowSummary) From 46e6382b69e30fe85b8e77bac6c4e5604b6195d1 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 22 Sep 2025 12:26:53 +0200 Subject: [PATCH 10/39] Added type formatters for the LLDB debuggers (e.g. Xcode, Android Studio) (#8950) --- docs/CHANGELOG.txt | 3 +++ misc/README.txt | 4 ++-- misc/debuggers/README.txt | 3 ++- misc/debuggers/imgui_lldb.py | 4 +++- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ebb60f9a9..344d5e228 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -45,6 +45,9 @@ Other Changes: - IO: added ImGuiPlatformIO::ClearPlatformHandlers(), ClearRendererHandlers() helpers to null all handlers. (#8945, #2769) +- Misc: Debuggers: added type formatters for the LLDB debuggers (e.g. Xcode, + Android Studio & more) to provide nicer display for ImVec2, ImVec4, ImVector etc. + See misc/debuggers/ for details. (#8950) [@mentlerd] - Backends: all backends call ImGuiPlatformIO::ClearPlatformHandlers() and ClearRendererHandlers() on shutdown, so as not to leave function pointers which may be dangling when using backend in e.g. DLL. (#8945, #2769) diff --git a/misc/README.txt b/misc/README.txt index b4ce89f03..58c00ee8c 100644 --- a/misc/README.txt +++ b/misc/README.txt @@ -4,8 +4,8 @@ misc/cpp/ This is also an example of how you may wrap your own similar types. misc/debuggers/ - Helper files for popular debuggers. - With the .natvis file, types like ImVector<> will be displayed nicely in Visual Studio debugger. + Helper files for popular debuggers (Visual Studio, GDB, LLDB). + e.g. With the .natvis file, types like ImVector<> will be displayed nicely in Visual Studio debugger. misc/fonts/ Fonts loading/merging instructions (e.g. How to handle glyph ranges, how to merge icons fonts). diff --git a/misc/debuggers/README.txt b/misc/debuggers/README.txt index 77a78b9e5..ad6f491fe 100644 --- a/misc/debuggers/README.txt +++ b/misc/debuggers/README.txt @@ -15,6 +15,7 @@ imgui.natvis (read comments inside file for details) imgui_lldb.py - LLDB: synthetic children provider and summaries for Dear ImGui types. + LLDB-based debuggers (*): synthetic children provider and summaries for Dear ImGui types. With this, types like ImVector<> will be displayed nicely in the debugger. (read comments inside file for details) + (*) Xcode, Android Studio, may be used from VS Code, C++Builder, CLion, Eclipse etc. diff --git a/misc/debuggers/imgui_lldb.py b/misc/debuggers/imgui_lldb.py index 336d3f513..7d3c6bfcb 100644 --- a/misc/debuggers/imgui_lldb.py +++ b/misc/debuggers/imgui_lldb.py @@ -1,4 +1,6 @@ -# This file implements synthetic children providers and summaries for various ImGui types for LLDB. +# This file implements synthetic children providers and summaries for various Dear ImGui types for LLDB. +# LLDB is used by Xcode, Android Studio, and may be used from VS Code, C++Builder, CLion, Eclipse etc. + # # Useful links/documentation related to the feature: # - https://lldb.llvm.org/use/variable.html#summary-strings From ef6fe2ecee61c4da1c57f31a585a8cc27909ee76 Mon Sep 17 00:00:00 2001 From: yaz0r <363511+yaz0r@users.noreply.github.com> Date: Sat, 20 Sep 2025 10:48:54 -0700 Subject: [PATCH 11/39] CI: update Windows Vulkan scripts. (#8925) --- .github/workflows/build.yml | 17 ++-------- .../workflows/build_windows_vulkan_libs.ps1 | 33 +++++++++++++++++++ .../workflows/build_windows_vulkan_libs.yml | 22 +++++++++++++ 3 files changed, 58 insertions(+), 14 deletions(-) create mode 100644 .github/workflows/build_windows_vulkan_libs.ps1 create mode 100644 .github/workflows/build_windows_vulkan_libs.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 783615aec..1c578b76b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -35,20 +35,9 @@ jobs: Expand-Archive -Path SDL3-devel-3.2.18-VC.zip echo "SDL3_DIR=$(pwd)\SDL3-devel-3.2.18-VC\SDL3-3.2.18\" >>${env:GITHUB_ENV} - # VulkanSDK (retrieve minimal bits of the SDK from git) - $vulkanVersion = "1.4.326" - # 1. Get the vulkan headers, we will treat that folder as the sdk folder to avoid having to copy headers around - Invoke-WebRequest -Uri "https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/v$($vulkanVersion).zip" -OutFile Vulkan-Headers-$($vulkanVersion).zip - Expand-Archive -Path Vulkan-Headers-$($vulkanVersion).zip - echo "VULKAN_SDK=$(pwd)\Vulkan-Headers-$($vulkanVersion)\Vulkan-Headers-$($vulkanVersion)" >>${env:GITHUB_ENV} - # 2. Get and build the vulkan loader source code (UPDATE_DEPS=On will make it automatically fetch its dependencies) - Invoke-WebRequest -Uri "https://github.com/KhronosGroup/Vulkan-Loader/archive/refs/tags/v$($vulkanVersion).zip" -OutFile Vulkan-Loader-$($vulkanVersion).zip - Expand-Archive -Path Vulkan-Loader-$($vulkanVersion).zip - cmake -S Vulkan-Loader-$($vulkanVersion)\Vulkan-Loader-$($vulkanVersion) -B VulkanLoader-build -D UPDATE_DEPS=On - cmake --build VulkanLoader-build - # 3. Copy the built lib/dll to the expected place - mkdir Vulkan-Headers-$($vulkanVersion)\Vulkan-Headers-$($vulkanVersion)\Lib - copy VulkanLoader-build\loader\Debug\vulkan-1.* Vulkan-Headers-$($vulkanVersion)\Vulkan-Headers-$($vulkanVersion)\Lib\ + Invoke-WebRequest -Uri "https://github.com/ocornut/imgui/files/3789205/vulkan-sdk-1.1.121.2.zip" -OutFile vulkan-sdk-1.1.121.2.zip + Expand-Archive -Path vulkan-sdk-1.1.121.2.zip + echo "VULKAN_SDK=$(pwd)\vulkan-sdk-1.1.121.2\" >>${env:GITHUB_ENV} - name: Fix Projects shell: powershell diff --git a/.github/workflows/build_windows_vulkan_libs.ps1 b/.github/workflows/build_windows_vulkan_libs.ps1 new file mode 100644 index 000000000..57e542372 --- /dev/null +++ b/.github/workflows/build_windows_vulkan_libs.ps1 @@ -0,0 +1,33 @@ +# Set default vulkan version if none provided +if (-not $env:VULKAN_TAG) { $env:VULKAN_TAG = "1.4.326" } + +# Create output folder +mkdir vulkanArtifact + +# Download Vulkan Headers + +Invoke-WebRequest -Uri "https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/v$($env:VULKAN_TAG).zip" -OutFile Vulkan-Headers-$($env:VULKAN_TAG).zip +Expand-Archive -Path Vulkan-Headers-$($env:VULKAN_TAG).zip + +# Copy Vulkan Headers to artifact folder + +cp -R Vulkan-Headers-$($env:VULKAN_TAG)\Vulkan-Headers-$($env:VULKAN_TAG)\include vulkanArtifact\Include + +# Download Vulkan Loader + +Invoke-WebRequest -Uri "https://github.com/KhronosGroup/Vulkan-Loader/archive/refs/tags/v$($env:VULKAN_TAG).zip" -OutFile Vulkan-Loader-$($env:VULKAN_TAG).zip +Expand-Archive -Path Vulkan-Loader-$($env:VULKAN_TAG).zip + +# Build Vulkan Loader x64 + +cmake -S Vulkan-Loader-$($env:VULKAN_TAG)\Vulkan-Loader-$($env:VULKAN_TAG) -B VulkanLoader-build64 -D UPDATE_DEPS=On -A x64 +cmake --build VulkanLoader-build64 +mkdir vulkanArtifact\Lib +copy VulkanLoader-build64\loader\Debug\vulkan-1.lib vulkanArtifact\Lib + +# Build Vulkan Loader win32 + +cmake -S Vulkan-Loader-$($env:VULKAN_TAG)\Vulkan-Loader-$($env:VULKAN_TAG) -B VulkanLoader-build32 -D UPDATE_DEPS=On -A Win32 +cmake --build VulkanLoader-build32 +mkdir vulkanArtifact\Lib32 +copy VulkanLoader-build32\loader\Debug\vulkan-1.lib vulkanArtifact\Lib32 diff --git a/.github/workflows/build_windows_vulkan_libs.yml b/.github/workflows/build_windows_vulkan_libs.yml new file mode 100644 index 000000000..beaa2ff0a --- /dev/null +++ b/.github/workflows/build_windows_vulkan_libs.yml @@ -0,0 +1,22 @@ +name: build-windows-vulkan-libs + +on: workflow_dispatch + +jobs: + Windows: + runs-on: windows-2025 + env: + VULKAN_TAG: 1.4.326 + steps: + - uses: actions/checkout@v4 + + - name: Build Vulkan libs + shell: powershell + run: .github/workflows/build_windows_vulkan_libs.ps1 + + - uses: actions/upload-artifact@v4 + with: + name: vulkan_windows_libs_${{ env.VULKAN_TAG }} + path: vulkanArtifact + overwrite: 'true' + From dc0198a7e475fb2c1d6a8aac386aa8b0d73794f4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 22 Sep 2025 12:44:49 +0200 Subject: [PATCH 12/39] CI: update Windows Vulkan scripts. Amends. (#8925) --- .github/workflows/build.yml | 8 ++++--- .../workflows/build_windows_vulkan_libs.ps1 | 5 +++++ .../workflows/build_windows_vulkan_libs.yml | 22 ------------------- docs/CHANGELOG.txt | 1 + 4 files changed, 11 insertions(+), 25 deletions(-) delete mode 100644 .github/workflows/build_windows_vulkan_libs.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1c578b76b..92d41dac1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,6 +24,8 @@ jobs: steps: - uses: actions/checkout@v4 + # The VulkanSDK libs for Windows is manually generated using build_windows_vulkan_libs.ps1 + attached to issue #8925. + # (we have a .yml workflow in commit history if it becomes ever useful to create this on CI too) - name: Install Dependencies shell: powershell run: | @@ -35,9 +37,9 @@ jobs: Expand-Archive -Path SDL3-devel-3.2.18-VC.zip echo "SDL3_DIR=$(pwd)\SDL3-devel-3.2.18-VC\SDL3-3.2.18\" >>${env:GITHUB_ENV} - Invoke-WebRequest -Uri "https://github.com/ocornut/imgui/files/3789205/vulkan-sdk-1.1.121.2.zip" -OutFile vulkan-sdk-1.1.121.2.zip - Expand-Archive -Path vulkan-sdk-1.1.121.2.zip - echo "VULKAN_SDK=$(pwd)\vulkan-sdk-1.1.121.2\" >>${env:GITHUB_ENV} + Invoke-WebRequest -Uri "https://github.com/user-attachments/files/22464296/vulkan_windows_libs_1.4.326.zip" -OutFile vulkan_windows_libs_1.4.326.zip + Expand-Archive -Path vulkan_windows_libs_1.4.326.zip + echo "VULKAN_SDK=$(pwd)\vulkan_windows_libs_1.4.326\" >>${env:GITHUB_ENV} - name: Fix Projects shell: powershell diff --git a/.github/workflows/build_windows_vulkan_libs.ps1 b/.github/workflows/build_windows_vulkan_libs.ps1 index 57e542372..6658f5b5b 100644 --- a/.github/workflows/build_windows_vulkan_libs.ps1 +++ b/.github/workflows/build_windows_vulkan_libs.ps1 @@ -1,3 +1,8 @@ +# This is current meant to be run manually, occasionally: +# - Run then zip the contents of vulkanArtifact/ into e.g. vulkan_windows_libs_1.4.326 +# - Upload as an attachment to https://github.com/ocornut/imgui/pull/8925 then change filename in build.yml +# - There is a build_windows_vulkan_libs.yml in commit history that we removed thinking this is run so rarely we don't need to pollute CI UI with it. + # Set default vulkan version if none provided if (-not $env:VULKAN_TAG) { $env:VULKAN_TAG = "1.4.326" } diff --git a/.github/workflows/build_windows_vulkan_libs.yml b/.github/workflows/build_windows_vulkan_libs.yml deleted file mode 100644 index beaa2ff0a..000000000 --- a/.github/workflows/build_windows_vulkan_libs.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: build-windows-vulkan-libs - -on: workflow_dispatch - -jobs: - Windows: - runs-on: windows-2025 - env: - VULKAN_TAG: 1.4.326 - steps: - - uses: actions/checkout@v4 - - - name: Build Vulkan libs - shell: powershell - run: .github/workflows/build_windows_vulkan_libs.ps1 - - - uses: actions/upload-artifact@v4 - with: - name: vulkan_windows_libs_${{ env.VULKAN_TAG }} - path: vulkanArtifact - overwrite: 'true' - diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 344d5e228..636110ba2 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -48,6 +48,7 @@ Other Changes: - Misc: Debuggers: added type formatters for the LLDB debuggers (e.g. Xcode, Android Studio & more) to provide nicer display for ImVec2, ImVec4, ImVector etc. See misc/debuggers/ for details. (#8950) [@mentlerd] +- CI: Updates Windows CI scripts to generate/use VulkanSDK. (#8925, #8778) [@yaz0r] - Backends: all backends call ImGuiPlatformIO::ClearPlatformHandlers() and ClearRendererHandlers() on shutdown, so as not to leave function pointers which may be dangling when using backend in e.g. DLL. (#8945, #2769) From dfe308bc53aec28099a17cb1809c0810d3e44c03 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 22 Sep 2025 15:31:23 +0200 Subject: [PATCH 13/39] Viewports: fixed an issue inferring Z-order when attempting to merge a viewport back in the the main/hosting viewport. (#8948) --- docs/CHANGELOG.txt | 5 +++++ imgui.cpp | 21 ++++++++++++++------- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 36c075eed..e2b33e182 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -54,6 +54,11 @@ Docking+Viewports Branch: - Nav: fixed a crash that could occur when opening a popup following the processing of a global shortcut while no windows were focused (the fix done in 1.92.3 was incomplete for docking branch). +- Viewports: fixed an issue inferring Z-order when attempting to merge a viewport + back in the the main/hosting viewport. (#8948) + Note that for GLFW/SDL2/OSX backends, which do not support honoring ParentViewportID. + setting io.ConfigViewportsNoDefaultParent=true will align imgui's expectation with + what the backend does. - Viewports: DestroyContext() does not call DestroyPlatformWindows() anymore at it assumed to be unnecessary as backensd should have done it and we check that backends have been shutdown since 1.90.4. Changed into asserts. (#7175, #8945) diff --git a/imgui.cpp b/imgui.cpp index 4bc16f9e1..2ef0d0706 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -16326,6 +16326,15 @@ static bool ImGui::GetWindowAlwaysWantOwnViewport(ImGuiWindow* window) return false; } + +// Heuristic, see #8948: depends on how backends handle OS-level parenting. +static bool IsViewportAbove(ImGuiViewportP* potential_above, ImGuiViewportP* potential_below) +{ + if (potential_above->LastFocusedStampCount > potential_below->LastFocusedStampCount || potential_above->ParentViewportId == potential_below->ID) // FIXME: Should follow the ParentViewportId list. + return true; + return false; +} + static bool ImGui::UpdateTryMergeWindowIntoHostViewport(ImGuiWindow* window, ImGuiViewportP* viewport) { ImGuiContext& g = *GImGui; @@ -16340,14 +16349,12 @@ static bool ImGui::UpdateTryMergeWindowIntoHostViewport(ImGuiWindow* window, ImG if (GetWindowAlwaysWantOwnViewport(window)) return false; - // FIXME: Can't use g.WindowsFocusOrder[] for root windows only as we care about Z order. If we maintained a DisplayOrder along with FocusOrder we could.. - for (ImGuiWindow* window_behind : g.Windows) + for (ImGuiViewportP* viewport_2 : g.Viewports) { - if (window_behind == window) - break; - if (window_behind->WasActive && window_behind->ViewportOwned && !(window_behind->Flags & ImGuiWindowFlags_ChildWindow)) - if (window_behind->Viewport->GetMainRect().Overlaps(window->Rect())) - return false; + if (viewport_2 == viewport || viewport_2 == window->Viewport) + continue; + if (IsViewportAbove(viewport_2, viewport) && viewport_2->GetMainRect().Overlaps(window->Rect())) + return false; } // Move to the existing viewport, Move child/hosted windows as well (FIXME-OPT: iterate child) From a1c0836becbae04a0727d981b464f3a56867e2c1 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 22 Sep 2025 15:56:10 +0200 Subject: [PATCH 14/39] Viewports: changed default value of io.ConfigViewportsNoDefaultParent to true. (#8948, #3152, #2871) --- backends/imgui_impl_glfw.cpp | 6 +++--- backends/imgui_impl_glfw.h | 6 +++--- backends/imgui_impl_osx.h | 4 ++-- backends/imgui_impl_osx.mm | 4 ++-- backends/imgui_impl_sdl2.cpp | 2 +- backends/imgui_impl_sdl2.h | 2 +- docs/CHANGELOG.txt | 5 +++-- examples/example_win32_directx11/main.cpp | 1 - imgui.cpp | 2 +- imgui.h | 2 +- imgui_demo.cpp | 6 +++--- 11 files changed, 20 insertions(+), 20 deletions(-) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 22ab49b04..35f950f2d 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -12,9 +12,9 @@ // [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Multiple Dear ImGui contexts support. // Missing features or Issues: -// [ ] Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround. -// [ ] Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors. -// [ ] Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor). +// [ ] Platform: Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround. +// [ ] Platform: Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors. +// [ ] Platform: Multi-viewport: viewport->ParentViewportID is ignored, and therefore io.ConfigViewportsNoDefaultParent has no effect either. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. diff --git a/backends/imgui_impl_glfw.h b/backends/imgui_impl_glfw.h index 532372790..37525caef 100644 --- a/backends/imgui_impl_glfw.h +++ b/backends/imgui_impl_glfw.h @@ -12,9 +12,9 @@ // [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Multiple Dear ImGui contexts support. // Missing features or Issues: -// [ ] Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround. -// [ ] Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors. -// [ ] Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor). +// [ ] Platform: Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround. +// [ ] Platform: Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors. +// [ ] Platform: Multi-viewport: viewport->ParentViewportID is ignored, and therefore io.ConfigViewportsNoDefaultParent has no effect either. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. diff --git a/backends/imgui_impl_osx.h b/backends/imgui_impl_osx.h index b48099881..4c2cde35a 100644 --- a/backends/imgui_impl_osx.h +++ b/backends/imgui_impl_osx.h @@ -12,8 +12,8 @@ // [X] Platform: IME support. // [x] Platform: Multi-viewport / platform windows. // Missing features or Issues: -// [ ] Multi-viewport: Window size not correctly reported when enabling io.ConfigViewportsNoDecoration -// [ ] Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor). +// [ ] Platform: Multi-viewport: Window size not correctly reported when enabling io.ConfigViewportsNoDecoration +// [ ] Platform: Multi-viewport: viewport->ParentViewportID is ignored, and therefore io.ConfigViewportsNoDefaultParent has no effect either. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index a18d1aebd..2345efbe8 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -12,8 +12,8 @@ // [X] Platform: IME support. // [x] Platform: Multi-viewport / platform windows. // Missing features or Issues: -// [ ] Multi-viewport: Window size not correctly reported when enabling io.ConfigViewportsNoDecoration -// [ ] Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor). +// [ ] Platform: Multi-viewport: Window size not correctly reported when enabling io.ConfigViewportsNoDecoration +// [ ] Platform: Multi-viewport: viewport->ParentViewportID is ignored, and therefore io.ConfigViewportsNoDefaultParent has no effect either. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index b49748b07..d50b06d1c 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -13,7 +13,7 @@ // [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // Missing features or Issues: // [ ] Platform: Multi-viewport: Minimized windows seems to break mouse wheel events (at least under Windows). -// [ ] Platform: Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor). +// [ ] Platform: Multi-viewport: viewport->ParentViewportID is ignored, and therefore io.ConfigViewportsNoDefaultParent has no effect either. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. diff --git a/backends/imgui_impl_sdl2.h b/backends/imgui_impl_sdl2.h index aeecfad34..0cf005cf6 100644 --- a/backends/imgui_impl_sdl2.h +++ b/backends/imgui_impl_sdl2.h @@ -12,7 +12,7 @@ // [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // Missing features or Issues: // [ ] Platform: Multi-viewport: Minimized windows seems to break mouse wheel events (at least under Windows). -// [ ] Platform: Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor). +// [ ] Platform: Multi-viewport: viewport->ParentViewportID is ignored, and therefore io.ConfigViewportsNoDefaultParent has no effect either. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index e2b33e182..e4dbac1c8 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -54,11 +54,12 @@ Docking+Viewports Branch: - Nav: fixed a crash that could occur when opening a popup following the processing of a global shortcut while no windows were focused (the fix done in 1.92.3 was incomplete for docking branch). +- Viewports: changed default value of io.ConfigViewportsNoDefaultParent to true. (#8948) - Viewports: fixed an issue inferring Z-order when attempting to merge a viewport back in the the main/hosting viewport. (#8948) Note that for GLFW/SDL2/OSX backends, which do not support honoring ParentViewportID. - setting io.ConfigViewportsNoDefaultParent=true will align imgui's expectation with - what the backend does. + setting io.ConfigViewportsNoDefaultParent=true will align imgui's expectation + with what the backend does. - Viewports: DestroyContext() does not call DestroyPlatformWindows() anymore at it assumed to be unnecessary as backensd should have done it and we check that backends have been shutdown since 1.90.4. Changed into asserts. (#7175, #8945) diff --git a/examples/example_win32_directx11/main.cpp b/examples/example_win32_directx11/main.cpp index 26a1f880b..fff7fb2a3 100644 --- a/examples/example_win32_directx11/main.cpp +++ b/examples/example_win32_directx11/main.cpp @@ -61,7 +61,6 @@ int main(int, char**) io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows //io.ConfigViewportsNoAutoMerge = true; //io.ConfigViewportsNoTaskBarIcon = true; - //io.ConfigViewportsNoDefaultParent = true; //io.ConfigDockingAlwaysTabBar = true; //io.ConfigDockingTransparentPayload = true; diff --git a/imgui.cpp b/imgui.cpp index 2ef0d0706..ad850fafd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1575,7 +1575,7 @@ ImGuiIO::ImGuiIO() ConfigViewportsNoAutoMerge = false; ConfigViewportsNoTaskBarIcon = false; ConfigViewportsNoDecoration = true; - ConfigViewportsNoDefaultParent = false; + ConfigViewportsNoDefaultParent = true; ConfigViewportPlatformFocusSetsImGuiFocus = true; // Miscellaneous options diff --git a/imgui.h b/imgui.h index 67c41b874..f658d37b6 100644 --- a/imgui.h +++ b/imgui.h @@ -2485,7 +2485,7 @@ struct ImGuiIO bool ConfigViewportsNoAutoMerge; // = false; // Set to make all floating imgui windows always create their own viewport. Otherwise, they are merged into the main host viewports when overlapping it. May also set ImGuiViewportFlags_NoAutoMerge on individual viewport. bool ConfigViewportsNoTaskBarIcon; // = false // Disable default OS task bar icon flag for secondary viewports. When a viewport doesn't want a task bar icon, ImGuiViewportFlags_NoTaskBarIcon will be set on it. bool ConfigViewportsNoDecoration; // = true // Disable default OS window decoration flag for secondary viewports. When a viewport doesn't want window decorations, ImGuiViewportFlags_NoDecoration will be set on it. Enabling decoration can create subsequent issues at OS levels (e.g. minimum window size). - bool ConfigViewportsNoDefaultParent; // = false // Disable default OS parenting to main viewport for secondary viewports. By default, viewports are marked with ParentViewportId = , expecting the platform backend to setup a parent/child relationship between the OS windows (some backend may ignore this). Set to true if you want the default to be 0, then all viewports will be top-level OS windows. + bool ConfigViewportsNoDefaultParent; // = true // When false: set secondary viewports' ParentViewportId to main viewport ID by default. Expects the platform backend to setup a parent/child relationship between the OS windows based on this value. Some backend may ignore this. Set to true if you want viewports to automatically be parent of main viewport, otherwise all viewports will be top-level OS windows. bool ConfigViewportPlatformFocusSetsImGuiFocus; //= true // When a platform window is focused (e.g. using Alt+Tab, clicking Platform Title Bar), apply corresponding focus on imgui windows (may clear focus/active id from imgui windows location in other platform windows). In principle this is better enabled but we provide an opt-out, because some Linux window managers tend to eagerly focus windows (e.g. on mouse hover, or even a simple window pos/size change). // DPI/Scaling options diff --git a/imgui_demo.cpp b/imgui_demo.cpp index c785cc822..97ec68d56 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -551,11 +551,11 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::Checkbox("io.ConfigViewportsNoAutoMerge", &io.ConfigViewportsNoAutoMerge); ImGui::SameLine(); HelpMarker("Set to make all floating imgui windows always create their own viewport. Otherwise, they are merged into the main host viewports when overlapping it."); ImGui::Checkbox("io.ConfigViewportsNoTaskBarIcon", &io.ConfigViewportsNoTaskBarIcon); - ImGui::SameLine(); HelpMarker("Toggling this at runtime is normally unsupported (most platform backends won't refresh the task bar icon state right away)."); + ImGui::SameLine(); HelpMarker("(note: some platform backends may not reflect a change of this value for existing viewports, and may need the viewport to be recreated)"); ImGui::Checkbox("io.ConfigViewportsNoDecoration", &io.ConfigViewportsNoDecoration); - ImGui::SameLine(); HelpMarker("Toggling this at runtime is normally unsupported (most platform backends won't refresh the decoration right away)."); + ImGui::SameLine(); HelpMarker("(note: some platform backends may not reflect a change of this value for existing viewports, and may need the viewport to be recreated)"); ImGui::Checkbox("io.ConfigViewportsNoDefaultParent", &io.ConfigViewportsNoDefaultParent); - ImGui::SameLine(); HelpMarker("Toggling this at runtime is normally unsupported (most platform backends won't refresh the parenting right away)."); + ImGui::SameLine(); HelpMarker("(note: some platform backends may not reflect a change of this value for existing viewports, and may need the viewport to be recreated)"); ImGui::Checkbox("io.ConfigViewportPlatformFocusSetsImGuiFocus", &io.ConfigViewportPlatformFocusSetsImGuiFocus); ImGui::SameLine(); HelpMarker("When a platform window is focused (e.g. using Alt+Tab, clicking Platform Title Bar), apply corresponding focus on imgui windows (may clear focus/active id from imgui windows location in other platform windows). In principle this is better enabled but we provide an opt-out, because some Linux window managers tend to eagerly focus windows (e.g. on mouse hover, or even a simple window pos/size change)."); ImGui::Unindent(); From 5a66d8fd573cdc814a287e39f1e6c4ce8a5e432f Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 22 Sep 2025 16:01:18 +0200 Subject: [PATCH 15/39] (Breaking) renamed io.ConfigViewportPlatformFocusSetsImGuiFocus to io.ConfigViewportsPlatformFocusSetsImGuiFocus. (#6299, #6462) --- docs/CHANGELOG.txt | 5 +++++ imgui.cpp | 5 +++-- imgui.h | 2 +- imgui_demo.cpp | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index e4dbac1c8..88f37c07d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,6 +41,11 @@ HOW TO UPDATE? Breaking Changes: +- Viewports: for consistency with other config flags, renamed + io.ConfigViewportPlatformFocusSetsImGuiFocus + to io.ConfigViewportsPlatformFocusSetsImGuiFocus. (#6299, #6462) + It was really a typo in the first place, and introduced in 1.92.2.s + Other Changes: - IO: added ImGuiPlatformIO::ClearPlatformHandlers(), ClearRendererHandlers() diff --git a/imgui.cpp b/imgui.cpp index ad850fafd..524142633 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -400,6 +400,7 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures: - likewise io.MousePos and GetMousePos() will use OS coordinates. If you query mouse positions to interact with non-imgui coordinates you will need to offset them, e.g. subtract GetWindowViewport()->Pos. + - 2025/09/22 (1.92.4) - Viewports: renamed io.ConfigViewportPlatformFocusSetsImGuiFocus to io.ConfigViewportsPlatformFocusSetsImGuiFocus. Was a typo in the first place. (#6299, #6462) - 2025/08/08 (1.92.2) - Backends: SDL_GPU3: Changed ImTextureID type from SDL_GPUTextureSamplerBinding* to SDL_GPUTexture*, which is more natural and easier for user to manage. If you need to change the current sampler, you can access the ImGui_ImplSDLGPU3_RenderState struct. (#8866, #8163, #7998, #7988) - 2025/07/31 (1.92.2) - Tabs: Renamed ImGuiTabBarFlags_FittingPolicyResizeDown to ImGuiTabBarFlags_FittingPolicyShrink. Kept inline redirection enum (will obsolete). - 2025/06/25 (1.92.0) - Layout: commented out legacy ErrorCheckUsingSetCursorPosToExtendParentBoundaries() fallback obsoleted in 1.89 (August 2022) which allowed a SetCursorPos()/SetCursorScreenPos() call WITHOUT AN ITEM @@ -1576,7 +1577,7 @@ ImGuiIO::ImGuiIO() ConfigViewportsNoTaskBarIcon = false; ConfigViewportsNoDecoration = true; ConfigViewportsNoDefaultParent = true; - ConfigViewportPlatformFocusSetsImGuiFocus = true; + ConfigViewportsPlatformFocusSetsImGuiFocus = true; // Miscellaneous options MouseDrawCursor = false; @@ -16486,7 +16487,7 @@ static void ImGui::UpdateViewportsNewFrame() // - if focus didn't happen because we destroyed another window (#6462) // FIXME: perhaps 'FocusTopMostWindowUnderOne()' can handle the 'focused_window->Window != NULL' case as well. const bool apply_imgui_focus_on_focused_viewport = !IsAnyMouseDown() && !prev_focused_has_been_destroyed; - if (apply_imgui_focus_on_focused_viewport && g.IO.ConfigViewportPlatformFocusSetsImGuiFocus) + if (apply_imgui_focus_on_focused_viewport && g.IO.ConfigViewportsPlatformFocusSetsImGuiFocus) { focused_viewport->LastFocusedHadNavWindow |= (g.NavWindow != NULL) && (g.NavWindow->Viewport == focused_viewport); // Update so a window changing viewport won't lose focus. ImGuiFocusRequestFlags focus_request_flags = ImGuiFocusRequestFlags_UnlessBelowModal | ImGuiFocusRequestFlags_RestoreFocusedChild; diff --git a/imgui.h b/imgui.h index f658d37b6..bf249e586 100644 --- a/imgui.h +++ b/imgui.h @@ -2486,7 +2486,7 @@ struct ImGuiIO bool ConfigViewportsNoTaskBarIcon; // = false // Disable default OS task bar icon flag for secondary viewports. When a viewport doesn't want a task bar icon, ImGuiViewportFlags_NoTaskBarIcon will be set on it. bool ConfigViewportsNoDecoration; // = true // Disable default OS window decoration flag for secondary viewports. When a viewport doesn't want window decorations, ImGuiViewportFlags_NoDecoration will be set on it. Enabling decoration can create subsequent issues at OS levels (e.g. minimum window size). bool ConfigViewportsNoDefaultParent; // = true // When false: set secondary viewports' ParentViewportId to main viewport ID by default. Expects the platform backend to setup a parent/child relationship between the OS windows based on this value. Some backend may ignore this. Set to true if you want viewports to automatically be parent of main viewport, otherwise all viewports will be top-level OS windows. - bool ConfigViewportPlatformFocusSetsImGuiFocus; //= true // When a platform window is focused (e.g. using Alt+Tab, clicking Platform Title Bar), apply corresponding focus on imgui windows (may clear focus/active id from imgui windows location in other platform windows). In principle this is better enabled but we provide an opt-out, because some Linux window managers tend to eagerly focus windows (e.g. on mouse hover, or even a simple window pos/size change). + bool ConfigViewportsPlatformFocusSetsImGuiFocus;//= true // When a platform window is focused (e.g. using Alt+Tab, clicking Platform Title Bar), apply corresponding focus on imgui windows (may clear focus/active id from imgui windows location in other platform windows). In principle this is better enabled but we provide an opt-out, because some Linux window managers tend to eagerly focus windows (e.g. on mouse hover, or even a simple window pos/size change). // DPI/Scaling options // This may keep evolving during 1.92.x releases. Expect some turbulence. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 97ec68d56..19673368f 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -556,7 +556,7 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::SameLine(); HelpMarker("(note: some platform backends may not reflect a change of this value for existing viewports, and may need the viewport to be recreated)"); ImGui::Checkbox("io.ConfigViewportsNoDefaultParent", &io.ConfigViewportsNoDefaultParent); ImGui::SameLine(); HelpMarker("(note: some platform backends may not reflect a change of this value for existing viewports, and may need the viewport to be recreated)"); - ImGui::Checkbox("io.ConfigViewportPlatformFocusSetsImGuiFocus", &io.ConfigViewportPlatformFocusSetsImGuiFocus); + ImGui::Checkbox("io.ConfigViewportsPlatformFocusSetsImGuiFocus", &io.ConfigViewportsPlatformFocusSetsImGuiFocus); ImGui::SameLine(); HelpMarker("When a platform window is focused (e.g. using Alt+Tab, clicking Platform Title Bar), apply corresponding focus on imgui windows (may clear focus/active id from imgui windows location in other platform windows). In principle this is better enabled but we provide an opt-out, because some Linux window managers tend to eagerly focus windows (e.g. on mouse hover, or even a simple window pos/size change)."); ImGui::Unindent(); } From 301e652376b6bb20cfc8aedaa1e6d0ca8afe7bd9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 22 Sep 2025 16:04:59 +0200 Subject: [PATCH 16/39] Backends: OpenGL3: fixed GL loader to work on Haiku OS which does not support. (#8952) --- backends/imgui_impl_opengl3_loader.h | 4 ++++ docs/CHANGELOG.txt | 2 ++ 2 files changed, 6 insertions(+) diff --git a/backends/imgui_impl_opengl3_loader.h b/backends/imgui_impl_opengl3_loader.h index a69ac89d7..2c80cc598 100644 --- a/backends/imgui_impl_opengl3_loader.h +++ b/backends/imgui_impl_opengl3_loader.h @@ -714,7 +714,11 @@ static void close_libgl(void) static int is_library_loaded(const char* name, void** lib) { +#if defined(__HAIKU__) + *lib = NULL; // no support for RTLD_NOLOAD on Haiku. +#else *lib = dlopen(name, RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD); +#endif return *lib != NULL; } diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 636110ba2..c6b65dd2f 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -52,6 +52,8 @@ Other Changes: - Backends: all backends call ImGuiPlatformIO::ClearPlatformHandlers() and ClearRendererHandlers() on shutdown, so as not to leave function pointers which may be dangling when using backend in e.g. DLL. (#8945, #2769) +- Backends: OpenGL3: fixed GL loader to work on Haiku OS which does not support + `RTLD_NOLOAD`. (#8952) [@Xottab-DUTY] ----------------------------------------------------------------------- From 8868ad67e4fa45c21c9db2e7b9abd6e5a1849b7e Mon Sep 17 00:00:00 2001 From: Brenton Bostick Date: Mon, 22 Sep 2025 10:09:44 -0400 Subject: [PATCH 17/39] Fixed typos. (#8955) --- imgui.cpp | 2 +- imgui_draw.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 0c61f9ee1..93a77ec25 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3814,7 +3814,7 @@ void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, cons // Another overly complex function until we reorganize everything into a nice all-in-one helper. // This is made more complex because we have dissociated the layout rectangle (pos_min..pos_max) from 'ellipsis_max_x' which may be beyond it. // This is because in the context of tabs we selectively hide part of the text when the Close Button appears, but we don't want the ellipsis to move. -// (BREAKING) On 2025/04/16 we removed the 'float clip_max_x' parameters which was preceeding 'float ellipsis_max' and was the same value for 99% of users. +// (BREAKING) On 2025/04/16 we removed the 'float clip_max_x' parameters which was preceding 'float ellipsis_max' and was the same value for 99% of users. void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float ellipsis_max_x, const char* text, const char* text_end_full, const ImVec2* text_size_if_known) { ImGuiContext& g = *GImGui; diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 3beb3aa80..0946d7a46 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -5598,7 +5598,7 @@ void ImFont::RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, Im } // Note: as with every ImDrawList drawing function, this expects that the font atlas texture is bound. -// DO NOT CALL DIRECTLY THIS WILL CHANGE WIDLY IN 2025-2025. Use ImDrawList::AddText(). +// DO NOT CALL DIRECTLY THIS WILL CHANGE WILDLY IN 2025-2025. Use ImDrawList::AddText(). void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, ImDrawTextFlags flags) { // Align to be pixel perfect From a00e517a8109030e13fc911abc9ebeb026c3ef2c Mon Sep 17 00:00:00 2001 From: Tomas Jakobsson Date: Mon, 22 Sep 2025 18:55:35 +0200 Subject: [PATCH 18/39] Examples: added SDL3+DirectX11 example. (#8956, #8957) --- .../example_sdl3_directx11/build_win32.bat | 8 + .../example_sdl3_directx11.vcxproj | 187 +++++++++++++ .../example_sdl3_directx11.vcxproj.filters | 63 +++++ examples/example_sdl3_directx11/main.cpp | 253 ++++++++++++++++++ examples/imgui_examples.sln | 10 + 5 files changed, 521 insertions(+) create mode 100644 examples/example_sdl3_directx11/build_win32.bat create mode 100644 examples/example_sdl3_directx11/example_sdl3_directx11.vcxproj create mode 100644 examples/example_sdl3_directx11/example_sdl3_directx11.vcxproj.filters create mode 100644 examples/example_sdl3_directx11/main.cpp diff --git a/examples/example_sdl3_directx11/build_win32.bat b/examples/example_sdl3_directx11/build_win32.bat new file mode 100644 index 000000000..b84b01f1a --- /dev/null +++ b/examples/example_sdl3_directx11/build_win32.bat @@ -0,0 +1,8 @@ +@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. +@set OUT_DIR=Debug +@set OUT_EXE=example_sdl3_directx11 +@set INCLUDES=/I..\.. /I..\..\backends /I%SDL3_DIR%\include /I "%WindowsSdkDir%Include\um" /I "%WindowsSdkDir%Include\shared" /I "%DXSDK_DIR%Include" +@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl3.cpp ..\..\backends\imgui_impl_dx11.cpp ..\..\imgui*.cpp +@set LIBS=/LIBPATH:%SDL3_DIR%\lib\x86 SDL3.lib /LIBPATH:"%DXSDK_DIR%/Lib/x86" d3d11.lib d3dcompiler.lib shell32.lib +mkdir %OUT_DIR% +cl /nologo /Zi /MD /utf-8 %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console diff --git a/examples/example_sdl3_directx11/example_sdl3_directx11.vcxproj b/examples/example_sdl3_directx11/example_sdl3_directx11.vcxproj new file mode 100644 index 000000000..340901c3d --- /dev/null +++ b/examples/example_sdl3_directx11/example_sdl3_directx11.vcxproj @@ -0,0 +1,187 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {009DAC16-1A9C-47BE-9770-A30A046E8090} + example_sdl3_directx11 + 8.1 + example_sdl3_directx11 + + + + Application + true + MultiByte + v140 + + + Application + true + MultiByte + v140 + + + Application + false + true + MultiByte + v140 + + + Application + false + true + MultiByte + v140 + + + + + + + + + + + + + + + + + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + + Level4 + Disabled + ..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include;%(AdditionalIncludeDirectories) + /utf-8 %(AdditionalOptions) + + + true + %SDL3_DIR%\lib\x86;$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories) + SDL3.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies) + Console + msvcrt.lib + + + + + Level4 + Disabled + ..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include;%(AdditionalIncludeDirectories) + /utf-8 %(AdditionalOptions) + + + true + %SDL3_DIR%\lib\x64;$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories) + SDL3.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies) + Console + msvcrt.lib + + + + + Level4 + MaxSpeed + true + true + ..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include;%(AdditionalIncludeDirectories) + false + /utf-8 %(AdditionalOptions) + + + true + true + true + %SDL3_DIR%\lib\x86;$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories) + SDL3.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies) + Console + + + + + + + Level4 + MaxSpeed + true + true + ..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include;%(AdditionalIncludeDirectories) + false + /utf-8 %(AdditionalOptions) + + + true + true + true + %SDL3_DIR%\lib\x64;$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories) + SDL3.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies) + Console + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/example_sdl3_directx11/example_sdl3_directx11.vcxproj.filters b/examples/example_sdl3_directx11/example_sdl3_directx11.vcxproj.filters new file mode 100644 index 000000000..0579b7a64 --- /dev/null +++ b/examples/example_sdl3_directx11/example_sdl3_directx11.vcxproj.filters @@ -0,0 +1,63 @@ + + + + + {0587d7a3-f2ce-4d56-b84f-a0005d3bfce6} + + + {08e36723-ce4f-4cff-9662-c40801cf1acf} + + + + + imgui + + + imgui + + + imgui + + + sources + + + sources + + + + + imgui + + + sources + + + imgui + + + imgui + + + imgui + + + imgui + + + sources + + + sources + + + + + + imgui + + + imgui + + + \ No newline at end of file diff --git a/examples/example_sdl3_directx11/main.cpp b/examples/example_sdl3_directx11/main.cpp new file mode 100644 index 000000000..a604e3076 --- /dev/null +++ b/examples/example_sdl3_directx11/main.cpp @@ -0,0 +1,253 @@ +// Dear ImGui: standalone example application for SDL3 + DirectX 11 +// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan/Metal graphics context creation, etc.) + +// Learn about Dear ImGui: +// - FAQ https://dearimgui.com/faq +// - Getting Started https://dearimgui.com/getting-started +// - Documentation https://dearimgui.com/docs (same as your local docs/ folder). +// - Introduction, links and more at the top of imgui.cpp + +#include "imgui.h" +#include "imgui_impl_sdl3.h" +#include "imgui_impl_dx11.h" +#include +#include +#include + +// Data +static ID3D11Device* g_pd3dDevice = nullptr; +static ID3D11DeviceContext* g_pd3dDeviceContext = nullptr; +static IDXGISwapChain* g_pSwapChain = nullptr; +static ID3D11RenderTargetView* g_mainRenderTargetView = nullptr; + +// Forward declarations of helper functions +bool CreateDeviceD3D(HWND hWnd); +void CleanupDeviceD3D(); +void CreateRenderTarget(); +void CleanupRenderTarget(); + +// Main code +int main(int, char**) +{ + // Setup SDL + // [If using SDL_MAIN_USE_CALLBACKS: all code below until the main loop starts would likely be your SDL_AppInit() function] + if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) + { + printf("Error: SDL_Init(): %s\n", SDL_GetError()); + return -1; + } + + // Setup window + float main_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay()); + SDL_WindowFlags window_flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN | SDL_WINDOW_HIGH_PIXEL_DENSITY; + SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+DirectX11 example", (int)(1280 * main_scale), (int)(720 * main_scale), window_flags); + if (window == nullptr) + { + printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); + return -1; + } + + SDL_PropertiesID props = SDL_GetWindowProperties(window); + HWND hwnd = (HWND)SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL); + + // Initialize Direct3D + if (!CreateDeviceD3D(hwnd)) + { + CleanupDeviceD3D(); + return 1; + } + + SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); + SDL_ShowWindow(window); + + // 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 + + // Setup Dear ImGui style + ImGui::StyleColorsDark(); + //ImGui::StyleColorsLight(); + + // Setup scaling + ImGuiStyle& style = ImGui::GetStyle(); + style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again) + style.FontScaleDpi = main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose) + + // Setup Platform/Renderer backends + ImGui_ImplSDL3_InitForD3D(window); + ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext); + + // Load Fonts + // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. + // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. + // - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). + // - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering. + // - Read 'docs/FONTS.md' for more instructions and details. If you like the default font but want it to scale better, consider using the 'ProggyVector' from the same author! + // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! + //style.FontSizeBase = 20.0f; + //io.Fonts->AddFontDefault(); + //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf"); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf"); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf"); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf"); + //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf"); + //IM_ASSERT(font != nullptr); + + // Our state + bool show_demo_window = true; + bool show_another_window = false; + ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); + + // Main loop + bool done = false; + while (!done) + { + // Poll and handle events (inputs, window resize, etc.) + // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. + // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. + // [If using SDL_MAIN_USE_CALLBACKS: call ImGui_ImplSDL3_ProcessEvent() from your SDL_AppEvent() function] + SDL_Event event; + while (SDL_PollEvent(&event)) + { + ImGui_ImplSDL3_ProcessEvent(&event); + if (event.type == SDL_EVENT_QUIT) + done = true; + if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED && event.window.windowID == SDL_GetWindowID(window)) + done = true; + if (event.type == SDL_EVENT_WINDOW_RESIZED && event.window.windowID == SDL_GetWindowID(window)) + { + // Release all outstanding references to the swap chain's buffers before resizing. + CleanupRenderTarget(); + g_pSwapChain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, 0); + CreateRenderTarget(); + } + } + + // [If using SDL_MAIN_USE_CALLBACKS: all code below would likely be your SDL_AppIterate() function] + if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) + { + SDL_Delay(10); + continue; + } + + // Start the Dear ImGui frame + ImGui_ImplDX11_NewFrame(); + ImGui_ImplSDL3_NewFrame(); + ImGui::NewFrame(); + + // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). + if (show_demo_window) + ImGui::ShowDemoWindow(&show_demo_window); + + // 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window. + { + static float f = 0.0f; + static int counter = 0; + + ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it. + + ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too) + ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state + ImGui::Checkbox("Another Window", &show_another_window); + + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color + + if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated) + counter++; + ImGui::SameLine(); + ImGui::Text("counter = %d", counter); + + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); + ImGui::End(); + } + + // 3. Show another simple window. + if (show_another_window) + { + ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked) + ImGui::Text("Hello from another window!"); + if (ImGui::Button("Close Me")) + show_another_window = false; + ImGui::End(); + } + + // Rendering + ImGui::Render(); + const float clear_color_with_alpha[4] = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w }; + g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, nullptr); + g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, clear_color_with_alpha); + ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); + + g_pSwapChain->Present(1, 0); // Present with vsync + //g_pSwapChain->Present(0, 0); // Present without vsync + } + + // Cleanup + ImGui_ImplDX11_Shutdown(); + ImGui_ImplSDL3_Shutdown(); + ImGui::DestroyContext(); + + CleanupDeviceD3D(); + SDL_DestroyWindow(window); + SDL_Quit(); + + return 0; +} + +// Helper functions to use DirectX11 +bool CreateDeviceD3D(HWND hWnd) +{ + // Setup swap chain + DXGI_SWAP_CHAIN_DESC sd; + ZeroMemory(&sd, sizeof(sd)); + sd.BufferCount = 2; + sd.BufferDesc.Width = 0; + sd.BufferDesc.Height = 0; + sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + sd.BufferDesc.RefreshRate.Numerator = 60; + sd.BufferDesc.RefreshRate.Denominator = 1; + sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; + sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + sd.OutputWindow = hWnd; + sd.SampleDesc.Count = 1; + sd.SampleDesc.Quality = 0; + sd.Windowed = TRUE; + sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + + UINT createDeviceFlags = 0; + //createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; + D3D_FEATURE_LEVEL featureLevel; + const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, }; + if (D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext) != S_OK) + return false; + + CreateRenderTarget(); + return true; +} + +void CleanupDeviceD3D() +{ + CleanupRenderTarget(); + if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = nullptr; } + if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = nullptr; } + if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = nullptr; } +} + +void CreateRenderTarget() +{ + ID3D11Texture2D* pBackBuffer; + g_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer)); + g_pd3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, &g_mainRenderTargetView); + pBackBuffer->Release(); +} + +void CleanupRenderTarget() +{ + if (g_mainRenderTargetView) { g_mainRenderTargetView->Release(); g_mainRenderTargetView = nullptr; } +} diff --git a/examples/imgui_examples.sln b/examples/imgui_examples.sln index cf1c5ad50..8ad1a2566 100644 --- a/examples/imgui_examples.sln +++ b/examples/imgui_examples.sln @@ -39,6 +39,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_win32_vulkan", "exa EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl3_sdlgpu3", "example_sdl3_sdlgpu3\example_sdl3_sdlgpu3.vcxproj", "{C22CB6F8-39A5-4DDA-90ED-4ACA4E81E1E5}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl3_directx11", "example_sdl3_directx11\example_sdl3_directx11.vcxproj", "{009DAC16-1A9C-47BE-9770-A30A046E8090}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -191,6 +193,14 @@ Global {C22CB6F8-39A5-4DDA-90ED-4ACA4E81E1E5}.Release|Win32.Build.0 = Release|Win32 {C22CB6F8-39A5-4DDA-90ED-4ACA4E81E1E5}.Release|x64.ActiveCfg = Release|x64 {C22CB6F8-39A5-4DDA-90ED-4ACA4E81E1E5}.Release|x64.Build.0 = Release|x64 + {009DAC16-1A9C-47BE-9770-A30A046E8090}.Debug|Win32.ActiveCfg = Debug|Win32 + {009DAC16-1A9C-47BE-9770-A30A046E8090}.Debug|Win32.Build.0 = Debug|Win32 + {009DAC16-1A9C-47BE-9770-A30A046E8090}.Debug|x64.ActiveCfg = Debug|x64 + {009DAC16-1A9C-47BE-9770-A30A046E8090}.Debug|x64.Build.0 = Debug|x64 + {009DAC16-1A9C-47BE-9770-A30A046E8090}.Release|Win32.ActiveCfg = Release|Win32 + {009DAC16-1A9C-47BE-9770-A30A046E8090}.Release|Win32.Build.0 = Release|Win32 + {009DAC16-1A9C-47BE-9770-A30A046E8090}.Release|x64.ActiveCfg = Release|x64 + {009DAC16-1A9C-47BE-9770-A30A046E8090}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From d701ffb4780467ca3a40e63ee7774346b9b61758 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 22 Sep 2025 21:37:41 +0200 Subject: [PATCH 19/39] Examples: added SDL3+DirectX11 example. Minor amends + fix both SDL2/SDL3+DirectX11 to allow WARP driver. (#8956, #8957) --- docs/CHANGELOG.txt | 5 ++++- docs/EXAMPLES.md | 6 +++++- examples/example_sdl2_directx11/main.cpp | 5 ++++- examples/example_sdl3_directx11/main.cpp | 12 ++++++++---- examples/example_win32_directx10/main.cpp | 2 +- examples/example_win32_directx11/main.cpp | 2 +- examples/example_win32_directx12/main.cpp | 2 +- examples/example_win32_directx9/main.cpp | 2 +- examples/example_win32_opengl3/main.cpp | 2 +- examples/example_win32_vulkan/main.cpp | 2 +- 10 files changed, 27 insertions(+), 13 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index c6b65dd2f..87cf826c1 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -53,7 +53,10 @@ Other Changes: ClearRendererHandlers() on shutdown, so as not to leave function pointers which may be dangling when using backend in e.g. DLL. (#8945, #2769) - Backends: OpenGL3: fixed GL loader to work on Haiku OS which does not support - `RTLD_NOLOAD`. (#8952) [@Xottab-DUTY] + `RTLD_NOLOAD`. (#8952) [@Xottab-DUTY, @threedeyes] +- Examples: SDL2+DirectX11: Try WARP software driver if hardware driver is + not available. (#5924, #5562) +- Examples: SDL3+DirectX11: Added SDL3+DirectX11 example. (#8956, #8957) [@tomaz82] ----------------------------------------------------------------------- diff --git a/docs/EXAMPLES.md b/docs/EXAMPLES.md index 038bd5858..f61297fd1 100644 --- a/docs/EXAMPLES.md +++ b/docs/EXAMPLES.md @@ -149,8 +149,12 @@ SDL2 (Win32, Mac, Linux, etc.) + Vulkan example.
This is quite long and tedious, because: Vulkan.
For this example, the main.cpp file exceptionally use helpers function from imgui_impl_vulkan.h/cpp. +[example_sdl3_directx11/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_directx11/)
+SDL3 + DirectX11 examples, Windows only.
+= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_dx11.cpp
+ [example_sdl3_metal/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_metal/)
-SDL3 + Metal example (Mac).
+SDL3 + Metal example, Mac only.
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_metal.mm
[example_sdl3_opengl3/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_opengl3/)
diff --git a/examples/example_sdl2_directx11/main.cpp b/examples/example_sdl2_directx11/main.cpp index a2b39f362..ec6602f83 100644 --- a/examples/example_sdl2_directx11/main.cpp +++ b/examples/example_sdl2_directx11/main.cpp @@ -230,7 +230,10 @@ bool CreateDeviceD3D(HWND hWnd) //createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; D3D_FEATURE_LEVEL featureLevel; const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, }; - if (D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext) != S_OK) + HRESULT res = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext); + if (res == DXGI_ERROR_UNSUPPORTED) // Try high-performance WARP software driver if hardware is not available. + res = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_WARP, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext); + if (res != S_OK) return false; CreateRenderTarget(); diff --git a/examples/example_sdl3_directx11/main.cpp b/examples/example_sdl3_directx11/main.cpp index a604e3076..bc8889b8c 100644 --- a/examples/example_sdl3_directx11/main.cpp +++ b/examples/example_sdl3_directx11/main.cpp @@ -11,7 +11,7 @@ #include "imgui_impl_sdl3.h" #include "imgui_impl_dx11.h" #include -#include +#include // printf #include // Data @@ -40,7 +40,7 @@ int main(int, char**) // Setup window float main_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay()); SDL_WindowFlags window_flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN | SDL_WINDOW_HIGH_PIXEL_DENSITY; - SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+DirectX11 example", (int)(1280 * main_scale), (int)(720 * main_scale), window_flags); + SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+DirectX11 example", (int)(1280 * main_scale), (int)(800 * main_scale), window_flags); if (window == nullptr) { printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); @@ -54,7 +54,7 @@ int main(int, char**) if (!CreateDeviceD3D(hwnd)) { CleanupDeviceD3D(); - return 1; + return -1; } SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); @@ -189,6 +189,7 @@ int main(int, char**) } // Cleanup + // [If using SDL_MAIN_USE_CALLBACKS: all code below would likely be your SDL_AppQuit() function] ImGui_ImplDX11_Shutdown(); ImGui_ImplSDL3_Shutdown(); ImGui::DestroyContext(); @@ -224,7 +225,10 @@ bool CreateDeviceD3D(HWND hWnd) //createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; D3D_FEATURE_LEVEL featureLevel; const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, }; - if (D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext) != S_OK) + HRESULT res = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext); + if (res == DXGI_ERROR_UNSUPPORTED) // Try high-performance WARP software driver if hardware is not available. + res = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_WARP, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext); + if (res != S_OK) return false; CreateRenderTarget(); diff --git a/examples/example_win32_directx10/main.cpp b/examples/example_win32_directx10/main.cpp index 12f10ab4d..6fd10f83d 100644 --- a/examples/example_win32_directx10/main.cpp +++ b/examples/example_win32_directx10/main.cpp @@ -1,4 +1,4 @@ -// Dear ImGui: standalone example application for DirectX 10 +// Dear ImGui: standalone example application for Windows API + DirectX 10 // Learn about Dear ImGui: // - FAQ https://dearimgui.com/faq diff --git a/examples/example_win32_directx11/main.cpp b/examples/example_win32_directx11/main.cpp index 2b85895f7..5b88007a9 100644 --- a/examples/example_win32_directx11/main.cpp +++ b/examples/example_win32_directx11/main.cpp @@ -1,4 +1,4 @@ -// Dear ImGui: standalone example application for DirectX 11 +// Dear ImGui: standalone example application for Windows API + DirectX 11 // Learn about Dear ImGui: // - FAQ https://dearimgui.com/faq diff --git a/examples/example_win32_directx12/main.cpp b/examples/example_win32_directx12/main.cpp index 4ff7c54e5..a5396d31b 100644 --- a/examples/example_win32_directx12/main.cpp +++ b/examples/example_win32_directx12/main.cpp @@ -1,4 +1,4 @@ -// Dear ImGui: standalone example application for DirectX 12 +// Dear ImGui: standalone example application for Windows API + DirectX 12 // Learn about Dear ImGui: // - FAQ https://dearimgui.com/faq diff --git a/examples/example_win32_directx9/main.cpp b/examples/example_win32_directx9/main.cpp index 66369d242..b330efdeb 100644 --- a/examples/example_win32_directx9/main.cpp +++ b/examples/example_win32_directx9/main.cpp @@ -1,4 +1,4 @@ -// Dear ImGui: standalone example application for DirectX 9 +// Dear ImGui: standalone example application for Windows API + DirectX 9 // Learn about Dear ImGui: // - FAQ https://dearimgui.com/faq diff --git a/examples/example_win32_opengl3/main.cpp b/examples/example_win32_opengl3/main.cpp index 648d0d969..9ad74d61f 100644 --- a/examples/example_win32_opengl3/main.cpp +++ b/examples/example_win32_opengl3/main.cpp @@ -1,4 +1,4 @@ -// Dear ImGui: standalone example application for Win32 + OpenGL 3 +// Dear ImGui: standalone example application for Windows API + OpenGL // Learn about Dear ImGui: // - FAQ https://dearimgui.com/faq diff --git a/examples/example_win32_vulkan/main.cpp b/examples/example_win32_vulkan/main.cpp index b4b3a0860..6063437d8 100644 --- a/examples/example_win32_vulkan/main.cpp +++ b/examples/example_win32_vulkan/main.cpp @@ -1,4 +1,4 @@ -// Dear ImGui: standalone example application for Win32 + Vulkan +// Dear ImGui: standalone example application for Windows API + Vulkan // Learn about Dear ImGui: // - FAQ https://dearimgui.com/faq From e639ff392c2d9b0edf89464702ec566f2af2607e Mon Sep 17 00:00:00 2001 From: Olivier Gerard Date: Thu, 18 Sep 2025 17:31:28 +0200 Subject: [PATCH 20/39] Backends: Vulkna: added ImGui_ImplVulkan_GetWindowDataFromViewport() accessor/helper. (#8946, #8940) --- backends/imgui_impl_vulkan.cpp | 7 +++++++ backends/imgui_impl_vulkan.h | 1 + docs/CHANGELOG.txt | 2 ++ 3 files changed, 10 insertions(+) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index be303ca6e..40eca3fbe 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -29,6 +29,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2025-09-22: [Docking] Added ImGui_ImplVulkanH_GetWindowDataFromViewport() accessor/helper. (#8946, #8940) // 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-09-04: Vulkan: Added ImGui_ImplVulkan_CreateMainPipeline(). (#8110, #8111) // 2025-07-27: Vulkan: Fixed texture update corruption introduced on 2025-06-11. (#8801, #8755, #8840) @@ -1947,6 +1948,12 @@ void ImGui_ImplVulkanH_DestroyAllViewportsRenderBuffers(VkDevice device, const V ImGui_ImplVulkan_DestroyWindowRenderBuffers(device, &vd->RenderBuffers, allocator); } +ImGui_ImplVulkanH_Window* ImGui_ImplVulkanH_GetWindowDataFromViewport(ImGuiViewport* viewport) +{ + ImGui_ImplVulkan_ViewportData* vd = (ImGui_ImplVulkan_ViewportData*)viewport->RendererUserData; + return vd ? &vd->Window : nullptr; +} + //-------------------------------------------------------------------------------------------------------- // MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT // This is an _advanced_ and _optional_ feature, allowing the backend to create and handle multiple viewports simultaneously. diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index 66b0a8b05..c18298d42 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -183,6 +183,7 @@ IMGUI_IMPL_API VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysic IMGUI_IMPL_API VkPhysicalDevice ImGui_ImplVulkanH_SelectPhysicalDevice(VkInstance instance); IMGUI_IMPL_API uint32_t ImGui_ImplVulkanH_SelectQueueFamilyIndex(VkPhysicalDevice physical_device); IMGUI_IMPL_API int ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(VkPresentModeKHR present_mode); +IMGUI_IMPL_API ImGui_ImplVulkanH_Window* ImGui_ImplVulkanH_GetWindowDataFromViewport(ImGuiViewport* viewport); // Access to Vulkan objects associated with a viewport (e.g to export a screenshot) // Helper structure to hold the data needed by one rendering frame // (Used by example's main.cpp. Used by multi-viewport features. Probably NOT used by your own engine/app.) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 88f37c07d..0e319f796 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -68,6 +68,8 @@ Docking+Viewports Branch: - Viewports: DestroyContext() does not call DestroyPlatformWindows() anymore at it assumed to be unnecessary as backensd should have done it and we check that backends have been shutdown since 1.90.4. Changed into asserts. (#7175, #8945) +- Backends: Vulkan: Added ImGui_ImplVulkanH_GetWindowDataFromViewport() accessor/helper. + (#8946, #8940) [@olivier-gerard] ----------------------------------------------------------------------- From 8a0888c76312ea85aacb563630fe4c15df0c84fc Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 23 Sep 2025 16:11:22 +0200 Subject: [PATCH 21/39] Viewports: fix ImGuiWindowFlags_NoBringToFrontOnFocus being ignored when windows first appear. (#7008) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 0e319f796..99b364ebd 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -59,6 +59,8 @@ Docking+Viewports Branch: - Nav: fixed a crash that could occur when opening a popup following the processing of a global shortcut while no windows were focused (the fix done in 1.92.3 was incomplete for docking branch). +- Viewports: fixed a bug where ImGuiWindowFlags_NoBringToFrontOnFocus would effectivey + be ignored when windows first appear and viewports are enabled. (#7008) [@jshofmann] - Viewports: changed default value of io.ConfigViewportsNoDefaultParent to true. (#8948) - Viewports: fixed an issue inferring Z-order when attempting to merge a viewport back in the the main/hosting viewport. (#8948) diff --git a/imgui.cpp b/imgui.cpp index 524142633..a011a07af 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -16365,7 +16365,8 @@ static bool ImGui::UpdateTryMergeWindowIntoHostViewport(ImGuiWindow* window, ImG if (g.Windows[n]->Viewport == old_viewport) SetWindowViewport(g.Windows[n], viewport); SetWindowViewport(window, viewport); - BringWindowToDisplayFront(window); + if ((window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus) == 0) + BringWindowToDisplayFront(window); return true; } From 5f6eaa5278aa56075f6b001105e2e7dde9cc82ce Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 23 Sep 2025 16:29:30 +0200 Subject: [PATCH 22/39] Backends: Win32: minor optimization not submitting gamepad input if packet number has not changed. (#8556) To be honest I don't believe this is valuable as an optimization, but it makes debug stepping a little nicer. --- backends/imgui_impl_win32.cpp | 5 +++++ docs/CHANGELOG.txt | 2 ++ 2 files changed, 7 insertions(+) diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index 20dce139e..a8b9ff8ee 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -21,6 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-23: Inputs: Minor optimization not submitting gamepad input if packet number has not changed. // 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown. // 2025-04-30: Inputs: Fixed an issue where externally losing mouse capture (due to e.g. focus loss) would fail to claim it again the next subsequent click. (#8594) // 2025-03-10: When dealing with OEM keys, use scancodes instead of translated keycodes to choose ImGuiKey values. (#7136, #7201, #7206, #7306, #7670, #7672, #8468) @@ -124,6 +125,7 @@ struct ImGui_ImplWin32_Data HMODULE XInputDLL; PFN_XInputGetCapabilities XInputGetCapabilities; PFN_XInputGetState XInputGetState; + DWORD XInputPacketNumber; #endif ImGui_ImplWin32_Data() { memset((void*)this, 0, sizeof(*this)); } @@ -355,6 +357,9 @@ static void ImGui_ImplWin32_UpdateGamepads(ImGuiIO& io) if (!bd->HasGamepad || bd->XInputGetState == nullptr || bd->XInputGetState(0, &xinput_state) != ERROR_SUCCESS) return; io.BackendFlags |= ImGuiBackendFlags_HasGamepad; + if (bd->XInputPacketNumber != 0 && bd->XInputPacketNumber == xinput_state.dwPacketNumber) + return; + bd->XInputPacketNumber = xinput_state.dwPacketNumber; #define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V) #define MAP_BUTTON(KEY_NO, BUTTON_ENUM) { io.AddKeyEvent(KEY_NO, (gamepad.wButtons & BUTTON_ENUM) != 0); } diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 87cf826c1..8f2aaac11 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -54,6 +54,8 @@ Other Changes: which may be dangling when using backend in e.g. DLL. (#8945, #2769) - Backends: OpenGL3: fixed GL loader to work on Haiku OS which does not support `RTLD_NOLOAD`. (#8952) [@Xottab-DUTY, @threedeyes] +- Backends: Win32: minor optimization not submitting gamepad io again if + XInput's dwPacketNumber has not changed. (#8556) [@MidTerm-CN] - Examples: SDL2+DirectX11: Try WARP software driver if hardware driver is not available. (#5924, #5562) - Examples: SDL3+DirectX11: Added SDL3+DirectX11 example. (#8956, #8957) [@tomaz82] From 82e9a5e47dfbb1954e4c3293302506a0a9f7b29d Mon Sep 17 00:00:00 2001 From: Aleksi Juvani Date: Wed, 19 Mar 2025 14:11:01 +0100 Subject: [PATCH 23/39] Windows: add resize grips for child windows with both ResizeX+ResizeY. (#8501) --- imgui.cpp | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 93a77ec25..c3977a21e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6647,8 +6647,19 @@ static ImGuiCol GetWindowBgColorIdx(ImGuiWindow* window) return ImGuiCol_WindowBg; } -static void CalcResizePosSizeFromAnyCorner(ImGuiWindow* window, const ImVec2& corner_target, const ImVec2& corner_norm, ImVec2* out_pos, ImVec2* out_size) +static void CalcResizePosSizeFromAnyCorner(ImGuiWindow* window, ImVec2 corner_target, const ImVec2& corner_norm, ImVec2* out_pos, ImVec2* out_size) { + if (window->Flags & ImGuiWindowFlags_ChildWindow) // Clamp resizing of childs within parent + { + ImGuiWindow* parent_window = window->ParentWindow; + ImGuiWindowFlags parent_flags = parent_window->Flags; + ImRect corner_limit_rect = parent_window->InnerRect; + corner_limit_rect.Expand(ImVec2(-ImMax(parent_window->WindowPadding.x, parent_window->WindowBorderSize), -ImMax(parent_window->WindowPadding.y, parent_window->WindowBorderSize))); + if ((parent_flags & (ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar)) == 0 || (parent_flags & ImGuiWindowFlags_NoScrollbar)) + corner_target.x = ImClamp(corner_target.x, corner_limit_rect.Min.x, corner_limit_rect.Max.x); + if (parent_flags & ImGuiWindowFlags_NoScrollbar) + corner_target.y = ImClamp(corner_target.y, corner_limit_rect.Min.y, corner_limit_rect.Max.y); + } ImVec2 pos_min = ImLerp(corner_target, window->Pos, corner_norm); // Expected window upper-left ImVec2 pos_max = ImLerp(window->Pos + window->Size, corner_target, corner_norm); // Expected window lower-right ImVec2 size_expected = pos_max - pos_min; @@ -6868,17 +6879,6 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si ImVec2 clamp_min(border_n == ImGuiDir_Right ? clamp_rect.Min.x : -FLT_MAX, border_n == ImGuiDir_Down || (border_n == ImGuiDir_Up && window_move_from_title_bar) ? clamp_rect.Min.y : -FLT_MAX); ImVec2 clamp_max(border_n == ImGuiDir_Left ? clamp_rect.Max.x : +FLT_MAX, border_n == ImGuiDir_Up ? clamp_rect.Max.y : +FLT_MAX); border_target = ImClamp(border_target, clamp_min, clamp_max); - if (flags & ImGuiWindowFlags_ChildWindow) // Clamp resizing of childs within parent - { - ImGuiWindow* parent_window = window->ParentWindow; - ImGuiWindowFlags parent_flags = parent_window->Flags; - ImRect border_limit_rect = parent_window->InnerRect; - border_limit_rect.Expand(ImVec2(-ImMax(parent_window->WindowPadding.x, parent_window->WindowBorderSize), -ImMax(parent_window->WindowPadding.y, parent_window->WindowBorderSize))); - if ((axis == ImGuiAxis_X) && ((parent_flags & (ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar)) == 0 || (parent_flags & ImGuiWindowFlags_NoScrollbar))) - border_target.x = ImClamp(border_target.x, border_limit_rect.Min.x, border_limit_rect.Max.x); - if ((axis == ImGuiAxis_Y) && (parent_flags & ImGuiWindowFlags_NoScrollbar)) - border_target.y = ImClamp(border_target.y, border_limit_rect.Min.y, border_limit_rect.Max.y); - } if (!ignore_resize) CalcResizePosSizeFromAnyCorner(window, border_target, ImMin(def.SegmentN1, def.SegmentN2), &pos_target, &size_target); } @@ -7657,7 +7657,19 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Handle manual resize: Resize Grips, Borders, Gamepad int border_hovered = -1, border_held = -1; ImU32 resize_grip_col[4] = {}; - const int resize_grip_count = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup)) ? 0 : g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // Allow resize from lower-left if we have the mouse cursor feedback for it. + int resize_grip_count; + if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup)) { + // Child windows can only be resized when they have the flags set. The resize grip allows resizing in both directions, so it should appear only if both flags are set. + if ((window->ChildFlags & ImGuiChildFlags_ResizeX) && (window->ChildFlags & ImGuiChildFlags_ResizeY)) { + resize_grip_count = 1; // Child windows can only be resized in the layout direction, that is rightwards and downwards. + } + else { + resize_grip_count = 0; + } + } + else { + resize_grip_count = g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // Allow resize from lower-left if we have the mouse cursor feedback for it. + } const float resize_grip_draw_size = IM_TRUNC(ImMax(g.FontSize * 1.10f, window->WindowRounding + 1.0f + g.FontSize * 0.2f)); if (handle_borders_and_resize_grips && !window->Collapsed) if (int auto_fit_mask = UpdateWindowManualResize(window, size_auto_fit, &border_hovered, &border_held, resize_grip_count, &resize_grip_col[0], visibility_rect)) From e1aea42e45165350029d54683c363b623efd7469 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 23 Sep 2025 16:54:59 +0200 Subject: [PATCH 24/39] Windows: add resize grips for child windows with both ResizeX+ResizeY. Amends. (#8501) --- docs/CHANGELOG.txt | 3 +++ imgui.cpp | 32 ++++++++++++++------------------ 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 8f2aaac11..f1a9ff6da 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,9 @@ Breaking Changes: Other Changes: +- Windows: added lower-right resize grip on child windows using both + ImGuiChildFlags_ResizeX and ImGuiChildFlags_ResizeY flags. (#8501) [@aleksijuvani] + The grip is not visible before hovering to reduce clutter. - IO: added ImGuiPlatformIO::ClearPlatformHandlers(), ClearRendererHandlers() helpers to null all handlers. (#8945, #2769) - Misc: Debuggers: added type formatters for the LLDB debuggers (e.g. Xcode, diff --git a/imgui.cpp b/imgui.cpp index c3977a21e..417747bca 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6647,18 +6647,19 @@ static ImGuiCol GetWindowBgColorIdx(ImGuiWindow* window) return ImGuiCol_WindowBg; } -static void CalcResizePosSizeFromAnyCorner(ImGuiWindow* window, ImVec2 corner_target, const ImVec2& corner_norm, ImVec2* out_pos, ImVec2* out_size) +static void CalcResizePosSizeFromAnyCorner(ImGuiWindow* window, const ImVec2& corner_target_arg, const ImVec2& corner_norm, ImVec2* out_pos, ImVec2* out_size) { + ImVec2 corner_target = corner_target_arg; if (window->Flags & ImGuiWindowFlags_ChildWindow) // Clamp resizing of childs within parent { ImGuiWindow* parent_window = window->ParentWindow; ImGuiWindowFlags parent_flags = parent_window->Flags; - ImRect corner_limit_rect = parent_window->InnerRect; - corner_limit_rect.Expand(ImVec2(-ImMax(parent_window->WindowPadding.x, parent_window->WindowBorderSize), -ImMax(parent_window->WindowPadding.y, parent_window->WindowBorderSize))); + ImRect limit_rect = parent_window->InnerRect; + limit_rect.Expand(ImVec2(-ImMax(parent_window->WindowPadding.x, parent_window->WindowBorderSize), -ImMax(parent_window->WindowPadding.y, parent_window->WindowBorderSize))); if ((parent_flags & (ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar)) == 0 || (parent_flags & ImGuiWindowFlags_NoScrollbar)) - corner_target.x = ImClamp(corner_target.x, corner_limit_rect.Min.x, corner_limit_rect.Max.x); + corner_target.x = ImClamp(corner_target.x, limit_rect.Min.x, limit_rect.Max.x); if (parent_flags & ImGuiWindowFlags_NoScrollbar) - corner_target.y = ImClamp(corner_target.y, corner_limit_rect.Min.y, corner_limit_rect.Max.y); + corner_target.y = ImClamp(corner_target.y, limit_rect.Min.y, limit_rect.Max.y); } ImVec2 pos_min = ImLerp(corner_target, window->Pos, corner_norm); // Expected window upper-left ImVec2 pos_max = ImLerp(window->Pos + window->Size, corner_target, corner_norm); // Expected window lower-right @@ -6804,7 +6805,8 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si } // Only lower-left grip is visible before hovering/activating - if (resize_grip_n == 0 || held || hovered) + const bool resize_grip_visible = held || hovered || (resize_grip_n == 0 && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0); + if (resize_grip_visible) resize_grip_col[resize_grip_n] = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip); } @@ -7655,21 +7657,15 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) handle_borders_and_resize_grips = false; // Handle manual resize: Resize Grips, Borders, Gamepad + // Child windows can only be resized when they have the flags set. The resize grip allows resizing in both directions, so it should appear only if both flags are set. int border_hovered = -1, border_held = -1; ImU32 resize_grip_col[4] = {}; int resize_grip_count; - if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup)) { - // Child windows can only be resized when they have the flags set. The resize grip allows resizing in both directions, so it should appear only if both flags are set. - if ((window->ChildFlags & ImGuiChildFlags_ResizeX) && (window->ChildFlags & ImGuiChildFlags_ResizeY)) { - resize_grip_count = 1; // Child windows can only be resized in the layout direction, that is rightwards and downwards. - } - else { - resize_grip_count = 0; - } - } - else { - resize_grip_count = g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // Allow resize from lower-left if we have the mouse cursor feedback for it. - } + if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup)) + resize_grip_count = ((window->ChildFlags & ImGuiChildFlags_ResizeX) && (window->ChildFlags & ImGuiChildFlags_ResizeY)) ? 1 : 0; + else + resize_grip_count = g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // Allow resize from lower-left if we have the mouse cursor feedback for it. + const float resize_grip_draw_size = IM_TRUNC(ImMax(g.FontSize * 1.10f, window->WindowRounding + 1.0f + g.FontSize * 0.2f)); if (handle_borders_and_resize_grips && !window->Collapsed) if (int auto_fit_mask = UpdateWindowManualResize(window, size_auto_fit, &border_hovered, &border_held, resize_grip_count, &resize_grip_col[0], visibility_rect)) From e06b5dfe129ccfc3ab6f28e68bee34cb64a72345 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Sep 2025 14:17:24 +0200 Subject: [PATCH 25/39] Backends: SDL2,SDL3: Shallow tweaks. Toward fallback focused mouse handler to be a closer match docking version. --- backends/imgui_impl_sdl2.cpp | 13 ++++++++----- backends/imgui_impl_sdl3.cpp | 10 ++++++---- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index acd98f641..a116063ad 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -674,15 +674,18 @@ static void ImGui_ImplSDL2_UpdateMouseData() if (io.WantSetMousePos) SDL_WarpMouseInWindow(bd->Window, (int)io.MousePos.x, (int)io.MousePos.y); - // (Optional) Fallback to provide mouse position when focused (SDL_MOUSEMOTION already provides this when hovered or captured) + // (Optional) Fallback to provide unclamped mouse position when focused (SDL_MOUSEMOTION already provides this when hovered or captured) const bool is_relative_mouse_mode = SDL_GetRelativeMouseMode() != 0; if (bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0 && !is_relative_mouse_mode) { // Single-viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window) - int window_x, window_y, mouse_x_global, mouse_y_global; - SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global); - SDL_GetWindowPosition(bd->Window, &window_x, &window_y); - io.AddMousePosEvent((float)(mouse_x_global - window_x), (float)(mouse_y_global - window_y)); + int mouse_x, mouse_y; + int window_x, window_y; + SDL_GetGlobalMouseState(&mouse_x, &mouse_y); + SDL_GetWindowPosition(focused_window, &window_x, &window_y); + mouse_x -= window_x; + mouse_y -= window_y; + io.AddMousePosEvent((float)mouse_x, (float)mouse_y); } } } diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 83dc93282..871e7aba4 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -636,16 +636,18 @@ static void ImGui_ImplSDL3_UpdateMouseData() if (io.WantSetMousePos) SDL_WarpMouseInWindow(bd->Window, io.MousePos.x, io.MousePos.y); - // (Optional) Fallback to provide mouse position when focused (SDL_EVENT_MOUSE_MOTION already provides this when hovered or captured) + // (Optional) Fallback to provide unclamped mouse position when focused (SDL_EVENT_MOUSE_MOTION already provides this when hovered or captured) const bool is_relative_mouse_mode = SDL_GetWindowRelativeMouseMode(bd->Window); if (bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0 && !is_relative_mouse_mode) { // Single-viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window) - float mouse_x_global, mouse_y_global; + float mouse_x, mouse_y; int window_x, window_y; - SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global); + SDL_GetGlobalMouseState(&mouse_x, &mouse_y); SDL_GetWindowPosition(focused_window, &window_x, &window_y); - io.AddMousePosEvent(mouse_x_global - window_x, mouse_y_global - window_y); + mouse_x -= window_x; + mouse_y -= window_y; + io.AddMousePosEvent(mouse_x, mouse_y); } } } From f61a7ef222747779a81dfa6cc44c648eb944fa6a Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Sep 2025 14:48:33 +0200 Subject: [PATCH 26/39] Backends: SDL2,SDL3: avoid using the SDL_GetGlobalMouseState() path when one of our window is hovered. Fix mouse coordinate issue in fullscreen apps with macOS notch + better X11 perfs. (#7919, #7786) --- backends/imgui_impl_sdl2.cpp | 6 ++++-- backends/imgui_impl_sdl3.cpp | 6 ++++-- docs/CHANGELOG.txt | 4 ++++ imgui.h | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index a116063ad..53336995e 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -21,6 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-24: Skip using the SDL_GetGlobalMouseState() state when one of our window is hovered, as the SDL_MOUSEMOTION data is reliable. Fix macOS notch mouse coordinates issue in fullscreen mode + better perf on X11. (#7919, #7786) // 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown. // 2025-09-15: Content Scales are always reported as 1.0 on Wayland. (#8921) // 2025-07-08: Made ImGui_ImplSDL2_GetContentScaleForWindow(), ImGui_ImplSDL2_GetContentScaleForDisplay() helpers return 1.0f on Emscripten and Android platforms, matching macOS logic. (#8742, #8733) @@ -674,9 +675,10 @@ static void ImGui_ImplSDL2_UpdateMouseData() if (io.WantSetMousePos) SDL_WarpMouseInWindow(bd->Window, (int)io.MousePos.x, (int)io.MousePos.y); - // (Optional) Fallback to provide unclamped mouse position when focused (SDL_MOUSEMOTION already provides this when hovered or captured) + // (Optional) Fallback to provide unclamped mouse position when focused but not hovered (SDL_MOUSEMOTION already provides this when hovered or captured) + SDL_Window* hovered_window = SDL_GetMouseFocus(); const bool is_relative_mouse_mode = SDL_GetRelativeMouseMode() != 0; - if (bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0 && !is_relative_mouse_mode) + if (hovered_window == NULL && bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0 && !is_relative_mouse_mode) { // Single-viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window) int mouse_x, mouse_y; diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 871e7aba4..77e5b94a8 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -20,6 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-24: Skip using the SDL_GetGlobalMouseState() state when one of our window is hovered, as the SDL_EVENT_MOUSE_MOTION data is reliable. Fix macOS notch mouse coordinates issue in fullscreen mode + better perf on X11. (#7919, #7786) // 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown. // 2025-09-15: Use SDL_GetWindowDisplayScale() on Mac to output DisplayFrameBufferScale. The function is more reliable during resolution changes e.g. going fullscreen. (#8703, #4414) // 2025-06-27: IME: avoid calling SDL_StartTextInput() again if already active. (#8727) @@ -636,9 +637,10 @@ static void ImGui_ImplSDL3_UpdateMouseData() if (io.WantSetMousePos) SDL_WarpMouseInWindow(bd->Window, io.MousePos.x, io.MousePos.y); - // (Optional) Fallback to provide unclamped mouse position when focused (SDL_EVENT_MOUSE_MOTION already provides this when hovered or captured) + // (Optional) Fallback to provide unclamped mouse position when focused but not hovered (SDL_EVENT_MOUSE_MOTION already provides this when hovered or captured) + SDL_Window* hovered_window = SDL_GetMouseFocus(); const bool is_relative_mouse_mode = SDL_GetWindowRelativeMouseMode(bd->Window); - if (bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0 && !is_relative_mouse_mode) + if (hovered_window == NULL && bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0 && !is_relative_mouse_mode) { // Single-viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window) float mouse_x, mouse_y; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f1a9ff6da..9906174a5 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -57,6 +57,10 @@ Other Changes: which may be dangling when using backend in e.g. DLL. (#8945, #2769) - Backends: OpenGL3: fixed GL loader to work on Haiku OS which does not support `RTLD_NOLOAD`. (#8952) [@Xottab-DUTY, @threedeyes] +- Backends: SDL2,SDL3: avoid using the SDL_GetGlobalMouseState() path when one of our + window is hovered, as the event data is reliable and enough in this case. + - Fix mouse coordinates issue in fullscreen apps with macOS notch. (#7919, #7786) + - Better perf on X11 as querying global position requires a round trip to X11 server. - Backends: Win32: minor optimization not submitting gamepad io again if XInput's dwPacketNumber has not changed. (#8556) [@MidTerm-CN] - Examples: SDL2+DirectX11: Try WARP software driver if hardware driver is diff --git a/imgui.h b/imgui.h index 682364004..f04e8c0e4 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.92.4 WIP" -#define IMGUI_VERSION_NUM 19231 +#define IMGUI_VERSION_NUM 19232 #define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000 #define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198 From 719ea9c2284069c52135f1400d7fb7640e3d54ad Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Sep 2025 15:00:24 +0200 Subject: [PATCH 27/39] Comments --- backends/imgui_impl_sdl2.cpp | 1 + backends/imgui_impl_sdl3.cpp | 1 + docs/CHANGELOG.txt | 1 + 3 files changed, 3 insertions(+) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index 53336995e..12a8438b9 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -676,6 +676,7 @@ static void ImGui_ImplSDL2_UpdateMouseData() SDL_WarpMouseInWindow(bd->Window, (int)io.MousePos.x, (int)io.MousePos.y); // (Optional) Fallback to provide unclamped mouse position when focused but not hovered (SDL_MOUSEMOTION already provides this when hovered or captured) + // Note that SDL_GetGlobalMouseState() is in theory slow on X11, but this only runs on rather specific cases. If a problem we may provide a way to opt-out this feature. SDL_Window* hovered_window = SDL_GetMouseFocus(); const bool is_relative_mouse_mode = SDL_GetRelativeMouseMode() != 0; if (hovered_window == NULL && bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0 && !is_relative_mouse_mode) diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 77e5b94a8..564131a4d 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -638,6 +638,7 @@ static void ImGui_ImplSDL3_UpdateMouseData() SDL_WarpMouseInWindow(bd->Window, io.MousePos.x, io.MousePos.y); // (Optional) Fallback to provide unclamped mouse position when focused but not hovered (SDL_EVENT_MOUSE_MOTION already provides this when hovered or captured) + // Note that SDL_GetGlobalMouseState() is in theory slow on X11, but this only runs on rather specific cases. If a problem we may provide a way to opt-out this feature. SDL_Window* hovered_window = SDL_GetMouseFocus(); const bool is_relative_mouse_mode = SDL_GetWindowRelativeMouseMode(bd->Window); if (hovered_window == NULL && bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0 && !is_relative_mouse_mode) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 9906174a5..3357a1547 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -60,6 +60,7 @@ Other Changes: - Backends: SDL2,SDL3: avoid using the SDL_GetGlobalMouseState() path when one of our window is hovered, as the event data is reliable and enough in this case. - Fix mouse coordinates issue in fullscreen apps with macOS notch. (#7919, #7786) + - Essentially a working for SDL3 bug which will be fixed in SDL 3.3.0. - Better perf on X11 as querying global position requires a round trip to X11 server. - Backends: Win32: minor optimization not submitting gamepad io again if XInput's dwPacketNumber has not changed. (#8556) [@MidTerm-CN] From 28837ec64234849f8c6ff39f55e960be0b0e11ad Mon Sep 17 00:00:00 2001 From: Tomas Jakobsson Date: Wed, 24 Sep 2025 15:03:14 +0200 Subject: [PATCH 28/39] Examples: added SDL3+DirectX11 example (docking). (#8956, #8957) --- examples/example_sdl3_directx11/main.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/examples/example_sdl3_directx11/main.cpp b/examples/example_sdl3_directx11/main.cpp index bc8889b8c..681c30dbc 100644 --- a/examples/example_sdl3_directx11/main.cpp +++ b/examples/example_sdl3_directx11/main.cpp @@ -66,6 +66,10 @@ int main(int, char**) 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; // Setup Dear ImGui style ImGui::StyleColorsDark(); @@ -75,6 +79,15 @@ int main(int, char**) ImGuiStyle& style = ImGui::GetStyle(); style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again) style.FontScaleDpi = main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose) + io.ConfigDpiScaleFonts = true; // [Experimental] Automatically overwrite style.FontScaleDpi in Begin() when Monitor DPI changes. This will scale fonts but _NOT_ scale sizes/padding for now. + io.ConfigDpiScaleViewports = true; // [Experimental] Scale Dear ImGui and Platform Windows when Monitor DPI changes. + + // When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones. + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) + { + style.WindowRounding = 0.0f; + style.Colors[ImGuiCol_WindowBg].w = 1.0f; + } // Setup Platform/Renderer backends ImGui_ImplSDL3_InitForD3D(window); @@ -184,6 +197,13 @@ int main(int, char**) g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, clear_color_with_alpha); ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); + // Update and Render additional Platform Windows + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) + { + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindowsDefault(); + } + g_pSwapChain->Present(1, 0); // Present with vsync //g_pSwapChain->Present(0, 0); // Present without vsync } From 940627d008b8f0584b7f50d24574537cf24a32e1 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Sep 2025 15:29:00 +0200 Subject: [PATCH 29/39] Backends: SDL2: Fixed build for Emscripten and SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE=0 platforms. Amend e06b5df. --- backends/imgui_impl_sdl2.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index 12a8438b9..c2dae4053 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -667,6 +667,7 @@ static void ImGui_ImplSDL2_UpdateMouseData() SDL_Window* focused_window = SDL_GetKeyboardFocus(); const bool is_app_focused = (bd->Window == focused_window); #else + SDL_Window* focused_window = bd->Window; const bool is_app_focused = (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_INPUT_FOCUS) != 0; // SDL 2.0.3 and non-windowed systems: single-viewport only #endif if (is_app_focused) From cee40f8af99eee390eb17adfe79a68a26d83c436 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Sep 2025 17:48:48 +0200 Subject: [PATCH 30/39] Examples: made examples's main.cpp consistent with returning 1 on error. --- docs/CHANGELOG.txt | 1 + examples/example_sdl2_directx11/main.cpp | 4 ++-- examples/example_sdl2_metal/main.mm | 2 +- examples/example_sdl2_opengl2/main.cpp | 4 ++-- examples/example_sdl2_opengl3/main.cpp | 6 +++--- examples/example_sdl2_sdlrenderer2/main.cpp | 6 +++--- examples/example_sdl2_vulkan/main.cpp | 4 ++-- examples/example_sdl3_directx11/main.cpp | 6 +++--- examples/example_sdl3_metal/main.mm | 10 +++++----- examples/example_sdl3_opengl3/main.cpp | 6 +++--- examples/example_sdl3_sdlgpu3/main.cpp | 8 ++++---- examples/example_sdl3_sdlrenderer3/main.cpp | 6 +++--- examples/example_sdl3_vulkan/main.cpp | 4 ++-- 13 files changed, 34 insertions(+), 33 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 3357a1547..04ca7ef1c 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -67,6 +67,7 @@ Other Changes: - Examples: SDL2+DirectX11: Try WARP software driver if hardware driver is not available. (#5924, #5562) - Examples: SDL3+DirectX11: Added SDL3+DirectX11 example. (#8956, #8957) [@tomaz82] +- Examples: made examples's main.cpp consistent with returning 1 on error. ----------------------------------------------------------------------- diff --git a/examples/example_sdl2_directx11/main.cpp b/examples/example_sdl2_directx11/main.cpp index ec6602f83..e14085dd3 100644 --- a/examples/example_sdl2_directx11/main.cpp +++ b/examples/example_sdl2_directx11/main.cpp @@ -39,7 +39,7 @@ int main(int, char**) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) { printf("Error: %s\n", SDL_GetError()); - return -1; + return 1; } // From 2.0.18: Enable native IME. @@ -54,7 +54,7 @@ int main(int, char**) if (window == nullptr) { printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); - return -1; + return 1; } SDL_SysWMinfo wmInfo; diff --git a/examples/example_sdl2_metal/main.mm b/examples/example_sdl2_metal/main.mm index 80c7e7b1a..0f60d771d 100644 --- a/examples/example_sdl2_metal/main.mm +++ b/examples/example_sdl2_metal/main.mm @@ -51,7 +51,7 @@ int main(int, char**) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) { printf("Error: %s\n", SDL_GetError()); - return -1; + return 1; } // Inform SDL that we will be using metal for rendering. Without this hint initialization of metal renderer may fail. diff --git a/examples/example_sdl2_opengl2/main.cpp b/examples/example_sdl2_opengl2/main.cpp index a06b58c8c..327780e20 100644 --- a/examples/example_sdl2_opengl2/main.cpp +++ b/examples/example_sdl2_opengl2/main.cpp @@ -31,7 +31,7 @@ int main(int, char**) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) { printf("Error: %s\n", SDL_GetError()); - return -1; + return 1; } // From 2.0.18: Enable native IME. @@ -51,7 +51,7 @@ int main(int, char**) if (window == nullptr) { printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); - return -1; + return 1; } SDL_GLContext gl_context = SDL_GL_CreateContext(window); diff --git a/examples/example_sdl2_opengl3/main.cpp b/examples/example_sdl2_opengl3/main.cpp index 96631271b..4a655ac61 100644 --- a/examples/example_sdl2_opengl3/main.cpp +++ b/examples/example_sdl2_opengl3/main.cpp @@ -36,7 +36,7 @@ int main(int, char**) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) { printf("Error: %s\n", SDL_GetError()); - return -1; + return 1; } // Decide GL+GLSL versions @@ -85,14 +85,14 @@ int main(int, char**) if (window == nullptr) { printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); - return -1; + return 1; } SDL_GLContext gl_context = SDL_GL_CreateContext(window); if (gl_context == nullptr) { printf("Error: SDL_GL_CreateContext(): %s\n", SDL_GetError()); - return -1; + return 1; } SDL_GL_MakeCurrent(window, gl_context); diff --git a/examples/example_sdl2_sdlrenderer2/main.cpp b/examples/example_sdl2_sdlrenderer2/main.cpp index 60b365e6e..214f6f471 100644 --- a/examples/example_sdl2_sdlrenderer2/main.cpp +++ b/examples/example_sdl2_sdlrenderer2/main.cpp @@ -33,7 +33,7 @@ int main(int, char**) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) { printf("Error: %s\n", SDL_GetError()); - return -1; + return 1; } // From 2.0.18: Enable native IME. @@ -48,13 +48,13 @@ int main(int, char**) if (window == nullptr) { printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); - return -1; + return 1; } SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); if (renderer == nullptr) { SDL_Log("Error creating SDL_Renderer!"); - return -1; + return 1; } //SDL_RendererInfo info; //SDL_GetRendererInfo(renderer, &info); diff --git a/examples/example_sdl2_vulkan/main.cpp b/examples/example_sdl2_vulkan/main.cpp index 4a1228058..8dd505889 100644 --- a/examples/example_sdl2_vulkan/main.cpp +++ b/examples/example_sdl2_vulkan/main.cpp @@ -349,7 +349,7 @@ int main(int, char**) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) { printf("Error: %s\n", SDL_GetError()); - return -1; + return 1; } // From 2.0.18: Enable native IME. @@ -364,7 +364,7 @@ int main(int, char**) if (window == nullptr) { printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); - return -1; + return 1; } ImVector extensions; diff --git a/examples/example_sdl3_directx11/main.cpp b/examples/example_sdl3_directx11/main.cpp index bc8889b8c..946992409 100644 --- a/examples/example_sdl3_directx11/main.cpp +++ b/examples/example_sdl3_directx11/main.cpp @@ -34,7 +34,7 @@ int main(int, char**) if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) { printf("Error: SDL_Init(): %s\n", SDL_GetError()); - return -1; + return 1; } // Setup window @@ -44,7 +44,7 @@ int main(int, char**) if (window == nullptr) { printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); - return -1; + return 1; } SDL_PropertiesID props = SDL_GetWindowProperties(window); @@ -54,7 +54,7 @@ int main(int, char**) if (!CreateDeviceD3D(hwnd)) { CleanupDeviceD3D(); - return -1; + return 1; } SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); diff --git a/examples/example_sdl3_metal/main.mm b/examples/example_sdl3_metal/main.mm index 022e0f432..1dd80d010 100644 --- a/examples/example_sdl3_metal/main.mm +++ b/examples/example_sdl3_metal/main.mm @@ -24,7 +24,7 @@ int main(int, char**) if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) { printf("Error: SDL_Init(): %s\n", SDL_GetError()); - return -1; + return 1; } // Create SDL window graphics context @@ -34,19 +34,19 @@ int main(int, char**) if (window == nullptr) { printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); - return -1; + return 1; } SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); SDL_ShowWindow(window); // Create Metal device _before_ creating the view/layer - id metalDevice = MTLCreateSystemDefaultDevice(); + id metalDevice = MTLCreateSystemDefaultDevice(); if (!metalDevice) { printf("Error: failed to create Metal device.\n"); SDL_DestroyWindow(window); SDL_Quit(); - return -1; + return 1; } SDL_MetalView view = SDL_Metal_CreateView(window); CAMetalLayer* layer = (__bridge CAMetalLayer*)SDL_Metal_GetLayer(view); @@ -128,7 +128,7 @@ int main(int, char**) int width, height; SDL_GetWindowSizeInPixels(window, &width, &height); - + layer.drawableSize = CGSizeMake(width, height); id drawable = [layer nextDrawable]; diff --git a/examples/example_sdl3_opengl3/main.cpp b/examples/example_sdl3_opengl3/main.cpp index 36b5e2eba..44a6417d1 100644 --- a/examples/example_sdl3_opengl3/main.cpp +++ b/examples/example_sdl3_opengl3/main.cpp @@ -30,7 +30,7 @@ int main(int, char**) if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) { printf("Error: SDL_Init(): %s\n", SDL_GetError()); - return -1; + return 1; } // Decide GL+GLSL versions @@ -74,13 +74,13 @@ int main(int, char**) if (window == nullptr) { printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); - return -1; + return 1; } SDL_GLContext gl_context = SDL_GL_CreateContext(window); if (gl_context == nullptr) { printf("Error: SDL_GL_CreateContext(): %s\n", SDL_GetError()); - return -1; + return 1; } SDL_GL_MakeCurrent(window, gl_context); diff --git a/examples/example_sdl3_sdlgpu3/main.cpp b/examples/example_sdl3_sdlgpu3/main.cpp index 3f797ecd6..84b0a254f 100644 --- a/examples/example_sdl3_sdlgpu3/main.cpp +++ b/examples/example_sdl3_sdlgpu3/main.cpp @@ -31,7 +31,7 @@ int main(int, char**) if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) { printf("Error: SDL_Init(): %s\n", SDL_GetError()); - return -1; + return 1; } // Create SDL window graphics context @@ -41,7 +41,7 @@ int main(int, char**) if (window == nullptr) { printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); - return -1; + return 1; } SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); SDL_ShowWindow(window); @@ -51,14 +51,14 @@ int main(int, char**) if (gpu_device == nullptr) { printf("Error: SDL_CreateGPUDevice(): %s\n", SDL_GetError()); - return -1; + return 1; } // Claim window for GPU Device if (!SDL_ClaimWindowForGPUDevice(gpu_device, window)) { printf("Error: SDL_ClaimWindowForGPUDevice(): %s\n", SDL_GetError()); - return -1; + return 1; } SDL_SetGPUSwapchainParameters(gpu_device, window, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, SDL_GPU_PRESENTMODE_VSYNC); diff --git a/examples/example_sdl3_sdlrenderer3/main.cpp b/examples/example_sdl3_sdlrenderer3/main.cpp index 2256b7da7..39870f2c6 100644 --- a/examples/example_sdl3_sdlrenderer3/main.cpp +++ b/examples/example_sdl3_sdlrenderer3/main.cpp @@ -28,7 +28,7 @@ int main(int, char**) if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) { printf("Error: SDL_Init(): %s\n", SDL_GetError()); - return -1; + return 1; } // Create window with SDL_Renderer graphics context @@ -38,14 +38,14 @@ int main(int, char**) if (window == nullptr) { printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); - return -1; + return 1; } SDL_Renderer* renderer = SDL_CreateRenderer(window, nullptr); SDL_SetRenderVSync(renderer, 1); if (renderer == nullptr) { SDL_Log("Error: SDL_CreateRenderer(): %s\n", SDL_GetError()); - return -1; + return 1; } SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); SDL_ShowWindow(window); diff --git a/examples/example_sdl3_vulkan/main.cpp b/examples/example_sdl3_vulkan/main.cpp index dd9a460c9..060855259 100644 --- a/examples/example_sdl3_vulkan/main.cpp +++ b/examples/example_sdl3_vulkan/main.cpp @@ -349,7 +349,7 @@ int main(int, char**) if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) { printf("Error: SDL_Init(): %s\n", SDL_GetError()); - return -1; + return 1; } // Create window with Vulkan graphics context @@ -359,7 +359,7 @@ int main(int, char**) if (window == nullptr) { printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); - return -1; + return 1; } ImVector extensions; From 15c88c4941af71fffaae1ef6c6cbb00b7907dfcd Mon Sep 17 00:00:00 2001 From: David Maas Date: Wed, 21 Jul 2021 16:59:34 -0500 Subject: [PATCH 31/39] Backends: DX10, DX11, DX12: Disabled DXGI's Alt+Enter default behavior on secondary viewports. (#4350) Removed use of DXGI_MWA_NO_PRINT_SCREEN from original PR. --- backends/imgui_impl_dx10.cpp | 1 + backends/imgui_impl_dx11.cpp | 1 + backends/imgui_impl_dx12.cpp | 2 ++ docs/CHANGELOG.txt | 2 ++ 4 files changed, 6 insertions(+) diff --git a/backends/imgui_impl_dx10.cpp b/backends/imgui_impl_dx10.cpp index dd427d335..15ccf1e7c 100644 --- a/backends/imgui_impl_dx10.cpp +++ b/backends/imgui_impl_dx10.cpp @@ -708,6 +708,7 @@ static void ImGui_ImplDX10_CreateWindow(ImGuiViewport* viewport) IM_ASSERT(vd->SwapChain == nullptr && vd->RTView == nullptr); bd->pFactory->CreateSwapChain(bd->pd3dDevice, &sd, &vd->SwapChain); + bd->pFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER | DXGI_MWA_NO_WINDOW_CHANGES); // Disable e.g. Alt+Enter // Create the render target if (vd->SwapChain) diff --git a/backends/imgui_impl_dx11.cpp b/backends/imgui_impl_dx11.cpp index a50207749..69eecf047 100644 --- a/backends/imgui_impl_dx11.cpp +++ b/backends/imgui_impl_dx11.cpp @@ -738,6 +738,7 @@ static void ImGui_ImplDX11_CreateWindow(ImGuiViewport* viewport) break; } IM_ASSERT(SUCCEEDED(hr)); + bd->pFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER | DXGI_MWA_NO_WINDOW_CHANGES); // Disable e.g. Alt+Enter // Create the render target if (vd->SwapChain != nullptr) diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp index 7e13971e5..a224469d8 100644 --- a/backends/imgui_impl_dx12.cpp +++ b/backends/imgui_impl_dx12.cpp @@ -1087,6 +1087,8 @@ static void ImGui_ImplDX12_CreateWindow(ImGuiViewport* viewport) IDXGISwapChain1* swap_chain = nullptr; res = dxgi_factory->CreateSwapChainForHwnd(vd->CommandQueue, hwnd, &sd1, nullptr, nullptr, &swap_chain); IM_ASSERT(res == S_OK); + res = dxgi_factory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER | DXGI_MWA_NO_WINDOW_CHANGES); // Disable e.g. Alt+Enter + IM_ASSERT(res == S_OK); dxgi_factory->Release(); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 6d7a8f98e..3326f800c 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -88,6 +88,8 @@ Docking+Viewports Branch: - Viewports: DestroyContext() does not call DestroyPlatformWindows() anymore at it assumed to be unnecessary as backensd should have done it and we check that backends have been shutdown since 1.90.4. Changed into asserts. (#7175, #8945) +- Backends: DX10, DX11, DX12: Disabled DXGI's Alt+Enter default behavior on secondary + viewports managed by the backend. (#4350) [@PathogenDavid] - Backends: Vulkan: Added ImGui_ImplVulkanH_GetWindowDataFromViewport() accessor/helper. (#8946, #8940) [@olivier-gerard] From 3d937beb628ac1f39d32fde21f35c730cbfe6dcf Mon Sep 17 00:00:00 2001 From: David Maas Date: Thu, 25 Sep 2025 17:35:35 +0200 Subject: [PATCH 32/39] Examples: DX10, DX11: Disabled DXGI's Alt+Enter default behavior in examples. (#4350) --- docs/CHANGELOG.txt | 3 +++ examples/example_sdl2_directx11/main.cpp | 7 +++++++ examples/example_sdl3_directx11/main.cpp | 7 +++++++ examples/example_win32_directx10/main.cpp | 7 +++++++ examples/example_win32_directx11/main.cpp | 7 +++++++ 5 files changed, 31 insertions(+) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 3326f800c..2b11d5dde 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -92,6 +92,9 @@ Docking+Viewports Branch: viewports managed by the backend. (#4350) [@PathogenDavid] - Backends: Vulkan: Added ImGui_ImplVulkanH_GetWindowDataFromViewport() accessor/helper. (#8946, #8940) [@olivier-gerard] +- Examples: DX10, DX11: Disabled DXGI's Alt+Enter default behavior in examples. + Applications are free to leave this enabled, but it does not work properly with + multiple viewports. (#4350) [@PathogenDavid] ----------------------------------------------------------------------- diff --git a/examples/example_sdl2_directx11/main.cpp b/examples/example_sdl2_directx11/main.cpp index 298fcaaf7..c238c458b 100644 --- a/examples/example_sdl2_directx11/main.cpp +++ b/examples/example_sdl2_directx11/main.cpp @@ -256,6 +256,13 @@ bool CreateDeviceD3D(HWND hWnd) if (res != S_OK) return false; + // Disable DXGI's default Alt+Enter fullscreen behavior. + // - You are free to leave this enabled, but it will not work properly with multiple viewports. + // - This must be done for all windows associated to the device. Our DX11 backend does this automatically for secondary viewports that it creates. + IDXGIFactory* pSwapChainFactory; + if (SUCCEEDED(g_pSwapChain->GetParent(IID_PPV_ARGS(&pSwapChainFactory)))) + pSwapChainFactory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER); + CreateRenderTarget(); return true; } diff --git a/examples/example_sdl3_directx11/main.cpp b/examples/example_sdl3_directx11/main.cpp index 681c30dbc..e6f7515fd 100644 --- a/examples/example_sdl3_directx11/main.cpp +++ b/examples/example_sdl3_directx11/main.cpp @@ -251,6 +251,13 @@ bool CreateDeviceD3D(HWND hWnd) if (res != S_OK) return false; + // Disable DXGI's default Alt+Enter fullscreen behavior. + // - You are free to leave this enabled, but it will not work properly with multiple viewports. + // - This must be done for all windows associated to the device. Our DX11 backend does this automatically for secondary viewports that it creates. + IDXGIFactory* pSwapChainFactory; + if (SUCCEEDED(g_pSwapChain->GetParent(IID_PPV_ARGS(&pSwapChainFactory)))) + pSwapChainFactory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER); + CreateRenderTarget(); return true; } diff --git a/examples/example_win32_directx10/main.cpp b/examples/example_win32_directx10/main.cpp index f94440221..504502dac 100644 --- a/examples/example_win32_directx10/main.cpp +++ b/examples/example_win32_directx10/main.cpp @@ -241,6 +241,13 @@ bool CreateDeviceD3D(HWND hWnd) if (res != S_OK) return false; + // Disable DXGI's default Alt+Enter fullscreen behavior. + // - You are free to leave this enabled, but it will not work properly with multiple viewports. + // - This must be done for all windows associated to the device. Our DX11 backend does this automatically for secondary viewports that it creates. + IDXGIFactory* pSwapChainFactory; + if (SUCCEEDED(g_pSwapChain->GetParent(IID_PPV_ARGS(&pSwapChainFactory)))) + pSwapChainFactory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER); + CreateRenderTarget(); return true; } diff --git a/examples/example_win32_directx11/main.cpp b/examples/example_win32_directx11/main.cpp index e1ec03664..16b7e2cf2 100644 --- a/examples/example_win32_directx11/main.cpp +++ b/examples/example_win32_directx11/main.cpp @@ -245,6 +245,13 @@ bool CreateDeviceD3D(HWND hWnd) if (res != S_OK) return false; + // Disable DXGI's default Alt+Enter fullscreen behavior. + // - You are free to leave this enabled, but it will not work properly with multiple viewports. + // - This must be done for all windows associated to the device. Our DX11 backend does this automatically for secondary viewports that it creates. + IDXGIFactory* pSwapChainFactory; + if (SUCCEEDED(g_pSwapChain->GetParent(IID_PPV_ARGS(&pSwapChainFactory)))) + pSwapChainFactory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER); + CreateRenderTarget(); return true; } From bf2e0b2c6f053c5633b8288d7ffc17ab92ea923c Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 25 Sep 2025 19:07:51 +0200 Subject: [PATCH 33/39] Tables: change ImGuiTableFlags_NoBordersInBody behavior to not draw border in body even when resizing. (#8893) --- imgui_tables.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 21d5335c6..af0e8c6cf 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -2818,8 +2818,13 @@ void ImGui::TableDrawBorders(ImGuiTable* table) continue; // Draw in outer window so right-most column won't be clipped - // Always draw full height border when being resized/hovered, or on the delimitation of frozen column scrolling. - float draw_y2 = (is_hovered || is_resized || is_frozen_separator || (table->Flags & (ImGuiTableFlags_NoBordersInBody | ImGuiTableFlags_NoBordersInBodyUntilResize)) == 0) ? draw_y2_body : draw_y2_head; + float draw_y2 = draw_y2_head; + if (is_frozen_separator) + draw_y2 = draw_y2_body; + else if ((table->Flags & ImGuiTableFlags_NoBordersInBodyUntilResize) != 0 && (is_hovered || is_resized)) + draw_y2 = draw_y2_body; + else if ((table->Flags & (ImGuiTableFlags_NoBordersInBodyUntilResize | ImGuiTableFlags_NoBordersInBody)) == 0) + draw_y2 = draw_y2_body; if (draw_y2 > draw_y1) inner_drawlist->AddLine(ImVec2(column->MaxX, draw_y1), ImVec2(column->MaxX, draw_y2), TableGetColumnBorderCol(table, order_n, column_n), border_size); } From 01686c6294a778b017f63eaad4c9d391fd77495a Mon Sep 17 00:00:00 2001 From: johan0A Date: Sat, 5 Apr 2025 21:36:20 +0200 Subject: [PATCH 34/39] Backends: Vulkan: added a way to specify custom vertex/fragment shaders. (#8585, #8271) --- backends/imgui_impl_vulkan.cpp | 25 ++++++++++++++----------- backends/imgui_impl_vulkan.h | 8 +++++++- docs/CHANGELOG.txt | 2 ++ 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 4a0a5a947..0e0ba719b 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -27,6 +27,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-26: Vulkan: Added a way to customize shaders by filling ImGui_ImplVulkan_InitInfo::CustomShaderVertCreateInfo/CustomShaderFragCreateInfo. (#8585) // 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-09-04: Vulkan: Added ImGui_ImplVulkan_CreateMainPipeline(). (#8110, #8111) // 2025-07-27: Vulkan: Fixed texture update corruption introduced on 2025-06-11. (#8801, #8755, #8840) @@ -887,24 +888,26 @@ void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex) static void ImGui_ImplVulkan_CreateShaderModules(VkDevice device, const VkAllocationCallbacks* allocator) { - // Create the shader modules ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); + ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; if (bd->ShaderModuleVert == VK_NULL_HANDLE) { - VkShaderModuleCreateInfo vert_info = {}; - vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - vert_info.codeSize = sizeof(__glsl_shader_vert_spv); - vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv; - VkResult err = vkCreateShaderModule(device, &vert_info, allocator, &bd->ShaderModuleVert); + VkShaderModuleCreateInfo default_vert_info = {}; + default_vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + default_vert_info.codeSize = sizeof(__glsl_shader_vert_spv); + default_vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv; + VkShaderModuleCreateInfo* p_vert_info = (v->CustomShaderVertCreateInfo.sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO) ? &v->CustomShaderVertCreateInfo : &default_vert_info; + VkResult err = vkCreateShaderModule(device, p_vert_info, allocator, &bd->ShaderModuleVert); check_vk_result(err); } if (bd->ShaderModuleFrag == VK_NULL_HANDLE) { - VkShaderModuleCreateInfo frag_info = {}; - frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - frag_info.codeSize = sizeof(__glsl_shader_frag_spv); - frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv; - VkResult err = vkCreateShaderModule(device, &frag_info, allocator, &bd->ShaderModuleFrag); + VkShaderModuleCreateInfo default_frag_info = {}; + default_frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + default_frag_info.codeSize = sizeof(__glsl_shader_frag_spv); + default_frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv; + VkShaderModuleCreateInfo* p_frag_info = (v->CustomShaderFragCreateInfo.sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO) ? &v->CustomShaderFragCreateInfo : &default_frag_info; + VkResult err = vkCreateShaderModule(device, p_frag_info, allocator, &bd->ShaderModuleFrag); check_vk_result(err); } } diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index a24cb2cdb..cf1a5b9a1 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -102,7 +102,13 @@ struct ImGui_ImplVulkan_InitInfo // (Optional) Allocation, Debugging const VkAllocationCallbacks* Allocator; void (*CheckVkResultFn)(VkResult err); - VkDeviceSize MinAllocationSize; // Minimum allocation size. Set to 1024*1024 to satisfy zealous best practices validation layer and waste a little memory. + VkDeviceSize MinAllocationSize; // Minimum allocation size. Set to 1024*1024 to satisfy zealous best practices validation layer and waste a little memory. + + // (Optional) Customize default vertex/fragment shaders. + // - if .sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO we use specified structs, otherwise we use defaults. + // - Shader inputs/outputs need to match ours. Code/data pointed to by the structure needs to survive for whole during of backend usage. + VkShaderModuleCreateInfo CustomShaderVertCreateInfo; + VkShaderModuleCreateInfo CustomShaderFragCreateInfo; }; // Follow "Getting Started" link and check examples/ folder to learn about using backends! diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 04ca7ef1c..ce9a22f5a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -64,6 +64,8 @@ Other Changes: - Better perf on X11 as querying global position requires a round trip to X11 server. - Backends: Win32: minor optimization not submitting gamepad io again if XInput's dwPacketNumber has not changed. (#8556) [@MidTerm-CN] +- Backends: Vulkan: added a way to specify custom shaders by filling init fields + CustomShaderVertCreateInfo and CustomShaderFragCreateInfo. (#8585, #8271) [@johan0A] - Examples: SDL2+DirectX11: Try WARP software driver if hardware driver is not available. (#5924, #5562) - Examples: SDL3+DirectX11: Added SDL3+DirectX11 example. (#8956, #8957) [@tomaz82] From 5fe962216ac8af5688602ea01d51313f3b949c74 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 26 Sep 2025 17:32:39 +0200 Subject: [PATCH 35/39] (Breaking) Backends: Vulkan: added 'VkImageUsageFlags image_usage' parameter to ImGui_ImplVulkanH_CreateOrResizeWindow(). (#8946, #8110, #8111, #8686) Default to VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT. --- backends/imgui_impl_vulkan.cpp | 12 +++++++----- backends/imgui_impl_vulkan.h | 4 ++-- docs/CHANGELOG.txt | 6 ++++++ examples/example_glfw_vulkan/main.cpp | 5 +++-- examples/example_sdl2_vulkan/main.cpp | 5 +++-- examples/example_sdl3_vulkan/main.cpp | 5 +++-- examples/example_win32_vulkan/main.cpp | 5 +++-- 7 files changed, 27 insertions(+), 15 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 0e0ba719b..7a8d26362 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -27,6 +27,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-26: *BREAKING CHANGE*: helper ImGui_ImplVulkanH_CreateOrResizeWindow() added a VkImageUsageFlags image_usage` argument, default to VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT if 0. // 2025-09-26: Vulkan: Added a way to customize shaders by filling ImGui_ImplVulkan_InitInfo::CustomShaderVertCreateInfo/CustomShaderFragCreateInfo. (#8585) // 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-09-04: Vulkan: Added ImGui_ImplVulkan_CreateMainPipeline(). (#8110, #8111) @@ -118,7 +119,7 @@ void ImGui_ImplVulkan_DestroyFrameRenderBuffers(VkDevice device, ImGui_ImplVulka void ImGui_ImplVulkan_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulkan_WindowRenderBuffers* buffers, const VkAllocationCallbacks* allocator); void ImGui_ImplVulkanH_DestroyFrame(VkDevice device, ImGui_ImplVulkanH_Frame* fd, const VkAllocationCallbacks* allocator); void ImGui_ImplVulkanH_DestroyFrameSemaphores(VkDevice device, ImGui_ImplVulkanH_FrameSemaphores* fsd, const VkAllocationCallbacks* allocator); -void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count); +void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count, VkImageUsageFlags image_usage); void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator); // Vulkan prototypes for use with custom loaders @@ -1605,7 +1606,7 @@ int ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(VkPresentModeKHR present_m } // Also destroy old swap chain and in-flight frames data, if any. -void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count) +void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count, VkImageUsageFlags image_usage) { VkResult err; VkSwapchainKHR old_swapchain = wd->Swapchain; @@ -1644,7 +1645,7 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V info.imageFormat = wd->SurfaceFormat.format; info.imageColorSpace = wd->SurfaceFormat.colorSpace; info.imageArrayLayers = 1; - info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + info.imageUsage = (image_usage != 0) ? image_usage : VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; // Assume that graphics family == present family info.preTransform = (cap.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : cap.currentTransform; info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; @@ -1772,11 +1773,12 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V } // Create or resize window -void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int width, int height, uint32_t min_image_count) +// - 2025/09/26: v1.92.4 added a trailing 'VkImageUsageFlags image_usage' parameter which is usually VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT. +void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int width, int height, uint32_t min_image_count, VkImageUsageFlags image_usage) { IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!"); (void)instance; - ImGui_ImplVulkanH_CreateWindowSwapChain(physical_device, device, wd, allocator, width, height, min_image_count); + ImGui_ImplVulkanH_CreateWindowSwapChain(physical_device, device, wd, allocator, width, height, min_image_count, image_usage); ImGui_ImplVulkanH_CreateWindowCommandBuffers(physical_device, device, wd, queue_family, allocator); // FIXME: to submit the command buffer, we need a queue. In the examples folder, the ImGui_ImplVulkanH_CreateOrResizeWindow function is called diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index cf1a5b9a1..62158b7f9 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -181,8 +181,8 @@ struct ImGui_ImplVulkanH_Frame; struct ImGui_ImplVulkanH_Window; // Helpers -IMGUI_IMPL_API void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wnd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count); -IMGUI_IMPL_API void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wnd, const VkAllocationCallbacks* allocator); +IMGUI_IMPL_API void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count, VkImageUsageFlags image_usage); +IMGUI_IMPL_API void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator); IMGUI_IMPL_API VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space); IMGUI_IMPL_API VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count); IMGUI_IMPL_API VkPhysicalDevice ImGui_ImplVulkanH_SelectPhysicalDevice(VkInstance instance); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ce9a22f5a..1f6e463f5 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,6 +41,12 @@ HOW TO UPDATE? Breaking Changes: +- Backends: Vulkan: helper ImGui_ImplVulkanH_CreateOrResizeWindow() added a + `VkImageUsageFlags image_usage` argument. + It was previously hardcoded to `VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT` and defaults + to that when the value is 0. In theory the function is an internal helper but + since it's used by our examples some may have used it. (#8946, #8111, #8686) + Other Changes: - Windows: added lower-right resize grip on child windows using both diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index ebc78bdd5..176c8c4d3 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -54,6 +54,7 @@ static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; static ImGui_ImplVulkanH_Window g_MainWindowData; static uint32_t g_MinImageCount = 2; static bool g_SwapChainRebuild = false; +static VkImageUsageFlags g_SwapChainImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; static void glfw_error_callback(int error, const char* description) { @@ -239,7 +240,7 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface // Create SwapChain, RenderPass, Framebuffer, etc. IM_ASSERT(g_MinImageCount >= 2); - ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, g_SwapChainImageUsage); } static void CleanupVulkan() @@ -456,7 +457,7 @@ int main(int, char**) if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height)) { ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount); - ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, g_SwapChainImageUsage); g_MainWindowData.FrameIndex = 0; g_SwapChainRebuild = false; } diff --git a/examples/example_sdl2_vulkan/main.cpp b/examples/example_sdl2_vulkan/main.cpp index 8dd505889..21e892779 100644 --- a/examples/example_sdl2_vulkan/main.cpp +++ b/examples/example_sdl2_vulkan/main.cpp @@ -49,6 +49,7 @@ static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; static ImGui_ImplVulkanH_Window g_MainWindowData; static uint32_t g_MinImageCount = 2; static bool g_SwapChainRebuild = false; +static VkImageUsageFlags g_SwapChainImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; static void check_vk_result(VkResult err) { @@ -230,7 +231,7 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface // Create SwapChain, RenderPass, Framebuffer, etc. IM_ASSERT(g_MinImageCount >= 2); - ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, g_SwapChainImageUsage); } static void CleanupVulkan() @@ -476,7 +477,7 @@ int main(int, char**) if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height)) { ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount); - ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, g_SwapChainImageUsage); g_MainWindowData.FrameIndex = 0; g_SwapChainRebuild = false; } diff --git a/examples/example_sdl3_vulkan/main.cpp b/examples/example_sdl3_vulkan/main.cpp index 060855259..e4cecf210 100644 --- a/examples/example_sdl3_vulkan/main.cpp +++ b/examples/example_sdl3_vulkan/main.cpp @@ -51,6 +51,7 @@ static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; static ImGui_ImplVulkanH_Window g_MainWindowData; static uint32_t g_MinImageCount = 2; static bool g_SwapChainRebuild = false; +static VkImageUsageFlags g_SwapChainImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; static void check_vk_result(VkResult err) { @@ -232,7 +233,7 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface // Create SwapChain, RenderPass, Framebuffer, etc. IM_ASSERT(g_MinImageCount >= 2); - ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, g_SwapChainImageUsage); } static void CleanupVulkan() @@ -478,7 +479,7 @@ int main(int, char**) if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height)) { ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount); - ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_height, fb_height, g_MinImageCount, g_SwapChainImageUsage); g_MainWindowData.FrameIndex = 0; g_SwapChainRebuild = false; } diff --git a/examples/example_win32_vulkan/main.cpp b/examples/example_win32_vulkan/main.cpp index 6063437d8..7a68ccbdd 100644 --- a/examples/example_win32_vulkan/main.cpp +++ b/examples/example_win32_vulkan/main.cpp @@ -47,6 +47,7 @@ static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; static ImGui_ImplVulkanH_Window g_MainWindowData; static uint32_t g_MinImageCount = 2; static bool g_SwapChainRebuild = false; +static VkImageUsageFlags g_SwapChainImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; static void check_vk_result(VkResult err) { @@ -228,7 +229,7 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface // Create SwapChain, RenderPass, Framebuffer, etc. IM_ASSERT(g_MinImageCount >= 2); - ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, g_SwapChainImageUsage); } static void CleanupVulkan() @@ -549,7 +550,7 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height)) { ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount); - ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, g_SwapChainImageUsage); g_MainWindowData.FrameIndex = 0; g_SwapChainRebuild = false; } From cc0a6690bfb5af6ae38723587ec74e120142c67b Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 26 Sep 2025 17:33:32 +0200 Subject: [PATCH 36/39] Backends: Vulkan: minor internal renames/tweaks to reduce further patches. (#8946, #8110, #8111, #8686) --- backends/imgui_impl_vulkan.cpp | 45 +++++++++++++++++----------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 7a8d26362..49ceeef0b 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -1001,22 +1001,22 @@ static VkPipeline ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAlloc dynamic_state.dynamicStateCount = (uint32_t)IM_ARRAYSIZE(dynamic_states); dynamic_state.pDynamicStates = dynamic_states; - VkGraphicsPipelineCreateInfo info = {}; - info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - info.flags = bd->PipelineCreateFlags; - info.stageCount = 2; - info.pStages = stage; - info.pVertexInputState = &vertex_info; - info.pInputAssemblyState = &ia_info; - info.pViewportState = &viewport_info; - info.pRasterizationState = &raster_info; - info.pMultisampleState = &ms_info; - info.pDepthStencilState = &depth_info; - info.pColorBlendState = &blend_info; - info.pDynamicState = &dynamic_state; - info.layout = bd->PipelineLayout; - info.renderPass = renderPass; - info.subpass = subpass; + VkGraphicsPipelineCreateInfo create_info = {}; + create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + create_info.flags = bd->PipelineCreateFlags; + create_info.stageCount = 2; + create_info.pStages = stage; + create_info.pVertexInputState = &vertex_info; + create_info.pInputAssemblyState = &ia_info; + create_info.pViewportState = &viewport_info; + create_info.pRasterizationState = &raster_info; + create_info.pMultisampleState = &ms_info; + create_info.pDepthStencilState = &depth_info; + create_info.pColorBlendState = &blend_info; + create_info.pDynamicState = &dynamic_state; + create_info.layout = bd->PipelineLayout; + create_info.renderPass = renderPass; + create_info.subpass = subpass; #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING if (bd->VulkanInitInfo.UseDynamicRendering) @@ -1024,14 +1024,14 @@ static VkPipeline ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAlloc IM_ASSERT(pipeline_rendering_create_info && "PipelineRenderingCreateInfo must not be nullptr when using dynamic rendering"); IM_ASSERT(pipeline_rendering_create_info->sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR && "PipelineRenderingCreateInfo::sType must be VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR"); IM_ASSERT(pipeline_rendering_create_info->pNext == nullptr && "PipelineRenderingCreateInfo::pNext must be nullptr"); - info.pNext = pipeline_rendering_create_info; - info.renderPass = VK_NULL_HANDLE; // Just make sure it's actually nullptr. + create_info.pNext = pipeline_rendering_create_info; + create_info.renderPass = VK_NULL_HANDLE; // Just make sure it's actually nullptr. } #else IM_ASSERT(pipeline_rendering_create_info == nullptr); #endif VkPipeline pipeline; - VkResult err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &info, allocator, &pipeline); + VkResult err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &create_info, allocator, &pipeline); check_vk_result(err); return pipeline; } @@ -1108,11 +1108,11 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() } // Create pipeline - if (v->RenderPass + bool create_main_pipeline = (v->RenderPass != VK_NULL_HANDLE); #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING - || (v->UseDynamicRendering && v->PipelineRenderingCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR) + create_main_pipeline |= (v->UseDynamicRendering && v->PipelineRenderingCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR); #endif - ) + if (create_main_pipeline) { ImGui_ImplVulkan_MainPipelineCreateInfo mp_info = {}; mp_info.RenderPass = v->RenderPass; @@ -1292,6 +1292,7 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info) io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render. + // Sanity checks IM_ASSERT(info->Instance != VK_NULL_HANDLE); IM_ASSERT(info->PhysicalDevice != VK_NULL_HANDLE); IM_ASSERT(info->Device != VK_NULL_HANDLE); From e312b99296336c01b43ca91d42036022c6c20844 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 26 Sep 2025 17:37:42 +0200 Subject: [PATCH 37/39] (Breaking) Backends: Vulkan: renamed ImGui_ImplVulkan_MainPipelineCreateInfo to ImGui_ImplVulkan_PipelineInfo. (#8110, #8111) --- backends/imgui_impl_vulkan.cpp | 5 +++-- backends/imgui_impl_vulkan.h | 4 ++-- docs/CHANGELOG.txt | 3 +++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 49ceeef0b..ecd8b98d2 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -27,6 +27,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-26: *BREAKING CHANGE*: renamed ImGui_ImplVulkan_MainPipelineCreateInfo to ImGui_ImplVulkan_PipelineInfo. Introduced very recently so shouldn't affect many users. // 2025-09-26: *BREAKING CHANGE*: helper ImGui_ImplVulkanH_CreateOrResizeWindow() added a VkImageUsageFlags image_usage` argument, default to VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT if 0. // 2025-09-26: Vulkan: Added a way to customize shaders by filling ImGui_ImplVulkan_InitInfo::CustomShaderVertCreateInfo/CustomShaderFragCreateInfo. (#8585) // 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. @@ -1114,7 +1115,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() #endif if (create_main_pipeline) { - ImGui_ImplVulkan_MainPipelineCreateInfo mp_info = {}; + ImGui_ImplVulkan_PipelineInfo mp_info = {}; mp_info.RenderPass = v->RenderPass; mp_info.Subpass = v->Subpass; mp_info.MSAASamples = v->MSAASamples; @@ -1147,7 +1148,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() return true; } -void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_MainPipelineCreateInfo& info) +void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_PipelineInfo& info) { ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index 62158b7f9..a174e72d5 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -121,7 +121,7 @@ IMGUI_IMPL_API void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_i // (Advanced) Use e.g. if you need to recreate pipeline without reinitializing the backend (see #8110, #8111) // The main window pipeline will be created by ImGui_ImplVulkan_Init() if possible (== RenderPass xor (UseDynamicRendering && PipelineRenderingCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR)) // Else, the pipeline can be created, or re-created, using ImGui_ImplVulkan_CreateMainPipeline() before rendering. -struct ImGui_ImplVulkan_MainPipelineCreateInfo +struct ImGui_ImplVulkan_PipelineInfo { VkRenderPass RenderPass = VK_NULL_HANDLE; uint32_t Subpass = 0; @@ -130,7 +130,7 @@ struct ImGui_ImplVulkan_MainPipelineCreateInfo VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; // Optional, valid if .sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR #endif }; -IMGUI_IMPL_API void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_MainPipelineCreateInfo& info); // (render_pass xor (p_dynamic_rendering && p_dynamic_rendering is correct (sType and pNext))) +IMGUI_IMPL_API void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_PipelineInfo& info); // (render_pass xor (p_dynamic_rendering && p_dynamic_rendering is correct (sType and pNext))) // (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually. IMGUI_IMPL_API void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 1f6e463f5..912527734 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,6 +41,9 @@ HOW TO UPDATE? Breaking Changes: +- Backends: Vulkan: renamed ImGui_ImplVulkan_MainPipelineCreateInfo --> ImGui_ImplVulkan_PipelineInfo + (introduced very recently and only used by `ImGui_ImplVulkan_CreateMainPipeline()` + so it should not affect many users). (#8110, #8111) - Backends: Vulkan: helper ImGui_ImplVulkanH_CreateOrResizeWindow() added a `VkImageUsageFlags image_usage` argument. It was previously hardcoded to `VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT` and defaults From 3470e6112b8bb81059ec461e56385dc91d89dcb7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 26 Sep 2025 18:23:03 +0200 Subject: [PATCH 38/39] (Breaking) Backends: Vulkan: moved fields in ImGui_ImplVulkan_InitInfo: RenderPass, Subpass, MSAASamples, PipelineRenderingCreateInfo. (#8946, #8110, #8111, #8686) --- backends/imgui_impl_vulkan.cpp | 70 +++++++++++--------------- backends/imgui_impl_vulkan.h | 36 ++++++------- docs/CHANGELOG.txt | 7 +++ examples/example_glfw_vulkan/main.cpp | 6 +-- examples/example_sdl2_vulkan/main.cpp | 6 +-- examples/example_sdl3_vulkan/main.cpp | 6 +-- examples/example_win32_vulkan/main.cpp | 6 +-- imgui.h | 2 +- 8 files changed, 67 insertions(+), 72 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index ecd8b98d2..60554368e 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -27,6 +27,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-26: *BREAKING CHANGE*: moved some fields in ImGui_ImplVulkan_InitInfo: init_info.RenderPass --> init_info.PipelineInfoMain.RenderPass, init_info.Subpass --> init_info.PipelineInfoMain.Subpass, init_info.MSAASamples --> init_info.PipelineInfoMain.MSAASamples, init_info.PipelineRenderingCreateInfo --> init_info.PipelineInfoMain.PipelineRenderingCreateInfo. // 2025-09-26: *BREAKING CHANGE*: renamed ImGui_ImplVulkan_MainPipelineCreateInfo to ImGui_ImplVulkan_PipelineInfo. Introduced very recently so shouldn't affect many users. // 2025-09-26: *BREAKING CHANGE*: helper ImGui_ImplVulkanH_CreateOrResizeWindow() added a VkImageUsageFlags image_usage` argument, default to VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT if 0. // 2025-09-26: Vulkan: Added a way to customize shaders by filling ImGui_ImplVulkan_InitInfo::CustomShaderVertCreateInfo/CustomShaderFragCreateInfo. (#8585) @@ -918,7 +919,7 @@ static void ImGui_ImplVulkan_CreateShaderModules(VkDevice device, const VkAlloca typedef void VkPipelineRenderingCreateInfoKHR; #endif -static VkPipeline ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationCallbacks* allocator, VkPipelineCache pipelineCache, VkRenderPass renderPass, VkSampleCountFlagBits MSAASamples, uint32_t subpass, const VkPipelineRenderingCreateInfoKHR* pipeline_rendering_create_info) +static VkPipeline ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationCallbacks* allocator, VkPipelineCache pipelineCache, const ImGui_ImplVulkan_PipelineInfo* info) { ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); ImGui_ImplVulkan_CreateShaderModules(device, allocator); @@ -976,7 +977,7 @@ static VkPipeline ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAlloc VkPipelineMultisampleStateCreateInfo ms_info = {}; ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - ms_info.rasterizationSamples = (MSAASamples != 0) ? MSAASamples : VK_SAMPLE_COUNT_1_BIT; + ms_info.rasterizationSamples = (info->MSAASamples != 0) ? info->MSAASamples : VK_SAMPLE_COUNT_1_BIT; VkPipelineColorBlendAttachmentState color_attachment[1] = {}; color_attachment[0].blendEnable = VK_TRUE; @@ -1016,20 +1017,17 @@ static VkPipeline ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAlloc create_info.pColorBlendState = &blend_info; create_info.pDynamicState = &dynamic_state; create_info.layout = bd->PipelineLayout; - create_info.renderPass = renderPass; - create_info.subpass = subpass; + create_info.renderPass = info->RenderPass; + create_info.subpass = info->Subpass; #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING if (bd->VulkanInitInfo.UseDynamicRendering) { - IM_ASSERT(pipeline_rendering_create_info && "PipelineRenderingCreateInfo must not be nullptr when using dynamic rendering"); - IM_ASSERT(pipeline_rendering_create_info->sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR && "PipelineRenderingCreateInfo::sType must be VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR"); - IM_ASSERT(pipeline_rendering_create_info->pNext == nullptr && "PipelineRenderingCreateInfo::pNext must be nullptr"); - create_info.pNext = pipeline_rendering_create_info; + IM_ASSERT(info->PipelineRenderingCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR && "PipelineRenderingCreateInfo::sType must be VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR"); + IM_ASSERT(info->PipelineRenderingCreateInfo.pNext == nullptr && "PipelineRenderingCreateInfo::pNext must be nullptr"); + create_info.pNext = &info->PipelineRenderingCreateInfo; create_info.renderPass = VK_NULL_HANDLE; // Just make sure it's actually nullptr. } -#else - IM_ASSERT(pipeline_rendering_create_info == nullptr); #endif VkPipeline pipeline; VkResult err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &create_info, allocator, &pipeline); @@ -1109,21 +1107,12 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() } // Create pipeline - bool create_main_pipeline = (v->RenderPass != VK_NULL_HANDLE); + bool create_main_pipeline = (v->PipelineInfoMain.RenderPass != VK_NULL_HANDLE); #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING - create_main_pipeline |= (v->UseDynamicRendering && v->PipelineRenderingCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR); + create_main_pipeline |= (v->UseDynamicRendering && v->PipelineInfoMain.PipelineRenderingCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR); #endif if (create_main_pipeline) - { - ImGui_ImplVulkan_PipelineInfo mp_info = {}; - mp_info.RenderPass = v->RenderPass; - mp_info.Subpass = v->Subpass; - mp_info.MSAASamples = v->MSAASamples; -#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING - mp_info.PipelineRenderingCreateInfo = v->PipelineRenderingCreateInfo; -#endif - ImGui_ImplVulkan_CreateMainPipeline(mp_info); - } + ImGui_ImplVulkan_CreateMainPipeline(&v->PipelineInfoMain); // Create command pool/buffer for texture upload if (!bd->TexCommandPool) @@ -1148,7 +1137,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() return true; } -void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_PipelineInfo& info) +void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_PipelineInfo* pipeline_info_in) { ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; @@ -1157,28 +1146,23 @@ void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_PipelineInfo& in vkDestroyPipeline(v->Device, bd->Pipeline, v->Allocator); bd->Pipeline = VK_NULL_HANDLE; } - v->RenderPass = info.RenderPass; - v->MSAASamples = info.MSAASamples; - v->Subpass = info.Subpass; + ImGui_ImplVulkan_PipelineInfo* pipeline_info = &v->PipelineInfoMain; + if (pipeline_info != pipeline_info_in) + *pipeline_info = *pipeline_info_in; - const VkPipelineRenderingCreateInfoKHR* pipeline_rendering_create_info = nullptr; #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING - if (v->UseDynamicRendering) + VkPipelineRenderingCreateInfoKHR* pipeline_rendering_create_info = &pipeline_info->PipelineRenderingCreateInfo; + if (v->UseDynamicRendering && pipeline_rendering_create_info->pColorAttachmentFormats != NULL) { - v->PipelineRenderingCreateInfo = info.PipelineRenderingCreateInfo; - pipeline_rendering_create_info = &v->PipelineRenderingCreateInfo; - if (v->PipelineRenderingCreateInfo.pColorAttachmentFormats != NULL) - { - // Deep copy buffer to reduce error-rate for end user (#8282) - ImVector formats; - formats.resize((int)v->PipelineRenderingCreateInfo.colorAttachmentCount); - memcpy(formats.Data, v->PipelineRenderingCreateInfo.pColorAttachmentFormats, (size_t)formats.size_in_bytes()); - formats.swap(bd->PipelineRenderingCreateInfoColorAttachmentFormats); - v->PipelineRenderingCreateInfo.pColorAttachmentFormats = bd->PipelineRenderingCreateInfoColorAttachmentFormats.Data; - } + // Deep copy buffer to reduce error-rate for end user (#8282) + ImVector formats; + formats.resize((int)pipeline_rendering_create_info->colorAttachmentCount); + memcpy(formats.Data, pipeline_rendering_create_info->pColorAttachmentFormats, (size_t)formats.size_in_bytes()); + formats.swap(bd->PipelineRenderingCreateInfoColorAttachmentFormats); + pipeline_rendering_create_info->pColorAttachmentFormats = bd->PipelineRenderingCreateInfoColorAttachmentFormats.Data; } #endif - bd->Pipeline = ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, v->PipelineCache, v->RenderPass, v->MSAASamples, v->Subpass, pipeline_rendering_create_info); + bd->Pipeline = ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, v->PipelineCache, pipeline_info); } void ImGui_ImplVulkan_DestroyDeviceObjects() @@ -1298,12 +1282,14 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info) IM_ASSERT(info->PhysicalDevice != VK_NULL_HANDLE); IM_ASSERT(info->Device != VK_NULL_HANDLE); IM_ASSERT(info->Queue != VK_NULL_HANDLE); + IM_ASSERT(info->MinImageCount >= 2); + IM_ASSERT(info->ImageCount >= info->MinImageCount); if (info->DescriptorPool != VK_NULL_HANDLE) // Either DescriptorPool or DescriptorPoolSize must be set, not both! IM_ASSERT(info->DescriptorPoolSize == 0); else IM_ASSERT(info->DescriptorPoolSize > 0); - IM_ASSERT(info->MinImageCount >= 2); - IM_ASSERT(info->ImageCount >= info->MinImageCount); + if (info->UseDynamicRendering) + IM_ASSERT(info->PipelineInfoMain.RenderPass == VK_NULL_HANDLE); bd->VulkanInitInfo = *info; diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index a174e72d5..afc698701 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -65,6 +65,18 @@ // Backend uses a small number of descriptors per font atlas + as many as additional calls done to ImGui_ImplVulkan_AddTexture(). #define IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE (8) // Minimum per atlas +// Specify settings to create pipeline and swapchain +struct ImGui_ImplVulkan_PipelineInfo +{ + // For Main and Secondary viewports + VkRenderPass RenderPass; // Ignored if using dynamic rendering + uint32_t Subpass; // + VkSampleCountFlagBits MSAASamples = {}; // 0 defaults to VK_SAMPLE_COUNT_1_BIT +#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING + VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; // Optional, valid if .sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR +#endif +}; + // Initialization data, for ImGui_ImplVulkan_Init() // [Please zero-clear before use!] // - About descriptor pool: @@ -88,16 +100,15 @@ struct ImGui_ImplVulkan_InitInfo VkPipelineCache PipelineCache; // Optional // Pipeline - VkRenderPass RenderPass; // Ignored if using dynamic rendering - uint32_t Subpass; - VkSampleCountFlagBits MSAASamples; // 0 defaults to VK_SAMPLE_COUNT_1_BIT + ImGui_ImplVulkan_PipelineInfo PipelineInfoMain; // Infos for Main Viewport (created by app/user) + //VkRenderPass RenderPass; // --> Since 2025/09/26: set 'PipelineInfoMain.RenderPass' instead + //uint32_t Subpass; // --> Since 2025/09/26: set 'PipelineInfoMain.Subpass' instead + //VkSampleCountFlagBits MSAASamples; // --> Since 2025/09/26: set 'PipelineInfoMain.MSAASamples' instead + //VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; // Since 2025/09/26: set 'PipelineInfoMain.PipelineRenderingCreateInfo' instead // (Optional) Dynamic Rendering - // Need to explicitly enable VK_KHR_dynamic_rendering extension to use this, even for Vulkan 1.3 + setup PipelineRenderingCreateInfo. + // Need to explicitly enable VK_KHR_dynamic_rendering extension to use this, even for Vulkan 1.3 + setup PipelineInfoMain.PipelineRenderingCreateInfo. bool UseDynamicRendering; -#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING - VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; // Optional, valid if .sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR -#endif // (Optional) Allocation, Debugging const VkAllocationCallbacks* Allocator; @@ -121,16 +132,7 @@ IMGUI_IMPL_API void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_i // (Advanced) Use e.g. if you need to recreate pipeline without reinitializing the backend (see #8110, #8111) // The main window pipeline will be created by ImGui_ImplVulkan_Init() if possible (== RenderPass xor (UseDynamicRendering && PipelineRenderingCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR)) // Else, the pipeline can be created, or re-created, using ImGui_ImplVulkan_CreateMainPipeline() before rendering. -struct ImGui_ImplVulkan_PipelineInfo -{ - VkRenderPass RenderPass = VK_NULL_HANDLE; - uint32_t Subpass = 0; - VkSampleCountFlagBits MSAASamples = {}; -#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING - VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; // Optional, valid if .sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR -#endif -}; -IMGUI_IMPL_API void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_PipelineInfo& info); // (render_pass xor (p_dynamic_rendering && p_dynamic_rendering is correct (sType and pNext))) +IMGUI_IMPL_API void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_PipelineInfo* info); // (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually. IMGUI_IMPL_API void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 912527734..08337ee5c 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,6 +41,13 @@ HOW TO UPDATE? Breaking Changes: +- Backends: Vulkan: moved some fields in ImGui_ImplVulkan_InitInfo: + init_info.RenderPass --> init_info.PipelineInfoMain.RenderPass + init_info.Subpass --> init_info.PipelineInfoMain.Subpass + init_info.MSAASamples --> init_info.PipelineInfoMain.MSAASamples + init_info.PipelineRenderingCreateInfo --> init_info.PipelineInfoMain.PipelineRenderingCreateInfo + It makes things more consistent and was desirable to introduce new settings for + secondary viewports. (#8946, #8110, #8111, #8686) [@ocornut, @SuperRonan, @sylmroz] - Backends: Vulkan: renamed ImGui_ImplVulkan_MainPipelineCreateInfo --> ImGui_ImplVulkan_PipelineInfo (introduced very recently and only used by `ImGui_ImplVulkan_CreateMainPipeline()` so it should not affect many users). (#8110, #8111) diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index 176c8c4d3..d9cbfb787 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -411,12 +411,12 @@ int main(int, char**) init_info.Queue = g_Queue; init_info.PipelineCache = g_PipelineCache; init_info.DescriptorPool = g_DescriptorPool; - init_info.RenderPass = wd->RenderPass; - init_info.Subpass = 0; init_info.MinImageCount = g_MinImageCount; init_info.ImageCount = wd->ImageCount; - init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; init_info.Allocator = g_Allocator; + init_info.PipelineInfoMain.RenderPass = wd->RenderPass; + init_info.PipelineInfoMain.Subpass = 0; + init_info.PipelineInfoMain.MSAASamples = VK_SAMPLE_COUNT_1_BIT; init_info.CheckVkResultFn = check_vk_result; ImGui_ImplVulkan_Init(&init_info); diff --git a/examples/example_sdl2_vulkan/main.cpp b/examples/example_sdl2_vulkan/main.cpp index 21e892779..fd845373d 100644 --- a/examples/example_sdl2_vulkan/main.cpp +++ b/examples/example_sdl2_vulkan/main.cpp @@ -417,12 +417,12 @@ int main(int, char**) init_info.Queue = g_Queue; init_info.PipelineCache = g_PipelineCache; init_info.DescriptorPool = g_DescriptorPool; - init_info.RenderPass = wd->RenderPass; - init_info.Subpass = 0; init_info.MinImageCount = g_MinImageCount; init_info.ImageCount = wd->ImageCount; - init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; init_info.Allocator = g_Allocator; + init_info.PipelineInfoMain.RenderPass = wd->RenderPass; + init_info.PipelineInfoMain.Subpass = 0; + init_info.PipelineInfoMain.MSAASamples = VK_SAMPLE_COUNT_1_BIT; init_info.CheckVkResultFn = check_vk_result; ImGui_ImplVulkan_Init(&init_info); diff --git a/examples/example_sdl3_vulkan/main.cpp b/examples/example_sdl3_vulkan/main.cpp index e4cecf210..6f67e990d 100644 --- a/examples/example_sdl3_vulkan/main.cpp +++ b/examples/example_sdl3_vulkan/main.cpp @@ -416,12 +416,12 @@ int main(int, char**) init_info.Queue = g_Queue; init_info.PipelineCache = g_PipelineCache; init_info.DescriptorPool = g_DescriptorPool; - init_info.RenderPass = wd->RenderPass; - init_info.Subpass = 0; init_info.MinImageCount = g_MinImageCount; init_info.ImageCount = wd->ImageCount; - init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; init_info.Allocator = g_Allocator; + init_info.PipelineInfoMain.RenderPass = wd->RenderPass; + init_info.PipelineInfoMain.Subpass = 0; + init_info.PipelineInfoMain.MSAASamples = VK_SAMPLE_COUNT_1_BIT; init_info.CheckVkResultFn = check_vk_result; ImGui_ImplVulkan_Init(&init_info); diff --git a/examples/example_win32_vulkan/main.cpp b/examples/example_win32_vulkan/main.cpp index 7a68ccbdd..cdf4a247e 100644 --- a/examples/example_win32_vulkan/main.cpp +++ b/examples/example_win32_vulkan/main.cpp @@ -404,12 +404,12 @@ int main(int, char**) init_info.Queue = g_Queue; init_info.PipelineCache = g_PipelineCache; init_info.DescriptorPool = g_DescriptorPool; - init_info.RenderPass = wd->RenderPass; - init_info.Subpass = 0; init_info.MinImageCount = g_MinImageCount; init_info.ImageCount = wd->ImageCount; - init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; init_info.Allocator = g_Allocator; + init_info.PipelineInfoMain.RenderPass = wd->RenderPass; + init_info.PipelineInfoMain.Subpass = 0; + init_info.PipelineInfoMain.MSAASamples = VK_SAMPLE_COUNT_1_BIT; init_info.CheckVkResultFn = check_vk_result; ImGui_ImplVulkan_Init(&init_info); diff --git a/imgui.h b/imgui.h index f04e8c0e4..7d71480b8 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.92.4 WIP" -#define IMGUI_VERSION_NUM 19232 +#define IMGUI_VERSION_NUM 19233 #define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000 #define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198 From e4e3c2cc232218019230b470655c69c16ed348ef Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 26 Sep 2025 18:35:07 +0200 Subject: [PATCH 39/39] Backends: Vulkan: amends for docking. Add PipelineInfoForViewports and SwapChainImageUsage. (#8946, #8110, #8111, #8686) --- backends/imgui_impl_vulkan.cpp | 34 +++++++++++++++++----------------- backends/imgui_impl_vulkan.h | 6 +++++- docs/CHANGELOG.txt | 8 ++++++++ 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 85c7e4924..2624f5210 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -1321,7 +1321,9 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info) else IM_ASSERT(info->DescriptorPoolSize > 0); if (info->UseDynamicRendering) - IM_ASSERT(info->PipelineInfoMain.RenderPass == VK_NULL_HANDLE); + IM_ASSERT(info->PipelineInfoMain.RenderPass == VK_NULL_HANDLE && info->PipelineInfoForViewports.RenderPass == VK_NULL_HANDLE); + else if (info->PipelineInfoForViewports.RenderPass == NULL) + info->PipelineInfoForViewports.RenderPass = info->PipelineInfoMain.RenderPass; bd->VulkanInitInfo = *info; @@ -1975,10 +1977,11 @@ static void ImGui_ImplVulkan_CreateWindow(ImGuiViewport* viewport) } // Select Surface Format + ImGui_ImplVulkan_PipelineInfo* pipeline_info = &v->PipelineInfoForViewports; ImVector requestSurfaceImageFormats; #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING - for (uint32_t n = 0; n < v->PipelineRenderingCreateInfo.colorAttachmentCount; n++) - requestSurfaceImageFormats.push_back(v->PipelineRenderingCreateInfo.pColorAttachmentFormats[n]); + for (uint32_t n = 0; n < pipeline_info->PipelineRenderingCreateInfo.colorAttachmentCount; n++) + requestSurfaceImageFormats.push_back(pipeline_info->PipelineRenderingCreateInfo.pColorAttachmentFormats[n]); #endif const VkFormat defaultFormats[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM }; for (VkFormat format : defaultFormats) @@ -1996,28 +1999,25 @@ static void ImGui_ImplVulkan_CreateWindow(ImGuiViewport* viewport) // Create SwapChain, RenderPass, Framebuffer, etc. wd->ClearEnable = (viewport->Flags & ImGuiViewportFlags_NoRendererClear) ? false : true; wd->UseDynamicRendering = v->UseDynamicRendering; - ImGui_ImplVulkanH_CreateOrResizeWindow(v->Instance, v->PhysicalDevice, v->Device, wd, v->QueueFamily, v->Allocator, (int)viewport->Size.x, (int)viewport->Size.y, v->MinImageCount); + ImGui_ImplVulkanH_CreateOrResizeWindow(v->Instance, v->PhysicalDevice, v->Device, wd, v->QueueFamily, v->Allocator, (int)viewport->Size.x, (int)viewport->Size.y, v->MinImageCount, pipeline_info->SwapChainImageUsage); vd->WindowOwned = true; // Create pipeline (shared by all secondary viewports) if (bd->PipelineForViewports == VK_NULL_HANDLE) { - VkPipelineRenderingCreateInfoKHR* p_rendering_info = nullptr; #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING - VkPipelineRenderingCreateInfoKHR rendering_info = {}; if (wd->UseDynamicRendering) { - rendering_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO; - rendering_info.pNext = nullptr; - rendering_info.viewMask = 0; - rendering_info.colorAttachmentCount = 1; - rendering_info.pColorAttachmentFormats = &wd->SurfaceFormat.format; - rendering_info.depthAttachmentFormat = VK_FORMAT_UNDEFINED; - rendering_info.stencilAttachmentFormat = VK_FORMAT_UNDEFINED; - p_rendering_info = &rendering_info; + pipeline_info->PipelineRenderingCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO; + pipeline_info->PipelineRenderingCreateInfo.colorAttachmentCount = 1; + pipeline_info->PipelineRenderingCreateInfo.pColorAttachmentFormats = &wd->SurfaceFormat.format; + } + else + { + IM_ASSERT(pipeline_info->RenderPass != VK_NULL_HANDLE && "Did you set ImGui_ImplVulkan_InitInfo::PipelineInfoForViewports.RenderPass?"); // Since 1.92.4 it is required. } #endif - bd->PipelineForViewports = ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, VK_NULL_HANDLE, wd->UseDynamicRendering ? VK_NULL_HANDLE : wd->RenderPass, VK_SAMPLE_COUNT_1_BIT, 0, p_rendering_info); + bd->PipelineForViewports = ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, VK_NULL_HANDLE, &v->PipelineInfoForViewports); } } @@ -2044,7 +2044,7 @@ static void ImGui_ImplVulkan_SetWindowSize(ImGuiViewport* viewport, ImVec2 size) return; ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; vd->Window.ClearEnable = (viewport->Flags & ImGuiViewportFlags_NoRendererClear) ? false : true; - ImGui_ImplVulkanH_CreateOrResizeWindow(v->Instance, v->PhysicalDevice, v->Device, &vd->Window, v->QueueFamily, v->Allocator, (int)size.x, (int)size.y, v->MinImageCount); + ImGui_ImplVulkanH_CreateOrResizeWindow(v->Instance, v->PhysicalDevice, v->Device, &vd->Window, v->QueueFamily, v->Allocator, (int)size.x, (int)size.y, v->MinImageCount, v->PipelineInfoForViewports.SwapChainImageUsage); } static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*) @@ -2057,7 +2057,7 @@ static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*) if (vd->SwapChainNeedRebuild || vd->SwapChainSuboptimal) { - ImGui_ImplVulkanH_CreateOrResizeWindow(v->Instance, v->PhysicalDevice, v->Device, wd, v->QueueFamily, v->Allocator, (int)viewport->Size.x, (int)viewport->Size.y, v->MinImageCount); + ImGui_ImplVulkanH_CreateOrResizeWindow(v->Instance, v->PhysicalDevice, v->Device, wd, v->QueueFamily, v->Allocator, (int)viewport->Size.x, (int)viewport->Size.y, v->MinImageCount, v->PipelineInfoForViewports.SwapChainImageUsage); vd->SwapChainNeedRebuild = vd->SwapChainSuboptimal = false; } diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index 0fafbc5ec..44b8b8bae 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -76,6 +76,9 @@ struct ImGui_ImplVulkan_PipelineInfo #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; // Optional, valid if .sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR #endif + + // For Secondary viewports only (created/managed by backend) + VkImageUsageFlags SwapChainImageUsage; // 0 defaults to VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT. Add e.g. VK_IMAGE_USAGE_TRANSFER_SRC_BIT if you need to capture from viewports. }; // Initialization data, for ImGui_ImplVulkan_Init() @@ -102,13 +105,14 @@ struct ImGui_ImplVulkan_InitInfo // Pipeline ImGui_ImplVulkan_PipelineInfo PipelineInfoMain; // Infos for Main Viewport (created by app/user) + ImGui_ImplVulkan_PipelineInfo PipelineInfoForViewports; // Infos for Secondary Viewports (created by backend) //VkRenderPass RenderPass; // --> Since 2025/09/26: set 'PipelineInfoMain.RenderPass' instead //uint32_t Subpass; // --> Since 2025/09/26: set 'PipelineInfoMain.Subpass' instead //VkSampleCountFlagBits MSAASamples; // --> Since 2025/09/26: set 'PipelineInfoMain.MSAASamples' instead //VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; // Since 2025/09/26: set 'PipelineInfoMain.PipelineRenderingCreateInfo' instead // (Optional) Dynamic Rendering - // Need to explicitly enable VK_KHR_dynamic_rendering extension to use this, even for Vulkan 1.3 + setup PipelineInfoMain.PipelineRenderingCreateInfo. + // Need to explicitly enable VK_KHR_dynamic_rendering extension to use this, even for Vulkan 1.3 + setup PipelineInfoMain.PipelineRenderingCreateInfo and PipelineInfoViewports.PipelineRenderingCreateInfo. bool UseDynamicRendering; // (Optional) Allocation, Debugging diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 8935c882b..ece3cbdc0 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -109,6 +109,14 @@ Docking+Viewports Branch: backends have been shutdown since 1.90.4. Changed into asserts. (#7175, #8945) - Backends: DX10, DX11, DX12: Disabled DXGI's Alt+Enter default behavior on secondary viewports managed by the backend. (#4350) [@PathogenDavid] +- Backends: Vulkan: Added a way to configure secondary viewport pipelinen creation + by setting init_info.PipelineInfoForViewports fields. (#8946, #8110, #8111, #8686) +- Backends: Vulkan: Added a way to configure secondary viewport swapchain VkImageUsageFlags + to e.g. capture rendering. (#8946, #8940) [@olivier-gerard, @ocornut] + Usage example: + `init_info.PipelineInfoForViewports.SwapChainImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;` +- Backends: Vulkan: pipeline created for secondary viewport automatically match + surface format. (#8686) [@sylmroz] - Backends: Vulkan: Added ImGui_ImplVulkanH_GetWindowDataFromViewport() accessor/helper. (#8946, #8940) [@olivier-gerard] - Examples: DX10, DX11: Disabled DXGI's Alt+Enter default behavior in examples.