Merge branch 'master' into docking

# Conflicts:
#	docs/CHANGELOG.txt
This commit is contained in:
ocornut
2025-10-01 18:41:16 +02:00
15 changed files with 131 additions and 106 deletions

View File

@@ -331,18 +331,18 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
static void ImGui_ImplDX10_DestroyTexture(ImTextureData* tex) static void ImGui_ImplDX10_DestroyTexture(ImTextureData* tex)
{ {
ImGui_ImplDX10_Texture* backend_tex = (ImGui_ImplDX10_Texture*)tex->BackendUserData; if (ImGui_ImplDX10_Texture* backend_tex = (ImGui_ImplDX10_Texture*)tex->BackendUserData)
if (backend_tex == nullptr) {
return;
IM_ASSERT(backend_tex->pTextureView == (ID3D10ShaderResourceView*)(intptr_t)tex->TexID); IM_ASSERT(backend_tex->pTextureView == (ID3D10ShaderResourceView*)(intptr_t)tex->TexID);
backend_tex->pTexture->Release();
backend_tex->pTextureView->Release(); backend_tex->pTextureView->Release();
backend_tex->pTexture->Release();
IM_DELETE(backend_tex); IM_DELETE(backend_tex);
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running) // Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
tex->SetTexID(ImTextureID_Invalid); tex->SetTexID(ImTextureID_Invalid);
tex->SetStatus(ImTextureStatus_Destroyed);
tex->BackendUserData = nullptr; tex->BackendUserData = nullptr;
}
tex->SetStatus(ImTextureStatus_Destroyed);
} }
void ImGui_ImplDX10_UpdateTexture(ImTextureData* tex) void ImGui_ImplDX10_UpdateTexture(ImTextureData* tex)

View File

@@ -349,9 +349,8 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
static void ImGui_ImplDX11_DestroyTexture(ImTextureData* tex) static void ImGui_ImplDX11_DestroyTexture(ImTextureData* tex)
{ {
ImGui_ImplDX11_Texture* backend_tex = (ImGui_ImplDX11_Texture*)tex->BackendUserData; if (ImGui_ImplDX11_Texture* backend_tex = (ImGui_ImplDX11_Texture*)tex->BackendUserData)
if (backend_tex == nullptr) {
return;
IM_ASSERT(backend_tex->pTextureView == (ID3D11ShaderResourceView*)(intptr_t)tex->TexID); IM_ASSERT(backend_tex->pTextureView == (ID3D11ShaderResourceView*)(intptr_t)tex->TexID);
backend_tex->pTextureView->Release(); backend_tex->pTextureView->Release();
backend_tex->pTexture->Release(); backend_tex->pTexture->Release();
@@ -359,8 +358,9 @@ static void ImGui_ImplDX11_DestroyTexture(ImTextureData* tex)
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running) // Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
tex->SetTexID(ImTextureID_Invalid); tex->SetTexID(ImTextureID_Invalid);
tex->SetStatus(ImTextureStatus_Destroyed);
tex->BackendUserData = nullptr; tex->BackendUserData = nullptr;
}
tex->SetStatus(ImTextureStatus_Destroyed);
} }
void ImGui_ImplDX11_UpdateTexture(ImTextureData* tex) void ImGui_ImplDX11_UpdateTexture(ImTextureData* tex)

View File

@@ -423,9 +423,8 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
static void ImGui_ImplDX12_DestroyTexture(ImTextureData* tex) static void ImGui_ImplDX12_DestroyTexture(ImTextureData* tex)
{ {
ImGui_ImplDX12_Texture* backend_tex = (ImGui_ImplDX12_Texture*)tex->BackendUserData; if (ImGui_ImplDX12_Texture* backend_tex = (ImGui_ImplDX12_Texture*)tex->BackendUserData)
if (backend_tex == nullptr) {
return;
IM_ASSERT(backend_tex->hFontSrvGpuDescHandle.ptr == (UINT64)tex->TexID); IM_ASSERT(backend_tex->hFontSrvGpuDescHandle.ptr == (UINT64)tex->TexID);
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
bd->InitInfo.SrvDescriptorFreeFn(&bd->InitInfo, backend_tex->hFontSrvCpuDescHandle, backend_tex->hFontSrvGpuDescHandle); bd->InitInfo.SrvDescriptorFreeFn(&bd->InitInfo, backend_tex->hFontSrvCpuDescHandle, backend_tex->hFontSrvGpuDescHandle);
@@ -436,8 +435,9 @@ static void ImGui_ImplDX12_DestroyTexture(ImTextureData* tex)
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running) // Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
tex->SetTexID(ImTextureID_Invalid); tex->SetTexID(ImTextureID_Invalid);
tex->SetStatus(ImTextureStatus_Destroyed);
tex->BackendUserData = nullptr; tex->BackendUserData = nullptr;
}
tex->SetStatus(ImTextureStatus_Destroyed);
} }
void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex) void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex)

View File

@@ -448,14 +448,14 @@ void ImGui_ImplDX9_UpdateTexture(ImTextureData* tex)
} }
else if (tex->Status == ImTextureStatus_WantDestroy) else if (tex->Status == ImTextureStatus_WantDestroy)
{ {
LPDIRECT3DTEXTURE9 backend_tex = (LPDIRECT3DTEXTURE9)tex->TexID; if (LPDIRECT3DTEXTURE9 backend_tex = (LPDIRECT3DTEXTURE9)tex->TexID)
if (backend_tex == nullptr) {
return;
IM_ASSERT(tex->TexID == (ImTextureID)(intptr_t)backend_tex); IM_ASSERT(tex->TexID == (ImTextureID)(intptr_t)backend_tex);
backend_tex->Release(); backend_tex->Release();
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running) // Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
tex->SetTexID(ImTextureID_Invalid); tex->SetTexID(ImTextureID_Invalid);
}
tex->SetStatus(ImTextureStatus_Destroyed); tex->SetStatus(ImTextureStatus_Destroyed);
} }
} }

View File

@@ -350,16 +350,16 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer>
static void ImGui_ImplMetal_DestroyTexture(ImTextureData* tex) static void ImGui_ImplMetal_DestroyTexture(ImTextureData* tex)
{ {
MetalTexture* backend_tex = (__bridge_transfer MetalTexture*)(tex->BackendUserData); if (MetalTexture* backend_tex = (__bridge_transfer MetalTexture*)(tex->BackendUserData))
if (backend_tex == nullptr) {
return;
IM_ASSERT(backend_tex.metalTexture == (__bridge id<MTLTexture>)(void*)(intptr_t)tex->TexID); IM_ASSERT(backend_tex.metalTexture == (__bridge id<MTLTexture>)(void*)(intptr_t)tex->TexID);
backend_tex.metalTexture = nil; backend_tex.metalTexture = nil;
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running) // Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
tex->SetTexID(ImTextureID_Invalid); tex->SetTexID(ImTextureID_Invalid);
tex->SetStatus(ImTextureStatus_Destroyed);
tex->BackendUserData = nullptr; tex->BackendUserData = nullptr;
}
tex->SetStatus(ImTextureStatus_Destroyed);
} }
void ImGui_ImplMetal_UpdateTexture(ImTextureData* tex) void ImGui_ImplMetal_UpdateTexture(ImTextureData* tex)

View File

@@ -309,8 +309,7 @@ void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffe
static void ImGui_ImplSDLGPU3_DestroyTexture(ImTextureData* tex) static void ImGui_ImplSDLGPU3_DestroyTexture(ImTextureData* tex)
{ {
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
SDL_GPUTexture* raw_tex = (SDL_GPUTexture*)(intptr_t)tex->GetTexID(); if (SDL_GPUTexture* raw_tex = (SDL_GPUTexture*)(intptr_t)tex->GetTexID())
if (raw_tex != nullptr)
SDL_ReleaseGPUTexture(bd->InitInfo.Device, raw_tex); SDL_ReleaseGPUTexture(bd->InitInfo.Device, raw_tex);
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running) // Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)

View File

@@ -269,9 +269,7 @@ void ImGui_ImplSDLRenderer2_UpdateTexture(ImTextureData* tex)
} }
else if (tex->Status == ImTextureStatus_WantDestroy) else if (tex->Status == ImTextureStatus_WantDestroy)
{ {
SDL_Texture* sdl_texture = (SDL_Texture*)(intptr_t)tex->TexID; if (SDL_Texture* sdl_texture = (SDL_Texture*)(intptr_t)tex->TexID)
if (sdl_texture == nullptr)
return;
SDL_DestroyTexture(sdl_texture); SDL_DestroyTexture(sdl_texture);
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running) // Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)

View File

@@ -285,9 +285,7 @@ void ImGui_ImplSDLRenderer3_UpdateTexture(ImTextureData* tex)
} }
else if (tex->Status == ImTextureStatus_WantDestroy) else if (tex->Status == ImTextureStatus_WantDestroy)
{ {
SDL_Texture* sdl_texture = (SDL_Texture*)(intptr_t)tex->TexID; if (SDL_Texture* sdl_texture = (SDL_Texture*)(intptr_t)tex->TexID)
if (sdl_texture == nullptr)
return;
SDL_DestroyTexture(sdl_texture); SDL_DestroyTexture(sdl_texture);
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running) // Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)

View File

@@ -693,9 +693,8 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
static void ImGui_ImplVulkan_DestroyTexture(ImTextureData* tex) static void ImGui_ImplVulkan_DestroyTexture(ImTextureData* tex)
{ {
ImGui_ImplVulkan_Texture* backend_tex = (ImGui_ImplVulkan_Texture*)tex->BackendUserData; if (ImGui_ImplVulkan_Texture* backend_tex = (ImGui_ImplVulkan_Texture*)tex->BackendUserData)
if (backend_tex == nullptr) {
return;
IM_ASSERT(backend_tex->DescriptorSet == (VkDescriptorSet)tex->TexID); IM_ASSERT(backend_tex->DescriptorSet == (VkDescriptorSet)tex->TexID);
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
@@ -707,8 +706,9 @@ static void ImGui_ImplVulkan_DestroyTexture(ImTextureData* tex)
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running) // Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
tex->SetTexID(ImTextureID_Invalid); tex->SetTexID(ImTextureID_Invalid);
tex->SetStatus(ImTextureStatus_Destroyed);
tex->BackendUserData = nullptr; tex->BackendUserData = nullptr;
}
tex->SetStatus(ImTextureStatus_Destroyed);
} }
void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex) void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex)

View File

@@ -535,10 +535,8 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
static void ImGui_ImplWGPU_DestroyTexture(ImTextureData* tex) static void ImGui_ImplWGPU_DestroyTexture(ImTextureData* tex)
{ {
ImGui_ImplWGPU_Texture* backend_tex = (ImGui_ImplWGPU_Texture*)tex->BackendUserData; if (ImGui_ImplWGPU_Texture* backend_tex = (ImGui_ImplWGPU_Texture*)tex->BackendUserData)
if (backend_tex == nullptr) {
return;
IM_ASSERT(backend_tex->TextureView == (WGPUTextureView)(intptr_t)tex->TexID); IM_ASSERT(backend_tex->TextureView == (WGPUTextureView)(intptr_t)tex->TexID);
wgpuTextureViewRelease(backend_tex->TextureView); wgpuTextureViewRelease(backend_tex->TextureView);
wgpuTextureRelease(backend_tex->Texture); wgpuTextureRelease(backend_tex->Texture);
@@ -546,8 +544,9 @@ static void ImGui_ImplWGPU_DestroyTexture(ImTextureData* tex)
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running) // Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
tex->SetTexID(ImTextureID_Invalid); tex->SetTexID(ImTextureID_Invalid);
tex->SetStatus(ImTextureStatus_Destroyed);
tex->BackendUserData = nullptr; tex->BackendUserData = nullptr;
}
tex->SetStatus(ImTextureStatus_Destroyed);
} }
void ImGui_ImplWGPU_UpdateTexture(ImTextureData* tex) void ImGui_ImplWGPU_UpdateTexture(ImTextureData* tex)

View File

@@ -73,6 +73,18 @@ Other Changes:
- Misc: Debuggers: added type formatters for the LLDB debuggers (e.g. Xcode, - Misc: Debuggers: added type formatters for the LLDB debuggers (e.g. Xcode,
Android Studio & more) to provide nicer display for ImVec2, ImVec4, ImVector etc. Android Studio & more) to provide nicer display for ImVec2, ImVec4, ImVector etc.
See misc/debuggers/ for details. (#8950) [@mentlerd] See misc/debuggers/ for details. (#8950) [@mentlerd]
- Textures: fixed a crash if texture status is set to _WantDestroy by a backend after
it had already been destroyed. This would typically happen when calling backend's
ImGui_ImplXXXX_InvalidateDeviceObjects() helpers twice in a row. (#8977, #8811)
- Textures: allowed backend to destroy texture while inside the NewFrame/EndFrame
scope. Basically if a backend decide to destroy a texture that we didn't request
to destroy (for e.g. freeing resources) the texture is immediately set to
a _WantCreate status again. (#8811)
- Textures: fixed an issue preventing multi-contexts sharing a ImFontAtlas from
being possible to destroy in any order.
- Textures: fixed not updating ImTextureData's RefCount when destroying a context
using a shared ImFontAtlas, leading standard backends to not properly free
texture resources. (#8975) [@icrashstuff]
- CI: Updates Windows CI scripts to generate/use VulkanSDK. (#8925, #8778) [@yaz0r] - CI: Updates Windows CI scripts to generate/use VulkanSDK. (#8925, #8778) [@yaz0r]
- Backends: all backends call ImGuiPlatformIO::ClearPlatformHandlers() and - Backends: all backends call ImGuiPlatformIO::ClearPlatformHandlers() and
ClearRendererHandlers() on shutdown, so as not to leave function pointers ClearRendererHandlers() on shutdown, so as not to leave function pointers
@@ -80,6 +92,7 @@ Other Changes:
- Backends: DirectX12: reuse a command list and allocator for texture uploads instead - Backends: DirectX12: reuse a command list and allocator for texture uploads instead
of recreating them each time. (#8963, #8465) [@RT2Code] of recreating them each time. (#8963, #8465) [@RT2Code]
- Backends: DirectX12: Rework synchronization logic. (#8961) [@RT2Code] - Backends: DirectX12: Rework synchronization logic. (#8961) [@RT2Code]
(presumably fixes old hard-to-repro crash issues such as #3463, #5018)
- Backends: DirectX12: Enable swapchain tearing if available. (#8965) [@RT2Code] - Backends: DirectX12: Enable swapchain tearing if available. (#8965) [@RT2Code]
- Backends: OpenGL3: fixed GL loader to work on Haiku OS which does not support - Backends: OpenGL3: fixed GL loader to work on Haiku OS which does not support
`RTLD_NOLOAD`. (#8952) [@Xottab-DUTY, @threedeyes] `RTLD_NOLOAD`. (#8952) [@Xottab-DUTY, @threedeyes]
@@ -94,6 +107,9 @@ Other Changes:
XInput's dwPacketNumber has not changed. (#8556) [@MidTerm-CN] XInput's dwPacketNumber has not changed. (#8556) [@MidTerm-CN]
- Backends: Vulkan: added a way to specify custom shaders by filling init fields - Backends: Vulkan: added a way to specify custom shaders by filling init fields
CustomShaderVertCreateInfo and CustomShaderFragCreateInfo. (#8585, #8271) [@johan0A] CustomShaderVertCreateInfo and CustomShaderFragCreateInfo. (#8585, #8271) [@johan0A]
- Backends: DX9,DX10,DX11,DX12,Metal,Vulkan,WGPU,SDLRenderer2,SDLRenderer3:
ensure that a texture in _WantDestroy state always turn to _Destroyed even
if your underlying graphics data was already destroyed. (#8977)
- Examples: SDL2+DirectX11: Try WARP software driver if hardware driver is - Examples: SDL2+DirectX11: Try WARP software driver if hardware driver is
not available. (#5924, #5562) not available. (#5924, #5562)
- Examples: SDL3+DirectX11: Added SDL3+DirectX11 example. (#8956, #8957) [@tomaz82] - Examples: SDL3+DirectX11: Added SDL3+DirectX11 example. (#8956, #8957) [@tomaz82]

View File

@@ -107,22 +107,26 @@ Reading the changelogs is a good way to keep up to date with the things Dear ImG
### Demo ### Demo
Calling the `ImGui::ShowDemoWindow()` function will create a demo window showcasing a variety of features and examples. The code is always available for reference in `imgui_demo.cpp`. [Here's how the demo looks](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v167/v167-misc.png). Calling the `ImGui::ShowDemoWindow()` function will create a demo window showcasing a variety of features and examples. The code is always available for reference in `imgui_demo.cpp`.
- [Web version of the demo](https://pthom.github.io/imgui_manual_online/manual/imgui_manual.html) courtesy of [@pthom](https://github.com/pthom).
- [Screenshot of the demo](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v167/v167-misc.png).
You should be able to build the examples from sources. If you don't, let us know! If you want to have a quick look at some Dear ImGui features, you can download Windows binaries of the demo app here: You should be able to build the examples from sources. If you don't, let us know! If you want to have a quick look at some Dear ImGui features, you can download Windows binaries of the demo app here:
- [imgui-demo-binaries-20250625.zip](https://www.dearimgui.com/binaries/imgui-demo-binaries-20250625.zip) (Windows, 1.92.0, built 2025/06/25, master) or [older binaries](https://www.dearimgui.com/binaries). - [imgui-demo-binaries-20250625.zip](https://www.dearimgui.com/binaries/imgui-demo-binaries-20250625.zip) (Windows, 1.92.0, built 2025/06/25, master) or [older binaries](https://www.dearimgui.com/binaries).
The demo applications are not DPI aware so expect some blurriness on a 4K screen. For DPI awareness in your application, you can load/reload your font at a different scale and scale your style with `style.ScaleAllSizes()` (see [FAQ](https://www.dearimgui.com/faq)).
### Getting Started & Integration ### Getting Started & Integration
See the [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) guide for details. See the [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) guide for details.
On most platforms and when using C++, **you should be able to use a combination of the [imgui_impl_xxxx](https://github.com/ocornut/imgui/tree/master/backends) backends without modification** (e.g. `imgui_impl_win32.cpp` + `imgui_impl_dx11.cpp`). If your engine supports multiple platforms, consider using more imgui_impl_xxxx files instead of rewriting them: this will be less work for you, and you can get Dear ImGui running immediately. You can _later_ decide to rewrite a custom backend using your custom engine functions if you wish so. On most platforms and when using C++, **you should be able to use a combination of the [imgui_impl_xxxx](https://github.com/ocornut/imgui/tree/master/backends) backends without modification** (e.g. `imgui_impl_win32.cpp` + `imgui_impl_dx11.cpp`). If your engine supports multiple platforms, consider using more imgui_impl_xxxx files instead of rewriting them: this will be less work for you, and you can get Dear ImGui running immediately. You can _later_ decide to rewrite a custom backend using your custom engine functions if you wish so.
Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/keyboard/gamepad inputs 2) uploading a texture to your GPU/render engine 3) providing a render function that can bind textures and render textured triangles, which is essentially what Backends are doing. The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications doing just that: setting up a window and using backends. If you follow the [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) guide it should in theory take you less than an hour to integrate Dear ImGui. **Make sure to spend time reading the [FAQ](https://www.dearimgui.com/faq), comments, and the examples applications!** Integrating Dear ImGui within your custom engine is a matter of mainly 1) wiring mouse/keyboard/gamepad inputs 2) uploading a texture to your GPU/render engine 3) providing a render function that can create/update textures and render textured triangles. This is exactly what backends are doing.
- The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications setting up a window and using standard backends.
- The [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) guide has instructions to integrate imgui into an existing application using standard backends. It should in theory take you less than an hour to integrate Dear ImGui into your existing codebase where support libraries are linked. Less if you read carefully.
- The [Backends](https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md) guide explains what backends are doing, and has instructions to implement a custom backend. You can also refer to the source code of our ~20 backends to understand how they work.
- Generally, **make sure to spend time reading the [FAQ](https://www.dearimgui.com/faq), comments, and the examples applications!**
Officially maintained backends/bindings (in repository): Officially maintained backends (in repository):
- Renderers: DirectX9, DirectX10, DirectX11, DirectX12, Metal, OpenGL/ES/ES2, SDL_GPU, SDL_Renderer2/3, Vulkan, WebGPU. - Renderers: DirectX9, DirectX10, DirectX11, DirectX12, Metal, OpenGL/ES/ES2, SDL_GPU, SDL_Renderer2/3, Vulkan, WebGPU.
- Platforms: GLFW, SDL2/SDL3, Win32, Glut, OSX, Android. - Platforms: GLFW, SDL2/SDL3, Win32, Glut, OSX, Android.
- Frameworks: Allegro5, Emscripten. - Frameworks: Allegro5, Emscripten.
@@ -130,7 +134,7 @@ Officially maintained backends/bindings (in repository):
[Third-party backends/bindings](https://github.com/ocornut/imgui/wiki/Bindings) wiki page: [Third-party backends/bindings](https://github.com/ocornut/imgui/wiki/Bindings) wiki page:
- Languages: C, C# and: Beef, ChaiScript, CovScript, Crystal, D, Go, Haskell, Haxe/hxcpp, Java, JavaScript, Julia, Kotlin, Lobster, Lua, Nim, Odin, Pascal, PureBasic, Python, ReaScript, Ruby, Rust, Swift, Zig... - Languages: C, C# and: Beef, ChaiScript, CovScript, Crystal, D, Go, Haskell, Haxe/hxcpp, Java, JavaScript, Julia, Kotlin, Lobster, Lua, Nim, Odin, Pascal, PureBasic, Python, ReaScript, Ruby, Rust, Swift, Zig...
- Frameworks: AGS/Adventure Game Studio, Amethyst, Blender, bsf, Cinder, Cocos2d-x, Defold, Diligent Engine, Ebiten, Flexium, GML/Game Maker Studio, GLEQ, Godot, GTK3, Irrlicht Engine, JUCE, LÖVE+LUA, Mach Engine, Magnum, Marmalade, Monogame, NanoRT, nCine, Nim Game Lib, Nintendo 3DS/Switch/WiiU (homebrew), Ogre, openFrameworks, OSG/OpenSceneGraph, Orx, Photoshop, px_render, Qt/QtDirect3D, raylib, SFML, Sokol, Unity, Unreal Engine 4/5, UWP, vtk, VulkanHpp, VulkanSceneGraph, Win32 GDI, WxWidgets. - Frameworks: AGS/Adventure Game Studio, Amethyst, Blender, bsf, Cinder, Cocos2d-x, Defold, Diligent Engine, Ebiten, Flexium, GML/Game Maker Studio, GLEQ, Godot, GTK3, Irrlicht Engine, JUCE, LÖVE+LUA, Mach Engine, Magnum, Marmalade, Monogame, NanoRT, nCine, Nim Game Lib, Nintendo 3DS/Switch/WiiU (homebrew), Ogre, openFrameworks, OSG/OpenSceneGraph, Orx, Photoshop, px_render, Qt/QtDirect3D, raylib, SFML, Sokol, Unity, Unreal Engine 4/5, UWP, vtk, VulkanHpp, VulkanSceneGraph, Win32 GDI, WxWidgets.
- Many bindings are auto-generated (by good old [cimgui](https://github.com/cimgui/cimgui) or newer/experimental [dear_bindings](https://github.com/dearimgui/dear_bindings)), you can use their metadata output to generate bindings for other languages. - Many bindings are auto-generated (by good old [cimgui](https://github.com/cimgui/cimgui) or our newer [dear_bindings](https://github.com/dearimgui/dear_bindings)), you can use their metadata output to generate bindings for other languages.
[Useful Extensions/Widgets](https://github.com/ocornut/imgui/wiki/Useful-Extensions) wiki page: [Useful Extensions/Widgets](https://github.com/ocornut/imgui/wiki/Useful-Extensions) wiki page:
- Automation/testing, Text editors, node editors, timeline editors, plotting, software renderers, remote network access, memory editors, gizmos, etc. Notable and well supported extensions include [ImPlot](https://github.com/epezent/implot) and [Dear ImGui Test Engine](https://github.com/ocornut/imgui_test_engine). - Automation/testing, Text editors, node editors, timeline editors, plotting, software renderers, remote network access, memory editors, gizmos, etc. Notable and well supported extensions include [ImPlot](https://github.com/epezent/implot) and [Dear ImGui Test Engine](https://github.com/ocornut/imgui_test_engine).

View File

@@ -4426,7 +4426,7 @@ void ImGui::Shutdown()
for (ImFontAtlas* atlas : g.FontAtlases) for (ImFontAtlas* atlas : g.FontAtlases)
{ {
UnregisterFontAtlas(atlas); UnregisterFontAtlas(atlas);
if (atlas->OwnerContext == &g) if (atlas->RefCount == 0)
{ {
atlas->Locked = false; atlas->Locked = false;
IM_DELETE(atlas); IM_DELETE(atlas);
@@ -9461,6 +9461,8 @@ void ImGui::RegisterFontAtlas(ImFontAtlas* atlas)
atlas->RefCount++; atlas->RefCount++;
g.FontAtlases.push_back(atlas); g.FontAtlases.push_back(atlas);
ImFontAtlasAddDrawListSharedData(atlas, &g.DrawListSharedData); ImFontAtlasAddDrawListSharedData(atlas, &g.DrawListSharedData);
for (ImTextureData* tex : atlas->TexList)
tex->RefCount = (unsigned short)atlas->RefCount;
} }
void ImGui::UnregisterFontAtlas(ImFontAtlas* atlas) void ImGui::UnregisterFontAtlas(ImFontAtlas* atlas)
@@ -9470,6 +9472,8 @@ void ImGui::UnregisterFontAtlas(ImFontAtlas* atlas)
ImFontAtlasRemoveDrawListSharedData(atlas, &g.DrawListSharedData); ImFontAtlasRemoveDrawListSharedData(atlas, &g.DrawListSharedData);
g.FontAtlases.find_erase(atlas); g.FontAtlases.find_erase(atlas);
atlas->RefCount--; atlas->RefCount--;
for (ImTextureData* tex : atlas->TexList)
tex->RefCount = (unsigned short)atlas->RefCount;
} }
// Use ImDrawList::_SetTexture(), making our shared g.FontStack[] authoritative against window-local ImDrawList. // Use ImDrawList::_SetTexture(), making our shared g.FontStack[] authoritative against window-local ImDrawList.

View File

@@ -3614,8 +3614,10 @@ struct ImTextureData
ImTextureID GetTexID() const { return TexID; } ImTextureID GetTexID() const { return TexID; }
// Called by Renderer backend // Called by Renderer backend
void SetTexID(ImTextureID tex_id) { TexID = tex_id; } // Call after creating or destroying the texture. Never modify TexID directly! // - Call SetTexID() and SetStatus() after honoring texture requests. Never modify TexID and Status directly!
void SetStatus(ImTextureStatus status) { Status = status; } // Call after honoring a request. Never modify Status directly! // - A backend may decide to destroy a texture that we did not request to destroy, which is fine (e.g. freeing resources), but we immediately set the texture back in _WantCreate mode.
void SetTexID(ImTextureID tex_id) { TexID = tex_id; }
void SetStatus(ImTextureStatus status) { Status = status; if (status == ImTextureStatus_Destroyed && !WantDestroyNextFrame) Status = ImTextureStatus_WantCreate; }
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@@ -2796,21 +2796,29 @@ void ImFontAtlasUpdateNewFrame(ImFontAtlas* atlas, int frame_count, bool rendere
if (tex->Status == ImTextureStatus_WantCreate && atlas->RendererHasTextures) if (tex->Status == ImTextureStatus_WantCreate && atlas->RendererHasTextures)
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL && "Backend set texture's TexID/BackendUserData but did not update Status to OK."); IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL && "Backend set texture's TexID/BackendUserData but did not update Status to OK.");
// Request destroy
// - Keep bool to true in order to differentiate a planned destroy vs a destroy decided by the backend.
// - We don't destroy pixels right away, as backend may have an in-flight copy from RAM.
if (tex->WantDestroyNextFrame && tex->Status != ImTextureStatus_Destroyed && tex->Status != ImTextureStatus_WantDestroy)
{
IM_ASSERT(tex->Status == ImTextureStatus_OK || tex->Status == ImTextureStatus_WantCreate || tex->Status == ImTextureStatus_WantUpdates);
tex->Status = ImTextureStatus_WantDestroy;
}
// If a texture has never reached the backend, they don't need to know about it.
// (note: backends between 1.92.0 and 1.92.4 could set an already destroyed texture to ImTextureStatus_WantDestroy
// when invalidating graphics objects twice, which would previously remove it from the list and crash.)
if (tex->Status == ImTextureStatus_WantDestroy && tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL)
tex->Status = ImTextureStatus_Destroyed;
// Process texture being destroyed
if (tex->Status == ImTextureStatus_Destroyed) if (tex->Status == ImTextureStatus_Destroyed)
{ {
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL && "Backend set texture Status to Destroyed but did not clear TexID/BackendUserData!"); IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL && "Backend set texture Status to Destroyed but did not clear TexID/BackendUserData!");
if (tex->WantDestroyNextFrame) if (tex->WantDestroyNextFrame)
remove_from_list = true; // Destroy was scheduled by us remove_from_list = true; // Destroy was scheduled by us
else else
tex->Status = ImTextureStatus_WantCreate; // Destroy was done was backend (e.g. freed resources mid-run) tex->Status = ImTextureStatus_WantCreate; // Destroy was done was backend: recreate it (e.g. freed resources mid-run)
}
else if (tex->WantDestroyNextFrame && tex->Status != ImTextureStatus_WantDestroy)
{
// Request destroy.
// - Keep bool to true in order to differentiate a planned destroy vs a destroy decided by the backend.
// - We don't destroy pixels right away, as backend may have an in-flight copy from RAM.
IM_ASSERT(tex->Status == ImTextureStatus_OK || tex->Status == ImTextureStatus_WantCreate || tex->Status == ImTextureStatus_WantUpdates);
tex->Status = ImTextureStatus_WantDestroy;
} }
// The backend may need defer destroying by a few frames, to handle texture used by previous in-flight rendering. // The backend may need defer destroying by a few frames, to handle texture used by previous in-flight rendering.
@@ -2818,13 +2826,10 @@ void ImFontAtlasUpdateNewFrame(ImFontAtlas* atlas, int frame_count, bool rendere
if (tex->Status == ImTextureStatus_WantDestroy) if (tex->Status == ImTextureStatus_WantDestroy)
tex->UnusedFrames++; tex->UnusedFrames++;
// If a texture has never reached the backend, they don't need to know about it.
if (tex->Status == ImTextureStatus_WantDestroy && tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL)
remove_from_list = true;
// Destroy and remove // Destroy and remove
if (remove_from_list) if (remove_from_list)
{ {
IM_ASSERT(atlas->TexData != tex);
tex->DestroyPixels(); tex->DestroyPixels();
IM_DELETE(tex); IM_DELETE(tex);
atlas->TexList.erase(atlas->TexList.begin() + tex_n); atlas->TexList.erase(atlas->TexList.begin() + tex_n);