225 Commits
Author SHA1 Message Date
moonpower 1b1a443e19 Merge remote-tracking branch 'upstream/master' into HEAD
build / Build - Windows (push) Has been cancelled
build / Build - Linux (push) Has been cancelled
build / Build - MacOS (push) Has been cancelled
build / Build - iOS (push) Has been cancelled
build / Build - Emscripten (push) Has been cancelled
build / Build - Android (push) Has been cancelled
build / Test - Windows (push) Has been cancelled
build / Test - Linux (push) Has been cancelled
scheduled / scheduled (push) Successful in 14s
2026-06-03 03:05:20 +02:00
ocornut c4eaac6d48 Fonts: fixed an issue where passing a manually created ImFontAtlas to CreateContext() would incorrectly destroy it in DestroyContext() when ref-count gets back to zero. (#9426)
# Conflicts:
#	docs/CHANGELOG.txt
2026-06-02 19:05:40 +02:00
ocornut 5a42cddcd2 Fixed a build issue when defined IMGUI_API + IMGUI_DISABLE_OBSOLETE_FUNCTIONS. (#9424)
Amend 6df50a0
2026-06-02 18:40:14 +02:00
ocornut 995e4a65ff (Breaking) TreeNode: commented out legacy name ImGuiTreeNodeFlags_SpanTextWidth which was obsoleted in 1.90.7 (May 2024). Use ImGuiTreeNodeFlags_SpanLabelWidth instead. 2026-06-02 18:37:01 +02:00
omarandGitHub a054a016e2 Docs: Fonts: amends. 2026-06-02 18:09:48 +02:00
omarandGitHub 045a0907f4 Docs: Fonts.md: added notes about TexMinWidth,TexMinHeight.
Probably misplaced: the document could have a section about memory usage considerations?
2026-06-02 18:05:23 +02:00
ocornut 5aa0393a15 DrawList: don't mark ImDrawListFlags_TextNoPixelSnap as internal in comments. (#3437, #9417, #2291) 2026-06-01 17:23:11 +02:00
ocornut f241419b78 Tabs: use AddRectFilled(). 2026-06-01 16:49:18 +02:00
FlexanandGitHub 3495e329f3 Fixed small typo in demo code (#9425) 2026-06-01 15:34:00 +02:00
ocornut 3b99fc4883 ColorButton: small rendering tweak/optimization for the alpha checkerboard.
Inverting the pattern means that for our typical 3x3 grid we don't need to draw 1+4 rounded rectangles, only 1.
This also fix the slightly rounding mismatch when switching from a=255 to a<255 paths.
2026-06-01 14:23:29 +02:00
DexandGitHub 70f02b0558 Docs: Fix small grammar mistake in README. (#9423) 2026-05-31 13:54:30 +02:00
ocornut cac16b0d16 DrawList: rename ImDrawListFlags_NoTextPixelSnap -> ImDrawListFlags_TextNoPixelSnap. (#3437, #9417, #2291)
Amend 1d33ea9
2026-05-29 18:39:17 +02:00
ocornut 1d33ea939f DrawList: added ImDrawListFlags_NoTextPixelSnap to disable snapping of AddText() coordinates for a given scope. (#3437, #9417, #2291)
This may evolve into a per-call ImDrawFlags option as well.
+ clip_rect.Max.y early out may be applied before truncation.
2026-05-29 18:12:11 +02:00
ocornut 75f985998b Using custom ceilf inline impl in ImGui::CalcTextSize().
Amend 7b0bf230, 4622fa4b6, 12b7977. (#791)
2026-05-29 15:59:44 +02:00
ocornut 12b7977555 Tweak CalcTextSize() awkward width rounding/ceiling code to reduce floating-point imprecisions altering the result by 1 even at relatively small width. (#791) + apply same fudge factor to less important roundings.
ceilf() is still measurable e.g. ballpark +0.5 for 200k calls.
2026-05-28 19:19:11 +02:00
ocornut 33bb693b4c DrawList: skip PathLineTo/PathStroke calls for common AddLine(), AddLineH(), AddLineV() functions. (#4091) 2026-05-28 15:37:29 +02:00
ocornut 783eba926f Docs: retroactively amend 1.92.8 changelog about ImDrawFlags_Closed value.
Amend 6df50a0
2026-05-28 11:37:37 +02:00
qwerandocornut ac07da2b5b Fonts: Added macros to disable ProggyClean/ProggyVector separately. (#9407) 2026-05-27 16:50:53 +02:00
ocornut 243097ca8f Docs: retroactively amend changelog for AddLineH(), AddLineV().
Amend 691b89b. (#9360)
2026-05-26 20:36:29 +02:00
ocornut fbcf95193f ImFontAtlas: moved common TexData calls into a same helper functions, so adding new ones is easier. 2026-05-22 20:03:30 +02:00
ocornut 24a80f74a4 InputText, Style: added InputTextCursorSize to configure cursor/caret thickness. (#7031, #9409) 2026-05-22 19:12:36 +02:00
ocornut 904b663184 Clarify support for "%s" shortcuts in functions taking format strings. (#9404, #3466, #6846) 2026-05-19 18:50:39 +02:00
MouriNarutoandocornut 3e7b79aa17 Backends: Win32: use SetProcessDpiAwarenessContext instead of SetThreadDpiAwarenessContext when available, to fix the OpenGL3 Win32 example DPI scaling issue. (#9403) 2026-05-19 17:53:36 +02:00
ocornut e41d691da1 Demo: Tree Nodes: extract 'Tree Nodes->Selectable Nodes' into its own thing.
+ comments (#9401)
2026-05-18 14:31:58 +02:00
ocornut 93e396ffb7 Textures: call ImTextureDataUpdateNewFrame() for textures registered via RegisterUserTexture(). (#8789, #8465)
Amend
2026-05-15 16:38:45 +02:00
ocornut 068e055510 Textures: extract ImTextureDataUpdateNewFrame() out of ImFontAtlasUpdateNewFrame(). (#8465) 2026-05-15 16:38:45 +02:00
ocornut db161b84c9 Windows: clicking on a window's empty-space to move/focus a window checks for lack of queued focus request. (#9382) 2026-05-15 13:45:03 +02:00
ocornut 4088a4f40c Windows: clicking on a window's empty-space to move/focus a window checks for lack of mouse button ownership. (#9382) 2026-05-15 13:44:40 +02:00
ocornut 46a050fff2 Nav: minor optimization NavUpdate().
To be honest this is mostly to ease debug stepping in the common case.
2026-05-15 13:43:45 +02:00
ocornut c7767926ce Version 1.92.9 WIP 2026-05-15 13:28:32 +02:00
ocornut 310c719a1f Rework definition of ImDrawFlags_InvalidMask_ so it more strictly fits in an int32 for non C/C++ languages where it matters. (#9396, #9397) 2026-05-15 10:48:24 +02:00
ocornut b2546a5c93 Comments on not needing to use ImDrawFlags_RoundCornersAll. 2026-05-13 12:46:07 +02:00
ocornut e0f5f9a14c Amend AddRect(), AddPolyline() error detection to safely return an trigger error handling mechanism.
Amend 6df50a0667
2026-05-12 17:40:28 +02:00
ocornut 8936b58fe2 Version 1.92.8
Include minor bits: adjust activeid logging, tweak comments.
2026-05-12 16:30:30 +02:00
omarandGitHub eebaddd340 Docs: added SECURITY.md. 2026-05-11 19:03:08 +02:00
ocornut 73afb6b6e6 Fonts: clarify that ClearFonts() be useful over calling Clear(). 2026-05-11 17:45:59 +02:00
ocornut b8f6c51af7 Fonts: move ClearFonts(), ClearInputData(), ClearTexData() implementation (no other changes) 2026-05-11 17:42:08 +02:00
ocornut 4ac473b2c7 Fixed BeginMenu() leading to window with is_resizable_width=true. Fix/amend 95bd1577d + ac1f57b. (#9355) 2026-05-11 16:35:40 +02:00
ocornut ac1f57ba0c Fixed BeginMenu() leading to window with is_resizable_width=true. Fix/amend 95bd1577d. (#9355)
We should instead probably make BeginChild() not set on ImGuiWindowFlags_AlwaysAutoResize on either ResizeX or ResizeY, but that'll be done later.
2026-05-11 16:34:33 +02:00
ocornut 821a396556 Fixed warning on Clang 26. 2026-05-11 15:59:42 +02:00
manuelandocornut 2b31f65167 Examples: WebGPU+GLFW/SDL2/SDL3: wire up the IMGUI_WGVK_DIR path. (#9387)
The block was a stub - find Vulkan, detect Wayland/X11, set the SUPPORT_*_SURFACE defines that wgvk.c needs.
2026-05-11 15:42:16 +02:00
manuelandocornut b58836f287 Backends: WebGPU: detect WGSL support at runtime instead of excluding WGVK at compile time. (#9387)
Previously WGVK was hard-disabled from WGSL via #if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK),
forcing the SPIRV fallback unconditionally. Now the WGSL path is attempted on all backends
and an empty stage_desc is returned when the module fails to compile letting the existing
SPIRV fallback at the call site kick in.
2026-05-11 15:38:27 +02:00
ocornut bca5a69928 BeginMenu()/MenuItem(): fixed accidental triggering of child menu items when opening a menu inside a small host window forcing the child menu window to be repositioned under the mouse cursor. (#8233, #9394)
nb: ImGuiSelectableFlags_NoHoldingActiveID is not used anymore. Would remove remove once we remove the unnecessary call to Selectable() from MenuItem().
2026-05-11 15:32:39 +02:00
ocornut eb453f2be6 Checkbox, Style: added ImGuiCol_CheckboxSelectedBg. (#9392) 2026-05-11 14:30:34 +02:00
ocornut 56b37bf93c Inputs: SetItemKeyOwner(): does not set ownership is key is already taken.
(#456, #2637, #2620, #2891, #3370, #3724, #4828, #5108, #5242, #5641)
2026-05-07 21:22:33 +02:00
ocornut 0eae77f783 Inputs: SetItemKeyOwner(): return true if ownership has been requested, which can to be checked to accurately gate further input test.
(#456, #2637, #2620, #2891, #3370, #3724, #4828, #5108, #5242, #5641)
2026-05-07 21:15:27 +02:00
ocornut 02ccd9f348 Scrolling, Inputs: using mouse wheel to scroll takes and keeps ownership of the corresponding keys while a wheeling window is locked.
Ref 4448d975d. (#2604, #3795)
2026-05-07 20:51:57 +02:00
ocornut 163b8670c8 Demo: added image viewer with magnifier and grid. 2026-05-07 20:20:05 +02:00
ocornut a70b97ee48 Warning fixes. 2026-05-07 16:51:34 +02:00
ocornut 6df50a0667 (Breaking) DrawList: swapped the last two arguments of AddRect(), AddPolyline(), PathStroke(). thickness<>flags.
Added inline redirection functions when IMGUI_DISABLE_OBSOLETE_FUNCTIONS is off.
Marked the old functions are =delete when IMGUI_DISABLE_OBSOLETE_FUNCTIONS is on, to allow for better type-checking.
The aim is to be able to use/add flags to more ImDrawList functions, and making existing functions consistents was deemed very desirable.
2026-05-07 16:37:57 +02:00
ocornut 976c5c0f3a Textures: extract ImTextureDataQueueUpload() out of ImFontAtlasTextureBlockQueueUpload() (#8465)
Not atlas specific, in support of texture system.
2026-05-06 16:19:39 +02:00
Mikko Mononenandocornut 691b89baae ImDrawList: added AddLineH(), AddLineV() helpers. (#9360)
This commit is aimed to be a lossless transform. Further layout fixes in subsequent commits.
2026-04-28 17:04:54 +02:00
ocornut c0b693b1d4 MultiSelect: Box-Select + Tables: fixed when using SpanAllColumns paths. (#9383, #7994)
Amend d1a8995 which didn't fix the thing it claimed to fix, as my naive last minute refactor broke it.
2026-04-28 15:58:21 +02:00
Alexander "FireFox" Ongandocornut 865a6dfa59 InputScalar: fixed not parsing user input when the display format is configured not to show the scalar value. (#9385)
Useful e.g. for displaying "mixed" inputs, where a single field might represent multiple different values.
2026-04-28 15:25:12 +02:00
Vladandocornut dee9b15bbe Backends: Metal: add sampler states and DrawCallback_SetSamplerLinear / DrawCallback_SetSamplerNearest callbacks. (#9381, #9371, #9378) 2026-04-28 15:09:23 +02:00
ocornut d1a8995634 MultiSelect: Box-Select + Tables: fixed when using SpanAllColumns paths. (#9383, #7994)
Amend ac88294 + d7b40ab
2026-04-28 14:58:47 +02:00
ocornut ab36fbaf48 Drag and Drop, Style: added ImGuiStyleVar_DragDropTargetRounding. (#9056)
+ readded rounding arg to RenderDragDropTargetRectEx().
2026-04-27 18:23:56 +02:00
ocornut e3033c3975 Examples: moving example_win32_directx11 on top of the .sln makes it the default selected project. 2026-04-24 17:38:51 +02:00
ocornut 10c378cdfc InputInt, InputFloat, InputScalar: reinstated and fixed ImGuiInputTextFlags_EnterReturnsTrue. (#8665, #9299, #8065, #3946, #6284, #9117) 2026-04-24 15:15:19 +02:00
ocornut db23a78c60 Internals: store ImGuiItemStatusFlags_EditedInternal bypassing ImGuiItemFlags_NoMarkEdited.
Convenient if the same signal is not passed via e.g. return value. (#8665, #9299, #8065, #3946, #6284, #9117)
2026-04-24 15:15:16 +02:00
ocornut bda49826cf Backends: OpenGL3: build fix for WebGL/ES2/Emscripten. (#9378)
Amend 6b05f71 which was incorrectly labelled.
2026-04-24 12:26:21 +02:00
MoonPowerandGitHub 1c2068e341 Merge branch 'ocornut:master' into cpu 2026-04-24 00:51:13 +02:00
ocornut 6b05f711fd Backends: WebGPU: build fix for WebGL/ES2. 2026-04-23 22:06:42 +02:00
ocornut 86ebb3bc11 Backends: removed samplers from ImGui_ImplDX10_RenderState, ImGui_ImplDX11_RenderState + fixed all Changelogs. (#9378) 2026-04-23 22:03:11 +02:00
ocornut 7e7f3adb80 Removed DrawCallback_SetSamplerCustom feature for now. Too unreliable to get working everywhere. (#9378) 2026-04-23 21:50:52 +02:00
ocornut dfe6f9ebca Backends: WebGPU: added SetSamplerLinear/Nearest draw callbacks. (#9378) 2026-04-23 21:50:50 +02:00
ocornut 37952fb3b8 Backends: Vulkan, SDLGPU3: remove samplers from RenderState. (#9378)
Revert part of ac261203a5, 9ee3d731b5 (#8866, #8163, #7998, #7988) since we have a better solution.
2026-04-23 21:50:47 +02:00
omarandocornut 0a811e8ea1 Backends: DX9, DX10, DX11, DX12, Allegro5, OpenGL2, OpenGL3, SDLRenderer2, SDLRenderer3, SDLGPU3, Vulkan: added standard draw callbacks when possible. (#9378) 2026-04-23 21:50:45 +02:00
ocornut 82f46a73f8 (Breaking) Moved ImDrawCallback_ResetRenderState -> ImGui::GetPlatformIO().DrawCallback_ResetRenderState + added room in ImGuiPlatformIO for more standard backend-agnostic draw callbacks. (#9378) 2026-04-23 21:50:41 +02:00
ocornut a6a16cf8a2 Backends: WebGPU: protect better against zero tex id. 2026-04-23 20:50:34 +02:00
ocornut e887098740 Backends: WebGPU: always use SPIR-V shader on WGVK, as it cannot be detected at runtime. (#9316, #9246, #9257) 2026-04-23 19:42:29 +02:00
ocornut f934719fbf TabBar: comments about ImGuiTabBarFlags_FittingPolicyMixed and TabMinWidthShrink. (#9376, #3421, #8800) 2026-04-23 18:31:53 +02:00
ocornut ce3fe4078a Backends: WGPU: fixed build.
Incorrect line from a WIP branch slipped in ac06ad7
2026-04-23 17:31:14 +02:00
ocornut f2f843c113 Fixed some extremely zealous warnings (GCC -Wconversion, -Wdouble-promotion)
(amend a1e0552)
2026-04-23 17:23:43 +02:00
ocornut adc0027912 Backends: Vulkan: remove unused artefacts (mistakenly commited in 0453ae9). 2026-04-23 16:08:11 +02:00
ocornut ac06ad7b48 ImDrawList: made AddCallback() user data default to NULL + minor amends/comments. 2026-04-23 15:58:44 +02:00
ocornut 4739af2d51 Update VS toolset in all .vcxproj from VS2015 (v140) to VS2017 (v141).
It supports vcpkg.
2026-04-23 15:58:04 +02:00
ocornut b065713cec Backends: OpenGL2/3, SDLRenderer2/3, DirectX9, Metal: moved Init/Shutdown code lower in the file.
Allows to point to local functions without forward declaring them.
2026-04-23 15:53:28 +02:00
ocornut fb308c14ce Remove noise from 0453ae9 + amend comments. (#914) 2026-04-22 14:50:15 +02:00
ocornut ac261203a5 (Breaking) Backends: Vulkan: redesigned to use separate ImageView + Sampler instead of Combined Image Sampler. (fixes, amends) (#914) 2026-04-22 14:43:44 +02:00
yaz0randocornut 0453ae96e8 (Breaking) Backends: Vulkan: redesigned to use separate ImageView + Sampler instead of Combined Image Sampler. (WIP) (#914) 2026-04-22 14:43:44 +02:00
ocornut a5fd597be3 Backends: Vulkan: minor changes. 2026-04-22 14:23:42 +02:00
ocornut 382b99c334 PlotHistogram: add comments. (#9372) 2026-04-21 22:32:01 +02:00
ocornut 2d131ef5b7 Backends: Vulkan: renaming and moving code around to reduce diff in upcoming change. Should be no-op. 2026-04-21 22:22:06 +02:00
ocornut a1e05521e9 Backends: GLFW: added a Win32-specific implementation of ImGui_ImplGlfw_GetContentScaleXXXX functions for legacy GLFW 3.2. (#9003)
Since we ship GLFW 3.2 binaries for Windows this makes our examples a little better behaving by default.
Ideally we'd use ImGui_ImplWin32_GetDpiScaleForHwnd() and ImGui_ImplWin32_GetDpiScaleForMonitor() but they are too much code to copy.
2026-04-21 17:24:41 +02:00
ocornut d7b40ab9a9 MultiSelect: Box-Select + Tables: Amend ac88294. fix usage of box-selection columns with items straying out of columns. (#7994, #2221) 2026-04-20 11:46:36 +02:00
ocornut ac88294b4a MultiSelect: Box-Select +Tables: fix usage of box-selection columns with items straying out of columns. (#7994, #2221)
Use 00d3f9295e.
+ Assets Browser toggle to enable ScrollX.
2026-04-20 11:12:43 +02:00
ocornut ea1c04f7ab Multi-Select + Tables: fixed an issue which could lead to an extra vertical offset in the Header row. (#8250, #7994)
Because BeginMultiSelect() does `ms->ScopeRectMin = window->DC.CursorMaxPos = window->DC.CursorPos` at a time where CursorPos is already past MaxPos.y because of ItemSpacing.y. Accumulate spacing.
2026-04-17 19:23:10 +02:00
ocornut cdb046ac3f Demo: Assets Browser: fixed not submitting anything after a SetCursorScreenPos() call when no items. Would not manifest because BeginMultiSelect() altered CursorMaxPos. (#5548)
cc: 2819ab32f8, edcd5b113e
2026-04-17 19:23:04 +02:00
ocornut 97939e6837 Multi-Select: Box-Select: fixes for using accross nested child windows. (#8364)
- IsFocused scan nav focus route.
- When covering multiple windows, draw in front most ones (grabbed FindFrontMostVisibleChildWindow() from docking branch).
2026-04-17 16:36:09 +02:00
ocornut c91b03060d Multi-Select: Box-Select: improve dirty unclip rectangle calculation + use in ImGuiMultiSelectFlags_BoxSelect1d mode when needed (e.g. wheel scrolling up). (#7994, #8250, #7821, #7850, #7970) 2026-04-17 14:38:12 +02:00
ocornut a2eb6d99ed MultiSelect: Box-Select +Tables: revert 4d00bf8ad which seems unneeded since enforce table layout in BeginMultiSelect(). (#7970, #7821). 2026-04-16 23:59:44 +02:00
ocornut a2916923a1 MultiSelect: Box-Select + Clipper: extend UnclipRect by ItemSpacing. (#7994, #8250, #7821, #7850, #7970)
Amend 1ac469b50f
2026-04-16 23:37:46 +02:00
ocornut 2cbdb7a337 TextLink(), BeginCombo(): fixed two remainig instances of needlessly scanning for ##. 2026-04-16 16:47:13 +02:00
ocornut d4783bd553 Added missing Test Engine hooks for PlotXXX(), VSliderXXX(), TableHeader(). 2026-04-16 16:39:07 +02:00
ocornut ce855cada2 Tables, Multi-Select: Fixed an issue using Multi-Select within a Table causing column width measurement to be invalid when trailing column contents is not submitted in the last row. (#9341, #8250) 2026-04-16 15:21:56 +02:00
ocornut 39e7bf5a08 Separator(): enforce a minimum border size if style.SeparatorSize is 0.0f. (#9369) 2026-04-16 11:32:40 +02:00
ocornut 0e318a5182 Backends: SDL2: Made ImGui_ImplSDL2_GetContentScaleXXX helpers return a minimum of 1.0f, as some Linux setup seems to report <1.0f value and this breaks scaling border size. (#9369) 2026-04-16 11:32:07 +02:00
ocornut 19753a30d8 Multi-Select: Box-Select+Tables: fixed Column return value when UnClipRect is active. (#7994, #8250)
Amend 6ce4b44 + bbd0af7. This probably should be redesigned to be more generic, e.g. move UnclipRect concept outside of Boxselect.
2026-04-15 15:08:49 +02:00
ocornut 6fb74f38af Demo: Assets Browser: make default icon size font dependant. 2026-04-15 14:26:50 +02:00
Andy Grundmanandocornut 4b80d409e7 Backends: Metal: use a dedicated bufferCacheLock to avoid crashing when bufferCache is replaced by a new object while being used for synchronize(). (#9367)
This also removes the dispatch onto main when adding the finished buffers back into the cache. This operation should be fine to run on any thread as long as it's inside the sync block.
2026-04-14 17:14:08 +02:00
ocornut ed4dd679f1 Fixed vertical scrollbar top coordinates when using thick borders on windows with no title bar and no menu bar. (#9366) 2026-04-14 16:39:08 +02:00
ocornut 3cd8683061 Fonts: assert when using MergeMode with an explicit size over a target font with an implicit size, as scale factor are likely erroneous. (#9361) 2026-04-13 16:45:18 +02:00
ocornut bbd0af7256 Multi-Select: Box-Select+Tables: fixed using BeginMultiSelect() before table layout is locked. (#8250) 2026-04-13 16:19:45 +02:00
ocornut f83a378d62 TabBar: changed edge's TabItem ClipRect to not pass an inverted PushClipRect().
While not currently a problem, it would be if ImRect::Overlaps() is changed to use <= instead of < (cc: #3976 which deal with Contains but sort of similar topic).
Changing ImDrawList::PushClipRect()'s intersect_with_current_clip_rect path to use ClipRectFull() would also fix this, but it may ambiguous there which behavior would be correct.
Amend 1ec464eb9.
2026-04-13 14:11:19 +02:00
Flyingheadandocornut 84b4b35902 Fonts: rework UpdateCurrentFontSize() check. (#9364)
Consistent with line above.
2026-04-13 10:06:59 +02:00
MoonPowerandGitHub 869c16e6be Merge branch 'ocornut:master' into cpu 2026-04-11 23:59:04 +02:00
ocornut 2dc64f99bc Minor optimization: reduce redudant label scanning in common widgets.
Missing stuff from 11de9df.
The 6 remaining use of CalcTextSize(...,true) don't need this.
2026-04-10 18:37:08 +02:00
ocornut 5da7eb0a84 DrawList: remove/strip old FixRectCornerFlags() code.
Amend 44a6b493e
2026-04-10 17:42:13 +02:00
ocornut f678c91617 Multi-Select: disable MultiSelectAddSetRange() attempt at merging consecutive requests submitted from box-selection.
Essentially reverts 79b77d91c, f904a6646c which did the initial span merging.
Amend and disable change done for f08b33f.
2026-04-09 23:13:15 +02:00
ocornut 6ce4b44547 Mulit-Select: Box-Select: fixed an issue using in a table while relying on the TableNextColumn() return value to perform coarse clipping. (#7994)
This is presumably not sufficient as MultiSelectAddSetRange() is also deficient there.
2026-04-09 23:13:12 +02:00
ocornut f08b33fd0c Multi-Select: Box-Select: fixed an issue where items out of horizontal view would sometimes lead to incorrect merging of sequential selection requests. (#7994, #1861, #6518)
SetNextItemSelectionUserData() could use g.NextItemData.SelectionUserData if we could guarantee if would be valid when nesting multi-select blocks.
But it doesn't make much of a difference as whole ImGuiMultiSelectTempData fits in 2 cache lines.
2026-04-09 22:16:47 +02:00
ocornut b444694b3d Multi-Select: Box-Select: fixed an issue using ImGuiMultiSelectFlags_BoxSelect2d mode, where items out of view wouldn't be properly selected. (#7994, #1861, #6518)
Because BoxSelectRectPrev and BoxSelectRectCurr were clamped to scope boundaries, dragging mouse outside of the scope would usually keep one axis unchanged.
Amend 15391762dd
2026-04-09 21:40:29 +02:00
ocornut 24677c561e Multi-Select: Box-Select: add compile-time debug options. (#7994, #1861, #6518) 2026-04-09 21:40:13 +02:00
ocornut 01a4ad3a50 Docs: update legacy TODO list. 2026-04-09 15:01:40 +02:00
ocornut f4ed421a88 InputText: CharFilter callback event sets CursorPos/SelectionStart/SelectionEnd. (#816) 2026-04-09 14:54:09 +02:00
ocornut 11de9df44c Minor optimization: reduce redudant label scanning in common widgets. 2026-04-09 14:25:34 +02:00
ocornut c2565fe642 Update ignore list
Add .claude
2026-04-09 13:59:45 +02:00
ocornut 95bd1577d6 Windows: Child windows with only ImGuiChildFlags_AutoResizeY flag keep using the proportional default ItemWidth. (#9355)
+ Removed Tooltip flag check, it's from 8c4fcf1359 (!) where AlwaysAutoReszie was added after Tooltip. Nowadays Tooltips sets ImGuiChildFlags_AlwaysAutoResize.
2026-04-09 13:11:16 +02:00
ocornut dd17495a42 Detect and report error when calling End() instead of EndPopup() on a popup. (#9351) 2026-04-08 21:40:05 +02:00
ocornut 1870a779e1 Windows: fixed a single-axis auto-resizing feedback loop issue with nested containers and varying scrollbar visibility. (#9352) 2026-04-08 21:26:16 +02:00
ocornut a9bd173d89 Windows: shallow renames (should be no-op). 2026-04-08 20:40:35 +02:00
ocornut bccec3eabc Tables: fixed IdealMaxPos.y/CursorMaxPos.y computation being wrong when vertically scrolling. (#9352, #7651)
See ""table_reported_size_outer" test amends (0f9d1e02b0).
2026-04-08 20:01:00 +02:00
ocornut d946c6932b InputText: fixed a crash toggling ReadOnly flag while active. (#9354) 2026-04-08 15:56:59 +02:00
ocornut 4d38508c6b Tables: fixed an issue reporting ideal size to parent window/container when both scrollbars are visible but only one of ScrollX/ScrollY was explicitly requested. (#9352, #7651)
Since ScrollX de-facto also enables ScrollY we can't gate accounting for ScrollbarSizes.x based on explicit ScrollY.
Amend a31aa683f
2026-04-08 15:07:11 +02:00
ocornut c0e6580b62 Reword code in CalcWindowAutoFitSize() to match the order used in size_desired calculation.
Should be no-op. Toward (#9352)
2026-04-08 14:31:11 +02:00
ocornut 6985925244 Clipper, Tables: Improved error reporting when misusing the clipper inside a table + made the assert a better recoverable error. (#9350)
Amend 20e040c8
2026-04-07 19:19:40 +02:00
ocornut 7cb0baeb77 imgui_freetype: add FreeType headers & compiled version number in the 'About Dear ImGui' user facing string. 2026-04-07 17:18:16 +02:00
hunamandocornut 49df3116bc Backends: Metal: avoid redundant vertex buffer bind in SetupRenderState. (#9343) 2026-04-03 19:14:23 +02:00
ocornut 03a0b00a34 InputTextMultiline: fixed an issue processing deactivation logic when an active multi-line edit is clipped due to being out of view. 2026-04-03 16:25:57 +02:00
ocornut 4a61188322 Version 1.92.8 WIP 2026-04-03 16:15:46 +02:00
ocornut dac07199cf Version 1.92.7 2026-04-02 19:22:53 +02:00
ocornut 45866bea47 Tables: fixes not releasing ReorderColumn caused by 38f5e5a. Which could break clicking on header to sort. (#9312) 2026-04-02 18:59:23 +02:00
ocornut 65ebca8157 Fonts: fixed an issue introduced in 1.92.6 where style.FontBaseSize would be cleared during the first frame if no fonts was explicitely added before.
Amend 3aba95060e
2026-04-02 18:35:24 +02:00
ocornut 9e9fdc97bb InputText: rename Edited->EditedThisFrame, add EditedBefore. (#701) + Comments + About box clipboard blurb include a comment. 2026-04-02 15:48:49 +02:00
moonpower e7ca13b714 Fix SDL surface backend texture refresh 2026-04-02 14:03:42 +02:00
ocornut fc5e421cb9 Tables: columns freeze doesn't enforce a particular order + rework changelog for clarity. (#9312) 2026-04-02 13:59:41 +02:00
ocornut b7bdea3215 Tables: fixed FrozenColumns issue introduced by 505bc9a.
cc #9312
2026-04-01 21:35:55 +02:00
ocornut bf10275aa7 Tables: allow reordering columns by dragging them in the context menu. (#9312) 2026-04-01 20:08:34 +02:00
ocornut 0867f6113a Tables: reorder allowed check sweep through columns, checks _NoOrder barrier, and reworked to be easy to use from context menu. (#9312)
The sweep doesn't make a difference for reordering with headers as reordering is currently done 1 by 1. But menu ordering will change that.
2026-04-01 20:08:31 +02:00
ocornut 836278db6c Tables: context menu now present columns in display order. (#9312) 2026-04-01 20:08:29 +02:00
ocornut 505bc9a312 Tables: clarify FrozenColumns order to be in order space not in visible space.
+ Removed LeftMostUnfrozenOrder + Angled Headers comments.
While not strictly part of #9312, presenting a suitable reordering menu was made difficult by the old behavior.
2026-04-01 20:08:26 +02:00
ocornut 07acc8bc87 Tables: Angled Headers: angled section for column being reordered via the regular headers stay highlighted during reordering.
Easily possible thanks to 6603cde.
2026-04-01 20:05:34 +02:00
ocornut 6603cdef98 Tables: fixed dragging a header to reorder outside of visible bounds (due to horizontal scrolling) from losing active id. 2026-04-01 20:03:30 +02:00
ocornut 9df0d38d45 Tables: amend 2ac782f bad WIP merge broken reorder. (#9312) 2026-04-01 18:30:29 +02:00
ocornut 2ac782fbed Revert "Tables: rework TableSetColumnDisplayOrder() to take src_order. (#9312)"
This reverts commit 7be8076e9b.
Not a good idea as it's easier to reason and persist column index.
+ clear ReorderColumnDstOrder properly in reinit.
2026-04-01 17:57:13 +02:00
ocornut 9fedea83f0 Tables: TableQueueSetColumnDisplayOrder() enforce handling ImGuiTableColumnFlags_NoReorder as advertised: can't reorder through them. (#9312)
This would never using interactive reordering as reordering from headers was done on a 1 by 1 basis which was already covered in the test.
Hard to tell what's a sensible design for this tbh. Expecting _NoOrder columns to be sequential and leading/trailing anyhow.
2026-04-01 16:03:32 +02:00
ocornut ed4cffece7 Tables: store LeftMostUnfrozenOrder and amend TableQueueSetColumnDisplayOrder(). (#9312) 2026-04-01 16:02:41 +02:00
ocornut 7be8076e9b Tables: rework TableSetColumnDisplayOrder() to take src_order. (#9312) 2026-04-01 16:02:36 +02:00
ocornut 587c4cb87b Tables: rename locals in TableDrawDefaultContextMenu() to reduce confusion. 2026-04-01 15:25:59 +02:00
ocornut aab17456a7 Tables: mark setting as dirty when forcing reordering.
Otherwise the manufactured case of reloading a session that previously had e.g. a slider to adjust freeze count, resetting to 1 on new session, would keep showing you reordering items until another thing triggers marking dirty.
2026-04-01 15:25:57 +02:00
MoonPowerandGitHub ff2f9ae4e6 Merge branch 'ocornut:master' into cpu 2026-03-31 23:55:05 +02:00
Daniel K. O. (dkosmari)andocornut 3c78afbbbb Added missing ImVec2/ImVec4 operators. (#9339, #8510, #8258) 2026-03-31 21:44:09 +02:00
JoshBot-Debugandocornut b003a85143 Backends: Vulkan: use a single call to vkCmdPushConstants(). (#9183, #9327) 2026-03-31 16:07:46 +02:00
ocornut 689f837afa IO: added comments near ImGuiConfigFlags to refer to other fields. (#3379) 2026-03-30 13:04:38 +02:00
ocornut 97075fae4b Clipper: always pulls current context on ImGuiListClipper::Begin(). (#9324, #5856)
Marked Ctx as internal in the comments.
2026-03-30 12:53:30 +02:00
MoonPowerandGitHub 8fb4746c91 Merge branch 'ocornut:master' into cpu 2026-03-30 12:28:11 +02:00
thedmdandocornut bd3c925680 DrawList: PathArcTo(): fixed erroneous segment count for small arcs on large circles. (#9331, #9313) 2026-03-30 12:04:22 +02:00
ocornut b62cf3894b Inputs: fixed an issue using SetKeyOwner() with ImGuiInputFlags_LockThisFrame or ImGuiInputFlags_LockUntilRelease on ImGuiMod values. (#9323) 2026-03-25 22:00:14 +01:00
ocornut e9eb04ea95 Internals: TempInputText: added callback/user_data parameters and made end of signature match InputText(). (#2718) 2026-03-25 17:46:04 +01:00
ocornut ed2e5dd0f0 Examples+WebGPU: added support for WGVK in cmakefiles. (#9316, #9246, #9257) 2026-03-25 16:16:15 +01:00
ocornut 59183cf782 Backends, Examples: WebGPU: added support for WGVK. Remaining amends. (#9316, #9246, #9257) 2026-03-25 15:31:39 +01:00
r-lyehandocornut 59780020f6 Backends, Examples: WebGPU: added support for WGVK. (#9316, #9246, #9257)
Squashed: minified SPIRV binaries by stripping strings + emitting in binary_to_compressed_c.
2026-03-25 15:31:35 +01:00
ocornut 0b82487fed TempInputText: amends. Rename ImGuiInputTextFlags_MergedItem to ImGuiInputTextFlags_TempInput for explicitness. (#2718) 2026-03-25 14:29:54 +01:00
ocornut 51f590a2a8 Backends: GLFW: mouse cursor is properly restored if changed by user app/code while using glfwSetInputMode(..., GLFW_CURSOR_DISABLED) or ImGuiConfigFlags_NoMouseCursorChange. (#9322)
Amend 9a4fd69f6
2026-03-25 14:17:29 +01:00
ocornut 6c754ed2cb TempInputText, InputText: enforce making active via ImGuiInputTextFlags_MergedItem. Restore cursor as Rect is provided + comments. (#2718, #6690) 2026-03-25 11:36:40 +01:00
ocornut 79411a0405 Backends, Examples: WebGPU: fixed warnings + scale initial surface height for native. 2026-03-23 16:21:50 +01:00
ocornut 6b1776a7d2 Tables: context menu can be open using navigation Shift+F10 etc. (#8803, #9270) 2026-03-23 15:37:56 +01:00
ocornut 38f5e5a0b8 Tables: rework column reordering code. (#9312)
- Move more logic into TableQueueSetColumnDisplayOrder() so that it may be called from different locations.
- Use to checking if both columns are on same size of the frozen barrier slightly changed to avoid reordering hidden column (with caveat of ill-defined design for what's "right").
2026-03-23 15:14:58 +01:00
ocornut 697b6886e3 Docs: update FAQ about label/ID system. (#9318) 2026-03-23 14:13:36 +01:00
ocornut 8314fc3e5a Menus: shallow tweaks. 2026-03-20 20:47:07 +01:00
ocornut 50b488765f ButtonBehavior, Selectable: made low-level ImGuiButtonFlags_PressedOnRelease not explicitely avoid taking current active id. ImGuiButtonFlags_NoHoldingActiveId may be used for that.
Ditto for ImGuiSelectableFlags_SelectOnRelease, ImGuiSelectableFlags_NoHoldingActiveId. All internals.
Toward #9312
2026-03-20 20:15:17 +01:00
ocornut 4af77622d9 Scrollbar: Fixed an issue which could lead initial click to move the current scroll by a pixel. 2026-03-20 16:14:17 +01:00
ocornut 2315b9f33d InputTextMultiline: fixed an issue where edit buffer wouldn't be reapplied to back buffer on the IsItemDeactivatedAfterEdit() frame. (#9308, #8915, #8273) 2026-03-20 15:48:14 +01:00
ocornut 04dfcd838b InputTextMultiline: fixed losing revert value when activating scrollbar. (toward #9308) 2026-03-20 15:48:14 +01:00
ocornut 2d957152e4 InputTextMultiline: avoid going through reactivation path and InputTextDeactivateHook() when activating scrollbar. (#9308) 2026-03-20 15:37:56 +01:00
ocornut 325563a982 InputTextMultiline: InputTextMultiline: fixed an issue calculating lines count when active.
Amend 4252275
2026-03-20 15:17:07 +01:00
Pascal ThometandGitHub 763db046fa Docs: fixed imgui_manual -> imgui_explorer link. (#9315) 2026-03-20 12:40:32 +01:00
ocornut 3a26b640b2 Drag and Drop: make SetDragDropPayload() memcpy size match our buffer. 2026-03-20 11:50:05 +01:00
ocornut 386ce49c58 Backends: DirectX9: fixed build typo in 0500e54. 2026-03-19 18:17:35 +01:00
ocornut b2c3e37d55 Multi-Select: fix/amend 9700846. . (#9307, #1861) 2026-03-19 16:58:14 +01:00
ocornut 9700846bb3 MultiSelect: added ImGuiMultiSelectFlags_SelectOnClickAlways mode. Prevents Drag and Drop of multiple items but allows BoxSelect to always reselect even when clicking inside a selecttion. (#9307, #1861) 2026-03-19 16:39:50 +01:00
ocornut 0b4967992a MultiSelect: Box-Select: removed now seemingly unnecessary 'selected==false' check, which will also prevent implementation of ImGuiMultiSelectFlags_SelectOnClickAlways. (#9307)
We enter into the block either though navigation, and then the Mouse check fails, either through mouse, and then Selected==false is tested above.
Amend f904a6646.
2026-03-19 16:29:03 +01:00
ocornut 20d8bcb600 (Breaking) MultiSelect: renamed ImGuiMultiSelectFlags_SelectOnClick to ImGuiMultiSelectFlags_SelectOnAuto. (#1861, #6518) 2026-03-19 16:04:04 +01:00
ocornut 358d3912c9 Backends: SDLRenderer2/3: fixed build, typo in 0500e54. 2026-03-19 12:34:11 +01:00
ocornut 4d1ba782ee Revert changing default value of ImTextureID_Invalid to -1. Back to 0. (#9295, #9310, #9293, #8745, #8465, #7090)
Reverts 0db591935f
2026-03-19 11:54:42 +01:00
ocornut 0500e546b5 Backends: DX9, Metal, SDLRenderer2/3: fixed more assumptions that ImTextureID_Invald == 0 + Amend Changelogs. (#9310, #9293) 2026-03-19 11:47:01 +01:00
Starmanandocornut 7fc3092870 Backends: SDLGPU3: Prevent DestroyTexture from deleting invalid textures if ImTextureID_Invalid != 0. (#9310, #9293)
Amend 0db5919
2026-03-19 11:31:48 +01:00
ocornut b724f940d6 InputText: fixed selection highlight Y1 offset being very slightly off (since 1.92.3). (#9311)
Fixes 1e52e7b90c
2026-03-19 11:20:00 +01:00
ocornut 4252275c64 InputTextMultiline: fixed an issue calculating lines count when inactive, no word-wrap, and ending with a \n.
Amend 1e52e7b90c (#3237, #952, #1062, #7363)
2026-03-18 20:12:14 +01:00
ocornut 6abe65aac6 InputText: amend fix to avoid PVS-Studio sort of rightful false positive. Amend f4c2f50. (#9174)
Checking for state != NULL in the two othr functions where state is already deferenced was misleading.
imgui_widgets.cpp:4496:1: error: V595 The 'state' pointer was utilized before it was verified against nullptr. Check lines: 4496, 4500.
imgui_widgets.cpp:5273:1: error: V595 The 'state' pointer was utilized before it was verified against nullptr. Check lines: 5273, 5289.
2026-03-18 18:57:02 +01:00
ocornut f4c2f50896 InputText: fixed a crash when handling ImGuiInputTextFlags_CallbackResize. (#9174)
Fix/amend cb3b7ff.
2026-03-18 18:37:04 +01:00
ocornut 27cacb0e30 Fixed GetForegroundDrawList()/GetBackgroundDrawList() per-viewport buffers not being collected/ (#9303) 2026-03-18 16:48:18 +01:00
ocornut 709be8c495 Discard/GC of ImDrawList buffers for unused windows favor restoring them to ~Size*1.05 instead of Capacity when awakening again. (#9303)
+ made "GC now" button process even active windows.
2026-03-18 15:34:12 +01:00
MoonPowerandGitHub f46085238e Merge branch 'ocornut:master' into cpu 2026-03-17 01:26:19 +01:00
ocornut 994ca12b29 Fixed warning. (Amend 1677236) 2026-03-16 18:51:38 +01:00
ocornut 6464276b62 InputText: cleanup/rework old comments + remove unnecessary indent in callback and main block setting apply_new_text.
Amend 00f12b9a0, 3349296370 etc.
2026-03-16 18:42:28 +01:00
ocornut 16772365e2 Moved ImGuiButtonFlags_AllowOverlap from imgui_internal.h to imgui.h + standardize comments. 2026-03-16 18:42:22 +01:00
ocornut 8957b3df03 InputScalar: minor rework to facilitate incoming change. Intended to have no side-effects. 2026-03-16 11:41:01 +01:00
MoonPowerandGitHub 1e15739da4 Merge branch 'ocornut:master' into cpu 2026-03-15 12:34:13 +01:00
moonpower 31c2e522f5 cpu start 2026-03-15 12:33:32 +01:00
Yan Pujanteandocornut 4a2e3cce69 Examples: SDL2+WebGPU: fixes hi-dpi handling. (#9300) 2026-03-13 17:07:47 +01:00
ocornut fd752d8357 InputText: Fixed a glitch when using ImGuiInputTextFlags_ElideLeft where the local x offset would be incorrect during the deactivation frame. (#9298) 2026-03-13 16:32:39 +01:00
MoonPowerandGitHub af86719c5a Merge branch 'ocornut:master' into sdl_cpu 2026-03-13 15:51:47 +01:00
moonpower 10e6755ad5 Merge branch 'sdl_cpu' of https://github.com/momo-AUX1/imgui into sdl_cpu 2026-03-13 15:49:52 +01:00
moonpower dc4a1d294d Add Emscripten support for SDL2 and SDL3 surface examples 2026-03-13 15:49:21 +01:00
ocornut d02c645e38 Nav: short Gamepad Activation press on InputText() always activate with Text Input mode. 2026-03-13 15:07:46 +01:00
ocornut 49ee151ed6 Nav: pressing gamepad north button activates context menus.
+ update ShowUserGuide().
2026-03-13 15:07:46 +01:00
ocornut b76ab6232d Nav: changed Gamepad mapping for "Activate with Text Input" action from FaceUp press to FaceDown long press. (#8803, #787) 2026-03-13 15:07:46 +01:00
MoonPowerandGitHub 413c8817d4 Merge branch 'ocornut:master' into sdl_cpu 2026-03-13 14:50:16 +01:00
moonpower 6575c02cac Remove VSync setting from SDL window surface initialization 2026-03-13 14:22:06 +01:00
moonpower 5ae4be2b5f Refactor SDL surface backend for improved quad rendering and performance
- Introduced a new structure ImGui_ImplSDLSurface3_Quad to represent quads.
- Added functions to detect quads and check for constant colors and linear UVs.
- Enhanced rendering functions to utilize quad detection for faster rendering paths.
- Updated the rendering logic in ImGui_ImplSDLSurface3_RenderDrawData to leverage the new quad rendering capabilities.
- Optimized Makefiles and build scripts to include optimization flags for better performance.
2026-03-13 14:19:04 +01:00
moonpower 2f2b8a1226 Add SDL3 surface backend for ImGui example
- Created imgui_impl_sdlsurface3.h and corresponding implementation file.
- Added Makefile for building the SDL3 surface example on Linux and macOS.
- Included README.md with build instructions for Windows, Linux, and macOS.
- Added build script for Windows (build_win32.bat) and Visual Studio project files.
- Implemented main application logic in main.cpp to demonstrate ImGui with SDL3 and surface rendering.
2026-03-13 13:23:18 +01:00
ocornut 6dbda97fee Backends: OpenGL2, OpenGL3, SDLRenderer3: replaced erroneous IM_ASSERT(tex->TexID == 0) calls. (#9295, #9293)
Amend/fix 0db5919 which revealed this.
2026-03-12 19:29:39 +01:00
ocornut 90743d3112 Nav: allow ImGuiKey_Menu or Shift + F10 to work on Begin()...BeginPopupContextItem() sequence aiming at title bar. (#8803, #9270) 2026-03-12 19:12:47 +01:00
ocornut 14a500a476 Nav: allow ImGuiKey_Menu or Shift + F10 to open context menus. Rework with polling in NavUpdate(). (#8803, #9270)
This might be a little less flexible but removes burden from the higher-frequency calls.
2026-03-12 18:52:42 +01:00
ocornut 6cc99a6e2b Nav: allow ImGuiKey_Menu or Shift + F10 to open context menus. Amends. (#8803, #9270)
This doesn't attempt to move the shortcut polling in NavUpdate() yet.
2026-03-12 18:30:05 +01:00
exelixandocornut a103826154 Nav: allow ImGuiKey_Menu or Shift + F10 to open context menus. (#8803, #9270) 2026-03-12 18:24:34 +01:00
ocornut 0db591935f Changed default ImTextureID_Invalid value to -1 instead of 0 +added comments. (#9293, #8745, #8465, #7090) 2026-03-12 14:44:15 +01:00
ocornut 1fbab15c0a Focus: fixed fallback "Debug" window temporarily taking focus and setting io.WantCaptureKeyboard for a frame. (#9243) 2026-03-11 21:59:44 +01:00
Michael Böhmeandocornut 7546f1eb16 Backends: Vulkan: ImGui_ImplVulkan_AddTexture() skips updating descriptor_set if failing to allocate. (#8677)
Reduce error surface to the check_vk_result() call.
2026-03-11 21:22:50 +01:00
omarandGitHub 5220c14f4b Docs: update readme. 2026-03-11 21:16:49 +01:00
ocornut 378cb85bf0 Amend missing Changelog entry. (#9115) 2026-03-11 21:02:46 +01:00
ocornut 5aa7d61139 InputText: reworked so that io.ConfigInputTextEnterKeepActive reactivate in order for e.g. IsItemDeactivatedAfterEdit() to work. Amends. (#9001, #9115)
Rework. Fixes dangling InputTextReactivateId in case of field being hidden on activation.
2026-03-11 20:33:18 +01:00
xtttandocornut 03a9946a14 InputText: reworked so that io.ConfigInputTextEnterKeepActive reactivate in order for e.g. IsItemDeactivatedAfterEdit() to work. (#9001, #9115) 2026-03-11 20:15:48 +01:00
109 changed files with 9865 additions and 1895 deletions
+7 -4
View File
@@ -1,5 +1,7 @@
## OSX artifacts
## Misc artifacts
.DS_Store
.claude
.vscode
## Dear ImGui artifacts
imgui.ini
@@ -47,17 +49,16 @@ examples/example_glfw_opengl3/web/*
examples/example_glfw_wgpu/web/*
examples/example_glfw_wgpu/external/*
examples/example_sdl2_opengl3/web/*
examples/example_sdl2_surface/web/*
examples/example_sdl2_wgpu/web/*
examples/example_sdl3_opengl3/web/*
examples/example_sdl3_surface/web/*
examples/example_sdl3_wgpu/web/*
## JetBrains IDE artifacts
.idea
cmake-build-*
## VS code artifacts
.vscode
## Unix executables from our example Makefiles
examples/example_apple_metal/example_apple_metal
examples/example_apple_opengl2/example_apple_opengl2
@@ -70,10 +71,12 @@ examples/example_null/example_null
examples/example_sdl2_metal/example_sdl2_metal
examples/example_sdl2_opengl2/example_sdl2_opengl2
examples/example_sdl2_opengl3/example_sdl2_opengl3
examples/example_sdl2_surface/example_sdl2_surface
examples/example_sdl2_sdlrenderer2/example_sdl2_sdlrenderer2
examples/example_sdl2_vulkan/example_sdl2_vulkan
examples/example_sdl3_metal/example_sdl3_metal
examples/example_sdl3_opengl3/example_sdl3_opengl3
examples/example_sdl3_surface/example_sdl3_surface
examples/example_sdl3_sdlgpu3/example_sdl3_sdlgpu3
examples/example_sdl3_sdlrenderer3/example_sdl3_sdlrenderer3
examples/example_sdl3_vulkan/example_sdl3_vulkan
+10 -4
View File
@@ -9,6 +9,7 @@
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// Missing features or Issues:
// [ ] Renderer: The renderer is suboptimal as we need to unindex our buffers and convert vertices manually.
// [ ] Renderer: Missing support for DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest callbacks: Allegro5 cannot enable/disable LINEAR bitmap flags after creation.
// [ ] Platform: Missing gamepad support.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
@@ -21,6 +22,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState (others cannot be supported by Allegro5). (#9378)
// 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.
@@ -136,7 +138,10 @@ static void ImGui_ImplAllegro5_SetupRenderState(ImDrawData* draw_data)
}
}
// Render function.
// Draw callbacks
static void ImGui_ImplAllegro5_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
// Render function
void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data)
{
// Avoid rendering when minimized
@@ -152,6 +157,7 @@ void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data)
// Backup Allegro state that will be modified
ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
ALLEGRO_TRANSFORM last_transform = *al_get_current_transform();
ALLEGRO_TRANSFORM last_projection_transform = *al_get_current_projection_transform();
int last_clip_x, last_clip_y, last_clip_w, last_clip_h;
@@ -208,8 +214,7 @@ void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data)
if (pcmd->UserCallback)
{
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
if (pcmd->UserCallback == ImGui_ImplAllegro5_DrawCallback_ResetRenderState)
ImGui_ImplAllegro5_SetupRenderState(draw_data);
else
pcmd->UserCallback(draw_list, pcmd);
@@ -486,11 +491,12 @@ bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display)
ImGui_ImplAllegro5_SetDisplay(display);
#if ALLEGRO_HAS_CLIPBOARD
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
#if ALLEGRO_HAS_CLIPBOARD
platform_io.Platform_SetClipboardTextFn = ImGui_ImplAllegro5_SetClipboardText;
platform_io.Platform_GetClipboardTextFn = ImGui_ImplAllegro5_GetClipboardText;
#endif
platform_io.DrawCallback_ResetRenderState = ImGui_ImplAllegro5_DrawCallback_ResetRenderState;
return true;
}
+1
View File
@@ -9,6 +9,7 @@
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// Missing features or Issues:
// [ ] Renderer: The renderer is suboptimal as we need to unindex our buffers and convert vertices manually.
// [ ] Renderer: Missing support for DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest callbacks: Allegro5 cannot enable/disable LINEAR bitmap flags after creation.
// [ ] Platform: Missing gamepad support.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
File diff suppressed because it is too large Load Diff
+81
View File
@@ -0,0 +1,81 @@
// dear imgui: CPU framebuffer renderer backend
// (supports caller-owned framebuffers/textures in generic packed pixel formats)
//
// Implemented features:
// [X] Renderer: User texture binding. Use 'ImGui_ImplCPU_Texture*' as texture identifier.
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices.
// [X] Renderer: Texture updates support for dynamic font atlas.
#pragma once
#ifndef IMGUI_DISABLE
#include "imgui.h"
struct ImGui_ImplCPU_PixelFormat;
typedef ImU32 (*ImGui_ImplCPU_MapColorFn)(const ImGui_ImplCPU_PixelFormat* format, unsigned char r, unsigned char g, unsigned char b, unsigned char a);
struct ImGui_ImplCPU_PixelFormat
{
int BitsPerPixel;
int BytesPerPixel;
ImU32 Rmask;
ImU32 Gmask;
ImU32 Bmask;
ImU32 Amask;
ImU8 Rshift;
ImU8 Gshift;
ImU8 Bshift;
ImU8 Ashift;
ImU8 Rloss;
ImU8 Gloss;
ImU8 Bloss;
ImU8 Aloss;
const ImU32* Palette; // Optional palette entries stored as IM_COL32(r, g, b, a).
int PaletteSize; // Number of palette entries, or 0 when Palette is unused.
ImGui_ImplCPU_MapColorFn MapColorFn; // Optional indexed/paletted mapping override. Return a raw packed pixel value.
};
enum ImGui_ImplCPU_BuiltinFormat
{
ImGui_ImplCPU_BuiltinFormat_RGBA8888 = 0,
ImGui_ImplCPU_BuiltinFormat_BGRA8888,
ImGui_ImplCPU_BuiltinFormat_ARGB8888,
ImGui_ImplCPU_BuiltinFormat_ABGR8888,
ImGui_ImplCPU_BuiltinFormat_RGB565,
ImGui_ImplCPU_BuiltinFormat_ARGB1555,
ImGui_ImplCPU_BuiltinFormat_RGBA4444,
ImGui_ImplCPU_BuiltinFormat_RGB888,
ImGui_ImplCPU_BuiltinFormat_BGR888,
ImGui_ImplCPU_BuiltinFormat_Alpha8,
ImGui_ImplCPU_BuiltinFormat_COUNT
};
struct ImGui_ImplCPU_Framebuffer
{
unsigned char* Pixels;
int Width;
int Height;
int Pitch;
const ImGui_ImplCPU_PixelFormat* Format; // Optional. Defaults to ImGui_ImplCPU_BuiltinFormat_RGBA8888.
};
struct ImGui_ImplCPU_Texture
{
const unsigned char* Pixels;
int Width;
int Height;
int Pitch;
const ImGui_ImplCPU_PixelFormat* Format; // Optional. Defaults to ImGui_ImplCPU_BuiltinFormat_RGBA8888.
};
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
IMGUI_IMPL_API const ImGui_ImplCPU_PixelFormat* ImGui_ImplCPU_GetBuiltinPixelFormat(ImGui_ImplCPU_BuiltinFormat format);
IMGUI_IMPL_API bool ImGui_ImplCPU_Init();
IMGUI_IMPL_API void ImGui_ImplCPU_Shutdown();
IMGUI_IMPL_API void ImGui_ImplCPU_NewFrame();
IMGUI_IMPL_API void ImGui_ImplCPU_RenderDrawData(ImDrawData* draw_data, ImGui_ImplCPU_Framebuffer* framebuffer);
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates
// by setting ImDrawData::Textures = nullptr to handle this manually.
IMGUI_IMPL_API void ImGui_ImplCPU_UpdateTexture(ImTextureData* tex);
#endif // #ifndef IMGUI_DISABLE
+13 -7
View File
@@ -16,7 +16,8 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2026-01-19: DirectX11: Added 'SamplerNearest' in ImGui_ImplDX11_RenderState. Renamed 'SamplerDefault' to 'SamplerLinear'.
// 2026-04-23: DirectX10: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. Obsoleting samplers from ImGui_ImplDX10_RenderState. (#9378)
// 2026-01-19: DirectX10: Added 'SamplerNearest' in ImGui_ImplDX10_RenderState. Renamed 'SamplerDefault' to 'SamplerLinear'.
// 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).
@@ -153,6 +154,11 @@ static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device*
device->RSSetState(bd->pRasterizerState);
}
// Draw callbacks
static void ImGui_ImplDX10_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
static void ImGui_ImplDX10_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData(); bd->pd3dDevice->PSSetSamplers(0, 1, &bd->pTexSamplerLinear); }
static void ImGui_ImplDX10_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData(); bd->pd3dDevice->PSSetSamplers(0, 1, &bd->pTexSamplerNearest); }
// Render function
void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
{
@@ -177,7 +183,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
bd->VertexBufferSize = draw_data->TotalVtxCount + 5000;
D3D10_BUFFER_DESC desc = {};
desc.Usage = D3D10_USAGE_DYNAMIC;
desc.ByteWidth = bd->VertexBufferSize * sizeof(ImDrawVert);
desc.ByteWidth = (UINT)bd->VertexBufferSize * sizeof(ImDrawVert);
desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
desc.MiscFlags = 0;
@@ -191,7 +197,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
bd->IndexBufferSize = draw_data->TotalIdxCount + 10000;
D3D10_BUFFER_DESC desc = {};
desc.Usage = D3D10_USAGE_DYNAMIC;
desc.ByteWidth = bd->IndexBufferSize * sizeof(ImDrawIdx);
desc.ByteWidth = (UINT)bd->IndexBufferSize * sizeof(ImDrawIdx);
desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
if (device->CreateBuffer(&desc, nullptr, &bd->pIB) < 0)
@@ -260,8 +266,6 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
ImGui_ImplDX10_RenderState render_state;
render_state.Device = bd->pd3dDevice;
render_state.SamplerLinear = bd->pTexSamplerLinear;
render_state.SamplerNearest = bd->pTexSamplerNearest;
render_state.VertexConstantBuffer = bd->pVertexConstantBuffer;
platform_io.Renderer_RenderState = &render_state;
@@ -279,8 +283,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
if (pcmd->UserCallback != nullptr)
{
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
if (pcmd->UserCallback == ImGui_ImplDX10_DrawCallback_ResetRenderState)
ImGui_ImplDX10_SetupRenderState(draw_data, device);
else
pcmd->UserCallback(draw_list, pcmd);
@@ -613,6 +616,9 @@ bool ImGui_ImplDX10_Init(ID3D10Device* device)
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Renderer_TextureMaxWidth = platform_io.Renderer_TextureMaxHeight = D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
platform_io.DrawCallback_ResetRenderState = ImGui_ImplDX10_DrawCallback_ResetRenderState;
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplDX10_DrawCallback_SetSamplerLinear;
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplDX10_DrawCallback_SetSamplerNearest;
// Get factory from device
IDXGIDevice* pDXGIDevice = nullptr;
+2 -2
View File
@@ -41,9 +41,9 @@ IMGUI_IMPL_API void ImGui_ImplDX10_UpdateTexture(ImTextureData* tex);
struct ImGui_ImplDX10_RenderState
{
ID3D10Device* Device;
ID3D10SamplerState* SamplerLinear;
ID3D10SamplerState* SamplerNearest;
ID3D10Buffer* VertexConstantBuffer;
//ID3D10SamplerState* SamplerLinear; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerLinear)
//ID3D10SamplerState* SamplerNearest; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerNearest)
};
#endif // #ifndef IMGUI_DISABLE
+15 -8
View File
@@ -17,6 +17,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2026-04-23: DirectX11: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. Obsoleting samplers from ImGui_ImplDX11_RenderState. (#9378)
// 2026-01-19: DirectX11: Added 'SamplerNearest' in ImGui_ImplDX11_RenderState. Renamed 'SamplerDefault' to 'SamplerLinear'.
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
// 2025-06-11: DirectX11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas.
@@ -85,6 +86,7 @@ struct ImGui_ImplDX11_Data
ID3D11DepthStencilState* pDepthStencilState;
int VertexBufferSize;
int IndexBufferSize;
ImGui_ImplDX11_RenderState* RenderState; // == (ImGui_ImplDX11_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState during rendering.
ImGui_ImplDX11_Data() { memset((void*)this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
};
@@ -159,6 +161,11 @@ static void ImGui_ImplDX11_SetupRenderState(const ImDrawData* draw_data, ID3D11D
device_ctx->RSSetState(bd->pRasterizerState);
}
// Draw callbacks
static void ImGui_ImplDX11_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
static void ImGui_ImplDX11_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); bd->RenderState->DeviceContext->PSSetSamplers(0, 1, &bd->pTexSamplerLinear); }
static void ImGui_ImplDX11_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); bd->RenderState->DeviceContext->PSSetSamplers(0, 1, &bd->pTexSamplerNearest); }
// Render function
void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
{
@@ -183,7 +190,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
bd->VertexBufferSize = draw_data->TotalVtxCount + 5000;
D3D11_BUFFER_DESC desc = {};
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.ByteWidth = bd->VertexBufferSize * sizeof(ImDrawVert);
desc.ByteWidth = (UINT)bd->VertexBufferSize * sizeof(ImDrawVert);
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0;
@@ -196,7 +203,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
bd->IndexBufferSize = draw_data->TotalIdxCount + 10000;
D3D11_BUFFER_DESC desc = {};
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.ByteWidth = bd->IndexBufferSize * sizeof(ImDrawIdx);
desc.ByteWidth = (UINT)bd->IndexBufferSize * sizeof(ImDrawIdx);
desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
if (bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pIB) < 0)
@@ -274,10 +281,8 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
ImGui_ImplDX11_RenderState render_state;
render_state.Device = bd->pd3dDevice;
render_state.DeviceContext = bd->pd3dDeviceContext;
render_state.SamplerLinear = bd->pTexSamplerLinear;
render_state.SamplerNearest = bd->pTexSamplerNearest;
render_state.VertexConstantBuffer = bd->pVertexConstantBuffer;
platform_io.Renderer_RenderState = &render_state;
platform_io.Renderer_RenderState = bd->RenderState = &render_state;
// Render command lists
// (Because we merged all buffers into a single one, we maintain our own offset into them)
@@ -293,8 +298,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
if (pcmd->UserCallback != nullptr)
{
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
if (pcmd->UserCallback == ImGui_ImplDX11_DrawCallback_ResetRenderState)
ImGui_ImplDX11_SetupRenderState(draw_data, device);
else
pcmd->UserCallback(draw_list, pcmd);
@@ -320,7 +324,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
global_idx_offset += draw_list->IdxBuffer.Size;
global_vtx_offset += draw_list->VtxBuffer.Size;
}
platform_io.Renderer_RenderState = nullptr;
platform_io.Renderer_RenderState = bd->RenderState = nullptr;
// Restore modified DX state
device->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
@@ -629,6 +633,9 @@ bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_co
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Renderer_TextureMaxWidth = platform_io.Renderer_TextureMaxHeight = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
platform_io.DrawCallback_ResetRenderState = ImGui_ImplDX11_DrawCallback_ResetRenderState;
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplDX11_DrawCallback_SetSamplerLinear;
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplDX11_DrawCallback_SetSamplerNearest;
// Get factory from device
IDXGIDevice* pDXGIDevice = nullptr;
+2 -2
View File
@@ -44,9 +44,9 @@ struct ImGui_ImplDX11_RenderState
{
ID3D11Device* Device;
ID3D11DeviceContext* DeviceContext;
ID3D11SamplerState* SamplerLinear;
ID3D11SamplerState* SamplerNearest;
ID3D11Buffer* VertexConstantBuffer;
//ID3D11SamplerState* SamplerLinear; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerLinear)
//ID3D11SamplerState* SamplerNearest; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerNearest)
};
#endif // #ifndef IMGUI_DISABLE
+21 -12
View File
@@ -20,6 +20,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
// 2025-10-11: DirectX12: Reuse texture upload buffer and grow it only when necessary. (#9002)
// 2025-09-29: DirectX12: Rework synchronization logic. (#8961)
// 2025-09-29: DirectX12: Enable swapchain tearing to eliminate viewports framerate throttling. (#8965)
@@ -91,6 +92,8 @@ struct ImGui_ImplDX12_Texture
struct ImGui_ImplDX12_Data
{
ImGui_ImplDX12_InitInfo InitInfo;
ImGui_ImplDX12_RenderState* RenderState;
IDXGIFactory5* pdxgiFactory;
ID3D12Device* pd3dDevice;
ID3D12RootSignature* pRootSignatureLinear;
@@ -142,19 +145,15 @@ struct VERTEX_CONSTANT_BUFFER_DX12
float mvp[4][4];
};
// FIXME-WIP: Allow user to forward declare those two, for until we come up with a backend agnostic API to do this. (#9173)
void ImGui_ImplDX12_SetupSamplerLinear(ID3D12GraphicsCommandList* command_list);
void ImGui_ImplDX12_SetupSamplerNearest(ID3D12GraphicsCommandList* command_list);
// Functions
void ImGui_ImplDX12_SetupSamplerLinear(ID3D12GraphicsCommandList* command_list)
static void ImGui_ImplDX12_SetupSamplerLinear(ID3D12GraphicsCommandList* command_list)
{
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
command_list->SetPipelineState(bd->pPipelineStateLinear);
command_list->SetGraphicsRootSignature(bd->pRootSignatureLinear);
}
void ImGui_ImplDX12_SetupSamplerNearest(ID3D12GraphicsCommandList* command_list)
static void ImGui_ImplDX12_SetupSamplerNearest(ID3D12GraphicsCommandList* command_list)
{
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
command_list->SetPipelineState(bd->pPipelineStateNearest);
@@ -200,7 +199,7 @@ static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12Graphic
command_list->IASetVertexBuffers(0, 1, &vbv);
D3D12_INDEX_BUFFER_VIEW ibv = {};
ibv.BufferLocation = fr->IndexBuffer->GetGPUVirtualAddress();
ibv.SizeInBytes = fr->IndexBufferSize * sizeof(ImDrawIdx);
ibv.SizeInBytes = (UINT)fr->IndexBufferSize * sizeof(ImDrawIdx);
ibv.Format = sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT;
command_list->IASetIndexBuffer(&ibv);
command_list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
@@ -220,6 +219,11 @@ static inline void SafeRelease(T*& res)
res = nullptr;
}
// Draw callbacks
static void ImGui_ImplDX12_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
static void ImGui_ImplDX12_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); ImGui_ImplDX12_SetupSamplerLinear(bd->RenderState->CommandList); }
static void ImGui_ImplDX12_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); ImGui_ImplDX12_SetupSamplerNearest(bd->RenderState->CommandList); }
// Render function
void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandList* command_list)
{
@@ -317,7 +321,7 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
ImGui_ImplDX12_RenderState render_state;
render_state.Device = bd->pd3dDevice;
render_state.CommandList = command_list;
platform_io.Renderer_RenderState = &render_state;
platform_io.Renderer_RenderState = bd->RenderState = &render_state;
// Render command lists
// (Because we merged all buffers into a single one, we maintain our own offset into them)
@@ -334,7 +338,7 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
{
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
if (pcmd->UserCallback == ImGui_ImplDX12_DrawCallback_ResetRenderState)
ImGui_ImplDX12_SetupRenderState(draw_data, command_list, fr);
else
pcmd->UserCallback(draw_list, pcmd);
@@ -361,7 +365,7 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
global_idx_offset += draw_list->IdxBuffer.Size;
global_vtx_offset += draw_list->VtxBuffer.Size;
}
platform_io.Renderer_RenderState = nullptr;
platform_io.Renderer_RenderState = bd->RenderState = nullptr;
}
static void ImGui_ImplDX12_DestroyTexture(ImTextureData* tex)
@@ -664,7 +668,7 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
bd->pd3dDevice->CreateRootSignature(0, blob->GetBufferPointer(), blob->GetBufferSize(), IID_PPV_ARGS(&bd->pRootSignatureLinear));
blob->Release();
// Root Signature for ImDrawCallback_SetSamplerNearest
// Nearest sampler
staticSampler[0].Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
if (D3D12SerializeRootSignatureFn(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &blob, nullptr) != S_OK)
return false;
@@ -813,7 +817,6 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
return false;
}
// Pipeline State for ImDrawCallback_SetSamplerNearest
psoDesc.pRootSignature = bd->pRootSignatureNearest;
result_pipeline_state = bd->pd3dDevice->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&bd->pPipelineStateNearest));
@@ -927,6 +930,11 @@ bool ImGui_ImplDX12_Init(ImGui_ImplDX12_InitInfo* init_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.
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.DrawCallback_ResetRenderState = ImGui_ImplDX12_DrawCallback_ResetRenderState;
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplDX12_DrawCallback_SetSamplerLinear;
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplDX12_DrawCallback_SetSamplerNearest;
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
if (init_info->SrvDescriptorAllocFn == nullptr)
ImGui_ImplDX12_InitLegacySingleDescriptorMode(init_info);
@@ -971,6 +979,7 @@ bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FO
bool ret = ImGui_ImplDX12_Init(&init_info);
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
bd->commandQueueOwned = true;
ImGuiIO& io = ImGui::GetIO();
io.BackendFlags &= ~ImGuiBackendFlags_RendererHasTextures; // Using legacy ImGui_ImplDX12_Init() call with 1 SRV descriptor we cannot support multiple textures.
+62 -51
View File
@@ -17,6 +17,8 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
// 2026-03-19: Fixed issue in ImGui_ImplDX9_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295, #9310)
// 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.
@@ -161,6 +163,11 @@ static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data)
}
}
// Draw callbacks
static void ImGui_ImplDX9_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
static void ImGui_ImplDX9_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData(); bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); }
static void ImGui_ImplDX9_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData(); bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); }
// Render function.
void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
{
@@ -183,14 +190,14 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
{
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
bd->VertexBufferSize = draw_data->TotalVtxCount + 5000;
if (device->CreateVertexBuffer(bd->VertexBufferSize * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &bd->pVB, nullptr) < 0)
if (device->CreateVertexBuffer((UINT)bd->VertexBufferSize * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &bd->pVB, nullptr) < 0)
return;
}
if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount)
{
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
bd->IndexBufferSize = draw_data->TotalIdxCount + 10000;
if (device->CreateIndexBuffer(bd->IndexBufferSize * sizeof(ImDrawIdx), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, sizeof(ImDrawIdx) == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, D3DPOOL_DEFAULT, &bd->pIB, nullptr) < 0)
if (device->CreateIndexBuffer((UINT)bd->IndexBufferSize * sizeof(ImDrawIdx), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, sizeof(ImDrawIdx) == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, D3DPOOL_DEFAULT, &bd->pIB, nullptr) < 0)
return;
}
@@ -268,8 +275,7 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
if (pcmd->UserCallback != nullptr)
{
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
if (pcmd->UserCallback == ImGui_ImplDX9_DrawCallback_ResetRenderState)
ImGui_ImplDX9_SetupRenderState(draw_data);
else
pcmd->UserCallback(draw_list, pcmd);
@@ -324,46 +330,6 @@ static bool ImGui_ImplDX9_CheckFormatSupport(LPDIRECT3DDEVICE9 pDevice, D3DFORMA
return support;
}
bool ImGui_ImplDX9_Init(IDirect3DDevice9* device)
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
// Setup backend capabilities flags
ImGui_ImplDX9_Data* bd = IM_NEW(ImGui_ImplDX9_Data)();
io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_dx9";
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.
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Renderer_TextureMaxWidth = platform_io.Renderer_TextureMaxHeight = 4096;
bd->pd3dDevice = device;
bd->pd3dDevice->AddRef();
bd->HasRgbaSupport = ImGui_ImplDX9_CheckFormatSupport(bd->pd3dDevice, D3DFMT_A8B8G8R8);
return true;
}
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);
}
// Convert RGBA32 to BGRA32 (because RGBA32 is not well supported by DX9 devices)
static void ImGui_ImplDX9_CopyTextureRegion(bool tex_use_colors, const ImU32* src, int src_pitch, ImU32* dst, int dst_pitch, int w, int h)
{
@@ -431,14 +397,15 @@ void ImGui_ImplDX9_UpdateTexture(ImTextureData* tex)
}
else if (tex->Status == ImTextureStatus_WantDestroy)
{
if (LPDIRECT3DTEXTURE9 backend_tex = (LPDIRECT3DTEXTURE9)tex->TexID)
{
IM_ASSERT(tex->TexID == (ImTextureID)(intptr_t)backend_tex);
backend_tex->Release();
if (tex->TexID != ImTextureID_Invalid)
if (LPDIRECT3DTEXTURE9 backend_tex = (LPDIRECT3DTEXTURE9)tex->TexID)
{
IM_ASSERT(tex->TexID == (ImTextureID)(intptr_t)backend_tex);
backend_tex->Release();
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
tex->SetTexID(ImTextureID_Invalid);
}
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
tex->SetTexID(ImTextureID_Invalid);
}
tex->SetStatus(ImTextureStatus_Destroyed);
}
}
@@ -475,6 +442,50 @@ void ImGui_ImplDX9_NewFrame()
IM_UNUSED(bd);
}
bool ImGui_ImplDX9_Init(IDirect3DDevice9* device)
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
// Setup backend capabilities flags
ImGui_ImplDX9_Data* bd = IM_NEW(ImGui_ImplDX9_Data)();
io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_dx9";
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.
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Renderer_TextureMaxWidth = platform_io.Renderer_TextureMaxHeight = 4096;
platform_io.DrawCallback_ResetRenderState = ImGui_ImplDX9_DrawCallback_ResetRenderState;
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplDX9_DrawCallback_SetSamplerLinear;
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplDX9_DrawCallback_SetSamplerNearest;
bd->pd3dDevice = device;
bd->pd3dDevice->AddRef();
bd->HasRgbaSupport = ImGui_ImplDX9_CheckFormatSupport(bd->pd3dDevice, D3DFMT_A8B8G8R8);
return true;
}
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);
}
//-----------------------------------------------------------------------------
#endif // #ifndef IMGUI_DISABLE
+16 -1
View File
@@ -29,6 +29,8 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2026-04-21: Added a Win32-specific implementation of ImGui_ImplGlfw_GetContentScaleXXXX functions for legacy GLFW 3.2.
// 2026-03-25: Mouse cursor is properly restored if changed by user app/code while using glfwSetInputMode(..., GLFW_CURSOR_DISABLED) or ImGuiConfigFlags_NoMouseCursorChange. Amend change from 2025-12-10.
// 2026-02-10: Try to set IMGUI_IMPL_GLFW_DISABLE_X11 / IMGUI_IMPL_GLFW_DISABLE_WAYLAND automatically if corresponding headers are not accessible. (#9225)
// 2025-12-12: Added IMGUI_IMPL_GLFW_DISABLE_X11 / IMGUI_IMPL_GLFW_DISABLE_WAYLAND to forcefully disable either.
// 2025-12-10: Avoid repeated glfwSetCursor()/glfwSetInputMode() calls when unnecessary. Lowers overhead for very high framerates (e.g. 10k+ FPS).
@@ -859,7 +861,10 @@ static void ImGui_ImplGlfw_UpdateMouseCursor()
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) || glfwGetInputMode(bd->Window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)
{
bd->LastMouseCursor = nullptr; // Invalidate so that if user changes underlying cursor we will update it next time we can.
return;
}
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
// (those braces are here to reduce diff with multi-viewports support in 'docking' branch)
@@ -944,6 +949,16 @@ static void ImGui_ImplGlfw_UpdateGamepads()
#undef MAP_ANALOG
}
// For GFLW 3.2 + Windows: include a simplified non-monitor aware version of ImGui_ImplWin32_GetDpiScaleForMonitor().
// This is merely a band-aid to make using GLFW 3.2 a little bit nicer, but prefer to use GLFW 3.3+ or the full correct functions from the Win32 backend.
#if !GLFW_HAS_PER_MONITOR_DPI && defined(_WIN32) && !defined(NOGDI)
static float ImGui_ImplWin32_GetLegacyDpiScale() { const HDC dc = ::GetDC(nullptr); UINT xdpi = ::GetDeviceCaps(dc, LOGPIXELSX); ::ReleaseDC(nullptr, dc); return (float)xdpi / 96.0f; }
static void glfwGetWindowContentScale(GLFWwindow*, float* x_scale, float* y_scale) { *x_scale = *y_scale = ImGui_ImplWin32_GetLegacyDpiScale(); }
static void glfwGetMonitorContentScale(GLFWmonitor*, float* x_scale, float* y_scale) { *x_scale = *y_scale = ImGui_ImplWin32_GetLegacyDpiScale(); }
#undef GLFW_HAS_PER_MONITOR_DPI
#define GLFW_HAS_PER_MONITOR_DPI 1
#endif
// - On Windows the process needs to be marked DPI-aware!! SDL2 doesn't do it by default. You can call ::SetProcessDPIAware() or call ImGui_ImplWin32_EnableDpiAwareness() from Win32 backend.
// - Apple platforms use FramebufferScale so we always return 1.0f.
// - Some accessibility applications are declaring virtual monitors with a DPI of 0.0f, see #7902. We preserve this value for caller to handle.
@@ -1012,7 +1027,7 @@ void ImGui_ImplGlfw_NewFrame()
// (Accept glfwGetTime() not returning a monotonically increasing value. Seems to happens on disconnecting peripherals and probably on VMs and Emscripten, see #6491, #6189, #6114, #3644)
double current_time = glfwGetTime();
if (current_time <= bd->Time)
current_time = bd->Time + 0.00001f;
current_time = bd->Time + 0.00001;
io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f);
bd->Time = current_time;
+86 -54
View File
@@ -16,6 +16,11 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2026-04-28: Added support for standard draw callbacks (in platform_io): DrawCallback_SetSamplerLinear and DrawCallback_SetSamplerNearest. (#9378, #9381)
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState (others are not yet supported). (#9378)
// 2026-04-14: Metal: use a dedicated bufferCacheLock to avoid crashing when bufferCache is replaced by a new object while being used for @synchronize(). (#9367)
// 2026-04-03: Metal: avoid redundant vertex buffer bind in SetupRenderState. (#9343)
// 2026-03-19: Fixed issue in ImGui_ImplMetal_RenderDrawData() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295, #9310)
// 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)
@@ -73,9 +78,12 @@
@interface MetalContext : NSObject
@property (nonatomic, strong) id<MTLDevice> device;
@property (nonatomic, strong) id<MTLDepthStencilState> depthStencilState;
@property (nonatomic, strong) id<MTLSamplerState> samplerStateLinear;
@property (nonatomic, strong) id<MTLSamplerState> samplerStateNearest;
@property (nonatomic, strong) FramebufferDescriptor* framebufferDescriptor; // framebuffer descriptor for current frame; transient
@property (nonatomic, strong) NSMutableDictionary* renderPipelineStateCache; // pipeline cache; keyed on framebuffer descriptors
@property (nonatomic, strong) NSMutableArray<MetalBuffer*>* bufferCache;
@property (nonatomic, strong) NSObject* bufferCacheLock;
@property (nonatomic, assign) double lastBufferCachePurge;
- (MetalBuffer*)dequeueReusableBufferOfLength:(NSUInteger)length device:(id<MTLDevice>)device;
- (id<MTLRenderPipelineState>)renderPipelineStateForFramebufferDescriptor:(FramebufferDescriptor*)descriptor device:(id<MTLDevice>)device;
@@ -84,6 +92,7 @@
struct ImGui_ImplMetal_Data
{
MetalContext* SharedMetalContext;
id<MTLRenderCommandEncoder> RenderCommandEncoder;
ImGui_ImplMetal_Data() { memset((void*)this, 0, sizeof(*this)); }
};
@@ -126,41 +135,6 @@ bool ImGui_ImplMetal_CreateDeviceObjects(MTL::Device* device)
#pragma mark - Dear ImGui Metal Backend API
bool ImGui_ImplMetal_Init(id<MTLDevice> device)
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
ImGui_ImplMetal_Data* bd = IM_NEW(ImGui_ImplMetal_Data)();
io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_metal";
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.
bd->SharedMetalContext = [[MetalContext alloc] init];
bd->SharedMetalContext.device = device;
return true;
}
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();
io.BackendRendererName = nullptr;
io.BackendRendererUserData = nullptr;
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
platform_io.ClearRendererHandlers();
}
void ImGui_ImplMetal_NewFrame(MTLRenderPassDescriptor* renderPassDescriptor)
{
ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData();
@@ -213,11 +187,16 @@ static void ImGui_ImplMetal_SetupRenderState(ImDrawData* draw_data, id<MTLComman
[commandEncoder setVertexBytes:&ortho_projection length:sizeof(ortho_projection) atIndex:1];
[commandEncoder setRenderPipelineState:renderPipelineState];
[commandEncoder setFragmentSamplerState:bd->SharedMetalContext.samplerStateLinear atIndex:0];
[commandEncoder setVertexBuffer:vertexBuffer.buffer offset:0 atIndex:0];
[commandEncoder setVertexBufferOffset:vertexBufferOffset atIndex:0];
[commandEncoder setVertexBuffer:vertexBuffer.buffer offset:vertexBufferOffset atIndex:0];
}
// Draw callbacks
static void ImGui_ImplMetal_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
static void ImGui_ImplMetal_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData(); [bd->RenderCommandEncoder setFragmentSamplerState:bd->SharedMetalContext.samplerStateLinear atIndex:0]; }
static void ImGui_ImplMetal_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData(); [bd->RenderCommandEncoder setFragmentSamplerState:bd->SharedMetalContext.samplerStateNearest atIndex:0]; }
// Metal Render function.
void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer> commandBuffer, id<MTLRenderCommandEncoder> commandEncoder)
{
@@ -254,6 +233,7 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer>
MetalBuffer* vertexBuffer = [ctx dequeueReusableBufferOfLength:vertexBufferLength device:commandBuffer.device];
MetalBuffer* indexBuffer = [ctx dequeueReusableBufferOfLength:indexBufferLength device:commandBuffer.device];
bd->RenderCommandEncoder = commandEncoder;
ImGui_ImplMetal_SetupRenderState(draw_data, commandBuffer, commandEncoder, renderPipelineState, vertexBuffer, 0);
// Will project scissor/clipping rectangles into framebuffer space
@@ -274,8 +254,7 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer>
if (pcmd->UserCallback)
{
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
if (pcmd->UserCallback == ImGui_ImplMetal_DrawCallback_ResetRenderState)
ImGui_ImplMetal_SetupRenderState(draw_data, commandBuffer, commandEncoder, renderPipelineState, vertexBuffer, vertexBufferOffset);
else
pcmd->UserCallback(draw_list, pcmd);
@@ -289,8 +268,8 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer>
// Clamp to viewport as setScissorRect() won't accept values that are off bounds
if (clip_min.x < 0.0f) { clip_min.x = 0.0f; }
if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }
if (clip_max.x > fb_width) { clip_max.x = (float)fb_width; }
if (clip_max.y > fb_height) { clip_max.y = (float)fb_height; }
if (clip_max.x > (float)fb_width) { clip_max.x = (float)fb_width; }
if (clip_max.y > (float)fb_height) { clip_max.y = (float)fb_height; }
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue;
if (pcmd->ElemCount == 0) // drawIndexedPrimitives() validation doesn't accept this
@@ -307,7 +286,8 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer>
[commandEncoder setScissorRect:scissorRect];
// Bind texture, Draw
if (ImTextureID tex_id = pcmd->GetTexID())
ImTextureID tex_id = pcmd->GetTexID();
if (tex_id != ImTextureID_Invalid)
[commandEncoder setFragmentTexture:(__bridge id<MTLTexture>)(void*)(intptr_t)(tex_id) atIndex:0];
[commandEncoder setVertexBufferOffset:(vertexBufferOffset + pcmd->VtxOffset * sizeof(ImDrawVert)) atIndex:0];
@@ -326,14 +306,13 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer>
MetalContext* sharedMetalContext = bd->SharedMetalContext;
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer>)
{
dispatch_async(dispatch_get_main_queue(), ^{
@synchronized(sharedMetalContext.bufferCache)
{
[sharedMetalContext.bufferCache addObject:vertexBuffer];
[sharedMetalContext.bufferCache addObject:indexBuffer];
}
});
@synchronized(sharedMetalContext.bufferCacheLock)
{
[sharedMetalContext.bufferCache addObject:vertexBuffer];
[sharedMetalContext.bufferCache addObject:indexBuffer];
}
}];
bd->RenderCommandEncoder = nil;
}
static void ImGui_ImplMetal_DestroyTexture(ImTextureData* tex)
@@ -410,7 +389,17 @@ bool ImGui_ImplMetal_CreateDeviceObjects(id<MTLDevice> device)
depthStencilDescriptor.depthWriteEnabled = NO;
depthStencilDescriptor.depthCompareFunction = MTLCompareFunctionAlways;
bd->SharedMetalContext.depthStencilState = [device newDepthStencilStateWithDescriptor:depthStencilDescriptor];
MTLSamplerDescriptor* samplerDescriptor = [[MTLSamplerDescriptor alloc] init];
samplerDescriptor.minFilter = MTLSamplerMinMagFilterLinear;
samplerDescriptor.magFilter = MTLSamplerMinMagFilterLinear;
samplerDescriptor.mipFilter = MTLSamplerMipFilterLinear;
bd->SharedMetalContext.samplerStateLinear = [device newSamplerStateWithDescriptor:samplerDescriptor];
samplerDescriptor.minFilter = MTLSamplerMinMagFilterNearest;
samplerDescriptor.magFilter = MTLSamplerMinMagFilterNearest;
samplerDescriptor.mipFilter = MTLSamplerMipFilterNearest;
bd->SharedMetalContext.samplerStateNearest = [device newSamplerStateWithDescriptor:samplerDescriptor];
#ifdef IMGUI_IMPL_METAL_CPP
[samplerDescriptor release];
[depthStencilDescriptor release];
#endif
@@ -427,6 +416,48 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
ImGui_ImplMetal_DestroyTexture(tex);
[bd->SharedMetalContext.renderPipelineStateCache removeAllObjects];
bd->SharedMetalContext.samplerStateLinear = nil;
bd->SharedMetalContext.samplerStateNearest = nil;
}
bool ImGui_ImplMetal_Init(id<MTLDevice> device)
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
ImGui_ImplMetal_Data* bd = IM_NEW(ImGui_ImplMetal_Data)();
io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_metal";
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.
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.DrawCallback_ResetRenderState = ImGui_ImplMetal_DrawCallback_ResetRenderState;
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplMetal_DrawCallback_SetSamplerLinear;
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplMetal_DrawCallback_SetSamplerNearest;
bd->SharedMetalContext = [[MetalContext alloc] init];
bd->SharedMetalContext.device = device;
return true;
}
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();
io.BackendRendererName = nullptr;
io.BackendRendererUserData = nullptr;
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
platform_io.ClearRendererHandlers();
}
#pragma mark - MetalBuffer implementation
@@ -512,6 +543,7 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
{
self.renderPipelineStateCache = [NSMutableDictionary dictionary];
self.bufferCache = [NSMutableArray array];
self.bufferCacheLock = [[NSObject alloc] init];
_lastBufferCachePurge = GetMachAbsoluteTimeInSeconds();
}
return self;
@@ -519,9 +551,9 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
- (MetalBuffer*)dequeueReusableBufferOfLength:(NSUInteger)length device:(id<MTLDevice>)device
{
uint64_t now = GetMachAbsoluteTimeInSeconds();
double now = GetMachAbsoluteTimeInSeconds();
@synchronized(self.bufferCache)
@synchronized(self.bufferCacheLock)
{
// Purge old buffers that haven't been useful for a while
if (now - self.lastBufferCachePurge > 1.0)
@@ -588,9 +620,9 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
"}\n"
"\n"
"fragment half4 fragment_main(VertexOut in [[stage_in]],\n"
" texture2d<half, access::sample> texture [[texture(0)]]) {\n"
" constexpr sampler linearSampler(coord::normalized, min_filter::linear, mag_filter::linear, mip_filter::linear);\n"
" half4 texColor = texture.sample(linearSampler, in.texCoords);\n"
" texture2d<half, access::sample> texture [[texture(0)]],\n"
" sampler textureSampler [[sampler(0)]]) {\n"
" half4 texColor = texture.sample(textureSampler, in.texCoords);\n"
" return half4(in.color) * texColor;\n"
"}\n";
+63 -35
View File
@@ -6,6 +6,7 @@
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
// Missing features or Issues:
// [ ] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
// [ ] Renderer: Use of DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest is emulated by poking to glTexParameter(), as legacy OpenGL doesn't have glBindSampler().
// 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.
@@ -25,6 +26,8 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2026-04-23: OpenGL: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
// 2026-03-12: OpenGL: Fixed invalid assert in ImGui_ImplOpenGL3_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295)
// 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().
@@ -85,6 +88,9 @@
// OpenGL data
struct ImGui_ImplOpenGL2_Data
{
bool UseTexParameterToSetSampler;
GLuint NextSampler;
ImGui_ImplOpenGL2_Data() { memset((void*)this, 0, sizeof(*this)); }
};
@@ -96,37 +102,6 @@ static ImGui_ImplOpenGL2_Data* ImGui_ImplOpenGL2_GetBackendData()
}
// Functions
bool ImGui_ImplOpenGL2_Init()
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
// Setup backend capabilities flags
ImGui_ImplOpenGL2_Data* bd = IM_NEW(ImGui_ImplOpenGL2_Data)();
io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_opengl2";
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
return true;
}
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);
}
void ImGui_ImplOpenGL2_NewFrame()
{
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
@@ -137,6 +112,7 @@ void ImGui_ImplOpenGL2_NewFrame()
static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height)
{
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill.
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // In order to composite our output buffer we need to preserve alpha
@@ -154,6 +130,7 @@ static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_wid
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glShadeModel(GL_SMOOTH);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
bd->NextSampler = GL_LINEAR;
// If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!),
// you may need to backup/reset/restore other state, e.g. for current shader using the commented lines below.
@@ -178,12 +155,18 @@ static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_wid
glLoadIdentity();
}
// Draw callbacks
static void ImGui_ImplOpenGL2_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
static void ImGui_ImplOpenGL2_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_LINEAR; }
static void ImGui_ImplOpenGL2_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_NEAREST; }
// OpenGL2 Render function.
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly.
// This is in order to be able to run within an OpenGL engine that doesn't do so.
void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
{
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
if (fb_width == 0 || fb_height == 0)
@@ -227,8 +210,7 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
if (pcmd->UserCallback)
{
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
if (pcmd->UserCallback == ImGui_ImplOpenGL2_DrawCallback_ResetRenderState)
ImGui_ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height);
else
pcmd->UserCallback(draw_list, pcmd);
@@ -245,7 +227,17 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
glScissor((int)clip_min.x, (int)((float)fb_height - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y));
// Bind texture, Draw
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID());
GLuint pcmd_texture = (GLuint)(intptr_t)pcmd->GetTexID();
glBindTexture(GL_TEXTURE_2D, pcmd_texture);
// Emulate sampler change (even though it is technically part of texture data)
// As a sort of hack/workaround, we only start writing using glTextParameter() if sampler is ever changed explicitly.
if (bd->UseTexParameterToSetSampler)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, bd->NextSampler);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, bd->NextSampler);
}
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer + pcmd->IdxOffset);
}
}
@@ -274,7 +266,7 @@ void ImGui_ImplOpenGL2_UpdateTexture(ImTextureData* tex)
{
// Create and upload new texture to graphics system
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
IM_ASSERT(tex->TexID == 0 && tex->BackendUserData == nullptr);
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
const void* pixels = tex->GetPixels();
GLuint gl_texture_id = 0;
@@ -343,6 +335,42 @@ void ImGui_ImplOpenGL2_DestroyDeviceObjects()
}
}
bool ImGui_ImplOpenGL2_Init()
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
// Setup backend capabilities flags
ImGui_ImplOpenGL2_Data* bd = IM_NEW(ImGui_ImplOpenGL2_Data)();
io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_opengl2";
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.DrawCallback_ResetRenderState = ImGui_ImplOpenGL2_DrawCallback_ResetRenderState;
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplOpenGL2_DrawCallback_SetSamplerLinear;
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplOpenGL2_DrawCallback_SetSamplerNearest;
return true;
}
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);
}
//-----------------------------------------------------------------------------
#if defined(__clang__)
+1
View File
@@ -6,6 +6,7 @@
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
// Missing features or Issues:
// [ ] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
// [ ] Renderer: Use of DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest is emulated by poking to glTexParameter(), as legacy OpenGL doesn't have glBindSampler().
// 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.
+183 -137
View File
@@ -23,6 +23,8 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2026-04-23: OpenGL: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
// 2026-03-12: OpenGL: Fixed invalid assert in ImGui_ImplOpenGL3_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295)
// 2025-12-11: OpenGL: Fixed embedded loader multiple init/shutdown cycles broken on some platforms. (#8792, #9112)
// 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)
@@ -251,6 +253,12 @@ struct ImGui_ImplOpenGL3_Data
bool HasBindSampler;
bool HasClipOrigin;
bool UseBufferSubData;
bool UseTexParameterToSetSampler;
GLuint NextSampler; // Used if !HasBindSampler && UseTexParameterToSetSampler.
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
GLuint TexSamplers[2]; // Used if HasBindSimpler. (0=linear, 1=nearest)
#endif
ImVector<char> TempBuffer;
ImGui_ImplOpenGL3_Data() { memset((void*)this, 0, sizeof(*this)); }
@@ -311,139 +319,6 @@ static void ImGui_ImplOpenGL3_ShutdownLoader()
}
// Functions
bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
// Initialize loader
if (!ImGui_ImplOpenGL3_InitLoader())
return false;
// Setup backend capabilities flags
ImGui_ImplOpenGL3_Data* bd = IM_NEW(ImGui_ImplOpenGL3_Data)();
io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_opengl3";
// Query for GL version (e.g. 320 for GL 3.2)
const char* gl_version_str = (const char*)glGetString(GL_VERSION);
#if defined(IMGUI_IMPL_OPENGL_ES2)
// GLES 2
bd->GlVersion = 200;
bd->GlProfileIsES2 = true;
IM_UNUSED(gl_version_str);
#else
// Desktop or GLES 3
GLint major = 0;
GLint minor = 0;
glGetIntegerv(GL_MAJOR_VERSION, &major);
glGetIntegerv(GL_MINOR_VERSION, &minor);
if (major == 0 && minor == 0)
sscanf(gl_version_str, "%d.%d", &major, &minor); // Query GL_VERSION in desktop GL 2.x, the string will start with "<major>.<minor>"
bd->GlVersion = (GLuint)(major * 100 + minor * 10);
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &bd->MaxTextureSize);
#if defined(IMGUI_IMPL_OPENGL_ES3)
bd->GlProfileIsES3 = true;
#else
if (strncmp(gl_version_str, "OpenGL ES 3", 11) == 0)
bd->GlProfileIsES3 = true;
#endif
#if defined(GL_CONTEXT_PROFILE_MASK)
if (!bd->GlProfileIsES3 && bd->GlVersion >= 320)
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &bd->GlProfileMask);
bd->GlProfileIsCompat = (bd->GlProfileMask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) != 0;
#endif
bd->UseBufferSubData = false;
/*
// Query vendor to enable glBufferSubData kludge
#ifdef _WIN32
if (const char* vendor = (const char*)glGetString(GL_VENDOR))
if (strncmp(vendor, "Intel", 5) == 0)
bd->UseBufferSubData = true;
#endif
*/
#endif
#ifdef IMGUI_IMPL_OPENGL_DEBUG
printf("GlVersion = %d, \"%s\"\nGlProfileIsCompat = %d\nGlProfileMask = 0x%X\nGlProfileIsES2/IsEs3 = %d/%d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", bd->GlVersion, gl_version_str, bd->GlProfileIsCompat, bd->GlProfileMask, bd->GlProfileIsES2, bd->GlProfileIsES3, (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); // [DEBUG]
#endif
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
if (bd->GlVersion >= 320)
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
#endif
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Renderer_TextureMaxWidth = platform_io.Renderer_TextureMaxHeight = (int)bd->MaxTextureSize;
// Store GLSL version string so we can refer to it later in case we recreate shaders.
// Note: GLSL version is NOT the same as GL version. Leave this to nullptr if unsure.
if (glsl_version == nullptr)
{
#if defined(IMGUI_IMPL_OPENGL_ES2)
glsl_version = "#version 100";
#elif defined(IMGUI_IMPL_OPENGL_ES3)
glsl_version = "#version 300 es";
#elif defined(__APPLE__)
glsl_version = "#version 150";
#else
glsl_version = "#version 130";
#endif
}
IM_ASSERT((int)strlen(glsl_version) + 2 < IM_COUNTOF(bd->GlslVersionString));
strcpy(bd->GlslVersionString, glsl_version);
strcat(bd->GlslVersionString, "\n");
// Make an arbitrary GL call (we don't actually need the result)
// IF YOU GET A CRASH HERE: it probably means the OpenGL function loader didn't do its job. Let us know!
GLint current_texture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
// Detect extensions we support
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
bd->HasPolygonMode = (!bd->GlProfileIsES2 && !bd->GlProfileIsES3);
#endif
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
bd->HasBindSampler = (bd->GlVersion >= 330 || bd->GlProfileIsES3);
#endif
bd->HasClipOrigin = (bd->GlVersion >= 450);
#ifdef IMGUI_IMPL_OPENGL_HAS_EXTENSIONS
GLint num_extensions = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
for (GLint i = 0; i < num_extensions; i++)
{
const char* extension = (const char*)glGetStringi(GL_EXTENSIONS, i);
if (extension != nullptr && strcmp(extension, "GL_ARB_clip_control") == 0)
bd->HasClipOrigin = true;
}
#endif
return true;
}
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);
ImGui_ImplOpenGL3_ShutdownLoader();
}
void ImGui_ImplOpenGL3_NewFrame()
{
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
@@ -510,7 +385,7 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
if (bd->HasBindSampler)
glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 and GL ES 3.0 may set that otherwise.
glBindSampler(0, bd->TexSamplers[0]); // We use combined texture/sampler state. Applications using GL 3.3 and GL ES 3.0 may set that otherwise.
#endif
(void)vertex_array_object;
@@ -529,6 +404,16 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)offsetof(ImDrawVert, col)));
}
// Draw callbacks
static void ImGui_ImplOpenGL3_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); if (bd->HasBindSampler) { glBindSampler(0, bd->TexSamplers[0]); } else { bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_LINEAR; } }
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); if (bd->HasBindSampler) { glBindSampler(0, bd->TexSamplers[1]); } else { bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_NEAREST; } }
#else
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_LINEAR; }
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_NEAREST; }
#endif
// OpenGL3 Render function.
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly.
// This is in order to be able to run within an OpenGL engine that doesn't do so.
@@ -643,8 +528,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
if (pcmd->UserCallback != nullptr)
{
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
if (pcmd->UserCallback == ImGui_ImplOpenGL3_DrawCallback_ResetRenderState)
ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object);
else
pcmd->UserCallback(draw_list, pcmd);
@@ -662,6 +546,15 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
// Bind texture, Draw
GL_CALL(glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID()));
// Emulate sampler change (even though it is technically part of texture data)
// As a sort of hack/workaround, we only start writing using glTextParameter() if sampler is ever changed explicitly.
if (!bd->HasBindSampler && bd->UseTexParameterToSetSampler)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, bd->NextSampler);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, bd->NextSampler);
}
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
if (bd->GlVersion >= 320)
GL_CALL(glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset));
@@ -744,7 +637,7 @@ void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex)
{
// Create and upload new texture to graphics system
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
IM_ASSERT(tex->TexID == 0 && tex->BackendUserData == nullptr);
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
const void* pixels = tex->GetPixels();
GLuint gl_texture_id = 0;
@@ -1027,6 +920,20 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
glGenBuffers(1, &bd->VboHandle);
glGenBuffers(1, &bd->ElementsHandle);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
if (bd->HasBindSampler)
{
glGenSamplers(2, &bd->TexSamplers[0]);
for (int sampler_n = 0; sampler_n < 2; sampler_n++)
{
GL_CALL(glSamplerParameteri(bd->TexSamplers[sampler_n], GL_TEXTURE_MIN_FILTER, (sampler_n == 0) ? GL_LINEAR : GL_NEAREST));
GL_CALL(glSamplerParameteri(bd->TexSamplers[sampler_n], GL_TEXTURE_MAG_FILTER, (sampler_n == 0) ? GL_LINEAR : GL_NEAREST));
GL_CALL(glSamplerParameteri(bd->TexSamplers[sampler_n], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
GL_CALL(glSamplerParameteri(bd->TexSamplers[sampler_n], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
}
}
#endif
// Restore modified GL state
glBindTexture(GL_TEXTURE_2D, last_texture);
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
@@ -1044,6 +951,9 @@ void ImGui_ImplOpenGL3_DestroyDeviceObjects()
{
ImGui_ImplOpenGL3_InitLoader();
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
if (bd->TexSamplers[0]) { glDeleteSamplers(2, &bd->TexSamplers[0]); bd->TexSamplers[0] = bd->TexSamplers[1] = 0; }
#endif
if (bd->VboHandle) { glDeleteBuffers(1, &bd->VboHandle); bd->VboHandle = 0; }
if (bd->ElementsHandle) { glDeleteBuffers(1, &bd->ElementsHandle); bd->ElementsHandle = 0; }
if (bd->ShaderHandle) { glDeleteProgram(bd->ShaderHandle); bd->ShaderHandle = 0; }
@@ -1054,6 +964,142 @@ void ImGui_ImplOpenGL3_DestroyDeviceObjects()
ImGui_ImplOpenGL3_DestroyTexture(tex);
}
bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
// Initialize loader
if (!ImGui_ImplOpenGL3_InitLoader())
return false;
// Setup backend capabilities flags
ImGui_ImplOpenGL3_Data* bd = IM_NEW(ImGui_ImplOpenGL3_Data)();
io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_opengl3";
// Query for GL version (e.g. 320 for GL 3.2)
const char* gl_version_str = (const char*)glGetString(GL_VERSION);
#if defined(IMGUI_IMPL_OPENGL_ES2)
// GLES 2
bd->GlVersion = 200;
bd->GlProfileIsES2 = true;
IM_UNUSED(gl_version_str);
#else
// Desktop or GLES 3
GLint major = 0;
GLint minor = 0;
glGetIntegerv(GL_MAJOR_VERSION, &major);
glGetIntegerv(GL_MINOR_VERSION, &minor);
if (major == 0 && minor == 0)
sscanf(gl_version_str, "%d.%d", &major, &minor); // Query GL_VERSION in desktop GL 2.x, the string will start with "<major>.<minor>"
bd->GlVersion = (GLuint)(major * 100 + minor * 10);
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &bd->MaxTextureSize);
#if defined(IMGUI_IMPL_OPENGL_ES3)
bd->GlProfileIsES3 = true;
#else
if (strncmp(gl_version_str, "OpenGL ES 3", 11) == 0)
bd->GlProfileIsES3 = true;
#endif
#if defined(GL_CONTEXT_PROFILE_MASK)
if (!bd->GlProfileIsES3 && bd->GlVersion >= 320)
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &bd->GlProfileMask);
bd->GlProfileIsCompat = (bd->GlProfileMask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) != 0;
#endif
bd->UseBufferSubData = false;
/*
// Query vendor to enable glBufferSubData kludge
#ifdef _WIN32
if (const char* vendor = (const char*)glGetString(GL_VENDOR))
if (strncmp(vendor, "Intel", 5) == 0)
bd->UseBufferSubData = true;
#endif
*/
#endif
#ifdef IMGUI_IMPL_OPENGL_DEBUG
printf("GlVersion = %d, \"%s\"\nGlProfileIsCompat = %d\nGlProfileMask = 0x%X\nGlProfileIsES2/IsEs3 = %d/%d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", bd->GlVersion, gl_version_str, bd->GlProfileIsCompat, bd->GlProfileMask, bd->GlProfileIsES2, bd->GlProfileIsES3, (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); // [DEBUG]
#endif
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
if (bd->GlVersion >= 320)
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
#endif
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Renderer_TextureMaxWidth = platform_io.Renderer_TextureMaxHeight = (int)bd->MaxTextureSize;
platform_io.DrawCallback_ResetRenderState = ImGui_ImplOpenGL3_DrawCallback_ResetRenderState;
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplOpenGL3_DrawCallback_SetSamplerLinear;
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplOpenGL3_DrawCallback_SetSamplerNearest;
// Store GLSL version string so we can refer to it later in case we recreate shaders.
// Note: GLSL version is NOT the same as GL version. Leave this to nullptr if unsure.
if (glsl_version == nullptr)
{
#if defined(IMGUI_IMPL_OPENGL_ES2)
glsl_version = "#version 100";
#elif defined(IMGUI_IMPL_OPENGL_ES3)
glsl_version = "#version 300 es";
#elif defined(__APPLE__)
glsl_version = "#version 150";
#else
glsl_version = "#version 130";
#endif
}
IM_ASSERT((int)strlen(glsl_version) + 2 < IM_COUNTOF(bd->GlslVersionString));
strcpy(bd->GlslVersionString, glsl_version);
strcat(bd->GlslVersionString, "\n");
// Make an arbitrary GL call (we don't actually need the result)
// IF YOU GET A CRASH HERE: it probably means the OpenGL function loader didn't do its job. Let us know!
GLint current_texture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
// Detect extensions we support
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
bd->HasPolygonMode = (!bd->GlProfileIsES2 && !bd->GlProfileIsES3);
#endif
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
bd->HasBindSampler = (bd->GlVersion >= 330 || bd->GlProfileIsES3);
#endif
bd->HasClipOrigin = (bd->GlVersion >= 450);
#ifdef IMGUI_IMPL_OPENGL_HAS_EXTENSIONS
GLint num_extensions = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
for (GLint i = 0; i < num_extensions; i++)
{
const char* extension = (const char*)glGetStringi(GL_EXTENSIONS, i);
if (extension != nullptr && strcmp(extension, "GL_ARB_clip_control") == 0)
bd->HasClipOrigin = true;
}
#endif
return true;
}
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);
ImGui_ImplOpenGL3_ShutdownLoader();
}
//-----------------------------------------------------------------------------
#if defined(__GNUC__)
+8 -2
View File
@@ -21,6 +21,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2026-04-16: Made ImGui_ImplSDL2_GetContentScaleForWindow(), ImGui_ImplSDL2_GetContentScaleForDisplay() helpers return a minimum of 1.0f, as some Linux setup seems to report <1.0f value and this breaks scaling border size. (#9369)
// 2026-02-13: Inputs: systems other than X11 are back to starting mouse capture on mouse down (reverts 2025-02-26 change). Only X11 requires waiting for a drag by default (not ideal, but a better default for X11 users). Added ImGui_ImplSDL2_SetMouseCaptureMode() for X11 debugger users. (#3650, #6410, #9235)
// 2026-01-15: Changed GetClipboardText() handler to return nullptr on error aka clipboard contents is not text. Consistent with other backends. (#9168)
// 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)
@@ -748,6 +749,7 @@ float ImGui_ImplSDL2_GetContentScaleForWindow(SDL_Window* window)
return ImGui_ImplSDL2_GetContentScaleForDisplay(SDL_GetWindowDisplayIndex(window));
}
// SDL_GetDisplayDPI() seems rather unreliable on Linux.
float ImGui_ImplSDL2_GetContentScaleForDisplay(int display_index)
{
const char* sdl_driver = SDL_GetCurrentVideoDriver();
@@ -757,7 +759,11 @@ float ImGui_ImplSDL2_GetContentScaleForDisplay(int display_index)
#if !defined(__APPLE__) && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__)
float dpi = 0.0f;
if (SDL_GetDisplayDPI(display_index, &dpi, nullptr, nullptr) == 0)
{
if (dpi < 96.0f)
dpi = 96.0f;
return dpi / 96.0f;
}
#endif
#endif
IM_UNUSED(display_index);
@@ -884,7 +890,7 @@ static void ImGui_ImplSDL2_GetWindowSizeAndFramebufferScale(SDL_Window* window,
if (out_size != nullptr)
*out_size = ImVec2((float)w, (float)h);
if (out_framebuffer_scale != nullptr)
*out_framebuffer_scale = (w > 0 && h > 0) ? ImVec2((float)display_w / w, (float)display_h / h) : ImVec2(1.0f, 1.0f);
*out_framebuffer_scale = (w > 0 && h > 0) ? ImVec2((float)display_w / (float)w, (float)display_h / (float)h) : ImVec2(1.0f, 1.0f);
}
void ImGui_ImplSDL2_NewFrame()
@@ -902,7 +908,7 @@ void ImGui_ImplSDL2_NewFrame()
Uint64 current_time = SDL_GetPerformanceCounter();
if (current_time <= bd->Time)
current_time = bd->Time + 1;
io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / frequency) : (float)(1.0f / 60.0f);
io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / (double)frequency) : (float)(1.0f / 60.0f);
bd->Time = current_time;
if (bd->MouseLastLeaveFrame && bd->MouseLastLeaveFrame >= ImGui::GetFrameCount() && bd->MouseButtonsDown == 0)
+3 -3
View File
@@ -686,8 +686,8 @@ static void ImGui_ImplSDL3_UpdateMouseData()
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;
mouse_x -= (float)window_x;
mouse_y -= (float)window_y;
io.AddMousePosEvent(mouse_x, mouse_y);
}
}
@@ -860,7 +860,7 @@ void ImGui_ImplSDL3_NewFrame()
Uint64 current_time = SDL_GetPerformanceCounter();
if (current_time <= bd->Time)
current_time = bd->Time + 1;
io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / frequency) : (float)(1.0f / 60.0f);
io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / (double)frequency) : (float)(1.0f / 60.0f);
bd->Time = current_time;
if (bd->MousePendingLeaveFrame && bd->MousePendingLeaveFrame >= ImGui::GetFrameCount() && bd->MouseButtonsDown == 0)
+32 -16
View File
@@ -22,6 +22,8 @@
// 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
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. Obsoleting samplers from ImGui_ImplSDLGPU3_RenderState. (#9378)
// 2026-03-19: Fixed issue in ImGui_ImplSDLGPU3_DestroyTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295, #9310)
// 2026-02-25: Removed unnecessary call to SDL_WaitForGPUIdle when releasing vertex/index buffers. (#9262)
// 2025-11-26: macOS version can use MSL shaders in order to support macOS 10.14+ (vs Metallib shaders requiring macOS 14+). Requires calling SDL_CreateGPUDevice() with SDL_GPU_SHADERFORMAT_MSL.
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
@@ -58,6 +60,10 @@ struct ImGui_ImplSDLGPU3_Data
{
ImGui_ImplSDLGPU3_InitInfo InitInfo;
// Render state
ImGui_ImplSDLGPU3_RenderState* RenderState = nullptr; // == ImGui::GetPlatformIO().Renderer_RenderState during rendering.
SDL_GPUSampler* CurrentSampler = nullptr;
// Graphics pipeline & shaders
SDL_GPUShader* VertexShader = nullptr;
SDL_GPUShader* FragmentShader = nullptr;
@@ -86,10 +92,10 @@ static ImGui_ImplSDLGPU3_Data* ImGui_ImplSDLGPU3_GetBackendData()
return ImGui::GetCurrentContext() ? (ImGui_ImplSDLGPU3_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
}
static void ImGui_ImplSDLGPU3_SetupRenderState(ImDrawData* draw_data, ImGui_ImplSDLGPU3_RenderState* render_state, SDL_GPUGraphicsPipeline* pipeline, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, ImGui_ImplSDLGPU3_FrameData* fd, uint32_t fb_width, uint32_t fb_height)
static void ImGui_ImplSDLGPU3_SetupRenderState(ImDrawData* draw_data, SDL_GPUGraphicsPipeline* pipeline, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, ImGui_ImplSDLGPU3_FrameData* fd, uint32_t fb_width, uint32_t fb_height)
{
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
render_state->SamplerCurrent = bd->TexSamplerLinear;
bd->CurrentSampler = bd->TexSamplerLinear;
// Bind graphics pipeline
SDL_BindGPUGraphicsPipeline(render_pass, pipeline);
@@ -173,8 +179,8 @@ void ImGui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuff
ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo;
ImGui_ImplSDLGPU3_FrameData* fd = &bd->MainWindowFrameData;
uint32_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert);
uint32_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx);
uint32_t vertex_size = (uint32_t)draw_data->TotalVtxCount * sizeof(ImDrawVert);
uint32_t index_size = (uint32_t)draw_data->TotalIdxCount * sizeof(ImDrawIdx);
if (fd->VertexBuffer == nullptr || fd->VertexBufferSize < vertex_size)
CreateOrResizeBuffers(&fd->VertexBuffer, &fd->VertexTransferBuffer, &fd->VertexBufferSize, vertex_size, SDL_GPU_BUFFERUSAGE_VERTEX);
if (fd->IndexBuffer == nullptr || fd->IndexBufferSize < index_size)
@@ -215,6 +221,11 @@ void ImGui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuff
SDL_EndGPUCopyPass(copy_pass);
}
// Draw callbacks
static void ImGui_ImplSDLGPU3_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
static void ImGui_ImplSDLGPU3_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); bd->CurrentSampler = bd->TexSamplerLinear; }
static void ImGui_ImplSDLGPU3_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); bd->CurrentSampler = bd->TexSamplerNearest; }
void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, SDL_GPUGraphicsPipeline* pipeline)
{
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
@@ -237,11 +248,9 @@ void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffe
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
ImGui_ImplSDLGPU3_RenderState render_state;
render_state.Device = bd->InitInfo.Device;
render_state.SamplerLinear = render_state.SamplerCurrent = bd->TexSamplerLinear;
render_state.SamplerNearest = bd->TexSamplerNearest;
platform_io.Renderer_RenderState = &render_state;
platform_io.Renderer_RenderState = bd->RenderState = &render_state;
ImGui_ImplSDLGPU3_SetupRenderState(draw_data, &render_state, pipeline, command_buffer, render_pass, fd, fb_width, fb_height);
ImGui_ImplSDLGPU3_SetupRenderState(draw_data, pipeline, command_buffer, render_pass, fd, fb_width, fb_height);
// Render command lists
// (Because we merged all buffers into a single one, we maintain our own offset into them)
@@ -255,9 +264,8 @@ void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffe
if (pcmd->UserCallback != nullptr)
{
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
ImGui_ImplSDLGPU3_SetupRenderState(draw_data, &render_state, pipeline, command_buffer, render_pass, fd, fb_width, fb_height);
if (pcmd->UserCallback == ImGui_ImplSDLGPU3_DrawCallback_ResetRenderState)
ImGui_ImplSDLGPU3_SetupRenderState(draw_data, pipeline, command_buffer, render_pass, fd, fb_width, fb_height);
else
pcmd->UserCallback(draw_list, pcmd);
}
@@ -270,8 +278,8 @@ void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffe
// Clamp to viewport as SDL_SetGPUScissor() won't accept values that are off bounds
if (clip_min.x < 0.0f) { clip_min.x = 0.0f; }
if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }
if (clip_max.x > fb_width) { clip_max.x = (float)fb_width; }
if (clip_max.y > fb_height) { clip_max.y = (float)fb_height; }
if (clip_max.x > (float)fb_width) { clip_max.x = (float)fb_width; }
if (clip_max.y > (float)fb_height) { clip_max.y = (float)fb_height; }
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue;
@@ -286,7 +294,7 @@ void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffe
// Bind DescriptorSet with font or user texture
SDL_GPUTextureSamplerBinding texture_sampler_binding;
texture_sampler_binding.texture = (SDL_GPUTexture*)(intptr_t)pcmd->GetTexID();
texture_sampler_binding.sampler = render_state.SamplerCurrent;
texture_sampler_binding.sampler = bd->CurrentSampler;
SDL_BindGPUFragmentSamplers(render_pass, 0, &texture_sampler_binding, 1);
// Draw
@@ -305,13 +313,16 @@ void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffe
// We perform a call to SDL_SetGPUScissor() to set back a full viewport which is likely to fix things for 99% users but technically this is not perfect. (See github #4644)
SDL_Rect scissor_rect { 0, 0, fb_width, fb_height };
SDL_SetGPUScissor(render_pass, &scissor_rect);
platform_io.Renderer_RenderState = bd->RenderState = nullptr;
}
static void ImGui_ImplSDLGPU3_DestroyTexture(ImTextureData* tex)
{
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
if (SDL_GPUTexture* raw_tex = (SDL_GPUTexture*)(intptr_t)tex->GetTexID())
SDL_ReleaseGPUTexture(bd->InitInfo.Device, raw_tex);
if (tex->GetTexID() != ImTextureID_Invalid)
if (SDL_GPUTexture* raw_tex = (SDL_GPUTexture*)(intptr_t)tex->GetTexID())
SDL_ReleaseGPUTexture(bd->InitInfo.Device, raw_tex);
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
tex->SetTexID(ImTextureID_Invalid);
@@ -654,6 +665,11 @@ bool ImGui_ImplSDLGPU3_Init(ImGui_ImplSDLGPU3_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.
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.DrawCallback_ResetRenderState = ImGui_ImplSDLGPU3_DrawCallback_ResetRenderState;
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplSDLGPU3_DrawCallback_SetSamplerLinear;
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplSDLGPU3_DrawCallback_SetSamplerNearest;
IM_ASSERT(info->Device != nullptr);
IM_ASSERT(info->ColorTargetFormat != SDL_GPU_TEXTUREFORMAT_INVALID);
-3
View File
@@ -57,9 +57,6 @@ IMGUI_IMPL_API void ImGui_ImplSDLGPU3_UpdateTexture(ImTextureData* tex);
struct ImGui_ImplSDLGPU3_RenderState
{
SDL_GPUDevice* Device;
SDL_GPUSampler* SamplerLinear; // Bilinear filtering sampler
SDL_GPUSampler* SamplerNearest; // Nearest/point filtering sampler
SDL_GPUSampler* SamplerCurrent; // Current sampler (may be changed by callback)
};
#endif // #ifndef IMGUI_DISABLE
+51 -40
View File
@@ -14,8 +14,10 @@
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
// Missing features or Issues:
// [ ] Renderer: Missing support for DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest callbacks: SDLRenderer2 does not support changing SDL_SCALE_MODE while rendering.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// 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.
// Learn about Dear ImGui:
// - FAQ https://dearimgui.com/faq
@@ -24,6 +26,9 @@
// - Introduction, links and more at the top of imgui.cpp
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState (others cannot be supported). (#9378)
// 2026-03-12: Fixed invalid assert in ImGui_ImplSDLRenderer2_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295)
// 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.
@@ -71,41 +76,6 @@ static ImGui_ImplSDLRenderer2_Data* ImGui_ImplSDLRenderer2_GetBackendData()
}
// Functions
bool ImGui_ImplSDLRenderer2_Init(SDL_Renderer* renderer)
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
IM_ASSERT(renderer != nullptr && "SDL_Renderer not initialized!");
// Setup backend capabilities flags
ImGui_ImplSDLRenderer2_Data* bd = IM_NEW(ImGui_ImplSDLRenderer2_Data)();
io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_sdlrenderer2";
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.
bd->Renderer = renderer;
return true;
}
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);
}
static void ImGui_ImplSDLRenderer2_SetupRenderState(SDL_Renderer* renderer)
{
// Clear out any viewports and cliprect set by the user
@@ -121,6 +91,9 @@ void ImGui_ImplSDLRenderer2_NewFrame()
IM_UNUSED(bd);
}
// Draw callbacks
static void ImGui_ImplSDLRenderer2_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* renderer)
{
// If there's a scale factor set by the user, use that instead
@@ -183,8 +156,7 @@ void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
if (pcmd->UserCallback)
{
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
if (pcmd->UserCallback == ImGui_ImplSDLRenderer2_DrawCallback_ResetRenderState)
ImGui_ImplSDLRenderer2_SetupRenderState(renderer);
else
pcmd->UserCallback(draw_list, pcmd);
@@ -267,8 +239,9 @@ void ImGui_ImplSDLRenderer2_UpdateTexture(ImTextureData* tex)
}
else if (tex->Status == ImTextureStatus_WantDestroy)
{
if (SDL_Texture* sdl_texture = (SDL_Texture*)(intptr_t)tex->TexID)
SDL_DestroyTexture(sdl_texture);
if (tex->TexID != ImTextureID_Invalid)
if (SDL_Texture* sdl_texture = (SDL_Texture*)(intptr_t)tex->TexID)
SDL_DestroyTexture(sdl_texture);
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
tex->SetTexID(ImTextureID_Invalid);
@@ -291,6 +264,44 @@ void ImGui_ImplSDLRenderer2_DestroyDeviceObjects()
}
}
bool ImGui_ImplSDLRenderer2_Init(SDL_Renderer* renderer)
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
IM_ASSERT(renderer != nullptr && "SDL_Renderer not initialized!");
// Setup backend capabilities flags
ImGui_ImplSDLRenderer2_Data* bd = IM_NEW(ImGui_ImplSDLRenderer2_Data)();
io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_sdlrenderer2";
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.
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.DrawCallback_ResetRenderState = ImGui_ImplSDLRenderer2_DrawCallback_ResetRenderState;
bd->Renderer = renderer;
return true;
}
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);
}
//-----------------------------------------------------------------------------
#if defined(__clang__)
+2
View File
@@ -14,6 +14,8 @@
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
// Missing features or Issues:
// [ ] Renderer: Missing support for DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest callbacks: SDLRenderer2 does not support changing SDL_SCALE_MODE while rendering.
// 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.
+58 -41
View File
@@ -15,7 +15,7 @@
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// 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.
// Learn about Dear ImGui:
// - FAQ https://dearimgui.com/faq
@@ -24,6 +24,9 @@
// - Introduction, links and more at the top of imgui.cpp
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
// 2026-03-12: Fixed invalid assert in ImGui_ImplSDLRenderer3_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295)
// 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.
@@ -58,6 +61,9 @@ struct ImGui_ImplSDLRenderer3_Data
SDL_Renderer* Renderer; // Main viewport's renderer
ImVector<SDL_FColor> ColorBuffer;
// Render State
SDL_ScaleMode CurrentScaleMode;
ImGui_ImplSDLRenderer3_Data() { memset((void*)this, 0, sizeof(*this)); }
};
@@ -69,41 +75,6 @@ static ImGui_ImplSDLRenderer3_Data* ImGui_ImplSDLRenderer3_GetBackendData()
}
// Functions
bool ImGui_ImplSDLRenderer3_Init(SDL_Renderer* renderer)
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
IM_ASSERT(renderer != nullptr && "SDL_Renderer not initialized!");
// Setup backend capabilities flags
ImGui_ImplSDLRenderer3_Data* bd = IM_NEW(ImGui_ImplSDLRenderer3_Data)();
io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_sdlrenderer3";
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.
bd->Renderer = renderer;
return true;
}
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);
}
static void ImGui_ImplSDLRenderer3_SetupRenderState(SDL_Renderer* renderer)
{
// Clear out any viewports and cliprect set by the user
@@ -137,6 +108,11 @@ static int SDL_RenderGeometryRaw8BitColor(SDL_Renderer* renderer, ImVector<SDL_F
return SDL_RenderGeometryRaw(renderer, texture, xy, xy_stride, color3, sizeof(*color3), uv, uv_stride, num_vertices, indices, num_indices, size_indices);
}
// Draw callbacks
static void ImGui_ImplSDLRenderer3_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
static void ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData(); bd->CurrentScaleMode = SDL_SCALEMODE_LINEAR; }
static void ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData(); bd->CurrentScaleMode = SDL_SCALEMODE_NEAREST; }
void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* renderer)
{
ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData();
@@ -203,8 +179,7 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
if (pcmd->UserCallback)
{
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
if (pcmd->UserCallback == ImGui_ImplSDLRenderer3_DrawCallback_ResetRenderState)
ImGui_ImplSDLRenderer3_SetupRenderState(renderer);
else
pcmd->UserCallback(draw_list, pcmd);
@@ -230,6 +205,7 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
// Bind texture, Draw
SDL_Texture* tex = (SDL_Texture*)pcmd->GetTexID();
SDL_SetTextureScaleMode(tex, bd->CurrentScaleMode);
SDL_RenderGeometryRaw8BitColor(renderer, bd->ColorBuffer, tex,
xy, (int)sizeof(ImDrawVert),
color, (int)sizeof(ImDrawVert),
@@ -254,7 +230,7 @@ void ImGui_ImplSDLRenderer3_UpdateTexture(ImTextureData* tex)
{
// Create and upload new texture to graphics system
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
IM_ASSERT(tex->TexID == 0 && tex->BackendUserData == nullptr);
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
// Create texture
@@ -283,8 +259,9 @@ void ImGui_ImplSDLRenderer3_UpdateTexture(ImTextureData* tex)
}
else if (tex->Status == ImTextureStatus_WantDestroy)
{
if (SDL_Texture* sdl_texture = (SDL_Texture*)(intptr_t)tex->TexID)
SDL_DestroyTexture(sdl_texture);
if (tex->TexID != ImTextureID_Invalid)
if (SDL_Texture* sdl_texture = (SDL_Texture*)(intptr_t)tex->TexID)
SDL_DestroyTexture(sdl_texture);
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
tex->SetTexID(ImTextureID_Invalid);
@@ -307,6 +284,46 @@ void ImGui_ImplSDLRenderer3_DestroyDeviceObjects()
}
}
bool ImGui_ImplSDLRenderer3_Init(SDL_Renderer* renderer)
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
IM_ASSERT(renderer != nullptr && "SDL_Renderer not initialized!");
// Setup backend capabilities flags
ImGui_ImplSDLRenderer3_Data* bd = IM_NEW(ImGui_ImplSDLRenderer3_Data)();
io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_sdlrenderer3";
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.
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.DrawCallback_ResetRenderState = ImGui_ImplSDLRenderer3_DrawCallback_ResetRenderState;
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerLinear;
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerNearest;
bd->Renderer = renderer;
return true;
}
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);
}
//-----------------------------------------------------------------------------
#if defined(__clang__)
+1 -1
View File
@@ -15,7 +15,7 @@
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// 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.
// Learn about Dear ImGui:
// - FAQ https://dearimgui.com/faq
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+11
View File
@@ -0,0 +1,11 @@
#pragma once
#include "imgui.h"
#include <SDL3/SDL.h>
IMGUI_API bool ImGui_ImplSDLSurface3_Init(SDL_Surface* surface);
IMGUI_API void ImGui_ImplSDLSurface3_Shutdown();
IMGUI_API void ImGui_ImplSDLSurface3_NewFrame();
IMGUI_API void ImGui_ImplSDLSurface3_RenderDrawData(ImDrawData* draw_data);
IMGUI_API SDL_Surface* ImGui_ImplSDLSurface3_CreateFontAtlasSurface();
+190 -108
View File
@@ -2,7 +2,7 @@
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
// Implemented features:
// [!] Renderer: User texture binding. Use 'VkDescriptorSet' as texture identifier. Call ImGui_ImplVulkan_AddTexture() to register one. Read the FAQ about ImTextureID/ImTextureRef + https://github.com/ocornut/imgui/pull/914 for discussions.
// [!] Renderer: User texture binding. Use a VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE 'VkDescriptorSet' as texture identifier. Call ImGui_ImplVulkan_AddTexture() to register one. Read the FAQ about ImTextureID/ImTextureRef + https://github.com/ocornut/imgui/pull/914 for discussions.
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
@@ -27,6 +27,16 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
// 2026-04-22: *BREAKING CHANGE* redesigned to use separate ImageView + Sampler instead of Combined Image Sampler. This change allows us to facilitate changing samplers, in line with other backends.
// - When registering custom textures: changed ImGui_ImplVulkan_AddTexture() signature to remove Sampler.
// - Before: ImGui_ImplVulkan_AddTexture(VkSampler, VkImageView, VkImageLayout)
// - After: ImGui_ImplVulkan_AddTexture(VkImageView, VkImageLayout)
// - Kept inline redirection function that ignores the sampler.
// - When creating your own descriptor pool (instead of letting backend creates its own):
// - Before: need at least IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE descriptors of type VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER.
// - After: need at least IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE descriptors of type VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE.
// + IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE descriptors of type VK_DESCRIPTOR_TYPE_SAMPLER.
// 2026-03-11: Vulkan: Added ImGui_ImplVulkan_PipelineInfo::ExtraDynamicStates[] to allow specifying extra dynamic states to add when creating the VkPipeline. (#9211)
// 2025-09-26: [Helpers] *BREAKING CHANGE*: Vulkan: Helper ImGui_ImplVulkanH_DestroyWindow() does not call vkDestroySurfaceKHR(): as surface is created by caller of ImGui_ImplVulkanH_CreateOrResizeWindow(), it is more consistent that we don't destroy it. (#9163)
// 2026-01-05: [Helpers] *BREAKING CHANGE*: Vulkan: Helper for creating render pass uses ImGui_ImplVulkanH_Window::AttachmentDesc to create render pass. Removed ClearEnabled. (#9152)
@@ -266,10 +276,12 @@ struct ImGui_ImplVulkan_Texture
struct ImGui_ImplVulkan_Data
{
ImGui_ImplVulkan_InitInfo VulkanInitInfo;
ImGui_ImplVulkan_RenderState* RenderState; // == ImGui::GetPlatformIO().Renderer_RenderState during rendering.
VkDeviceSize BufferMemoryAlignment;
VkDeviceSize NonCoherentAtomSize;
VkPipelineCreateFlags PipelineCreateFlags;
VkDescriptorSetLayout DescriptorSetLayout;
VkDescriptorSetLayout DescriptorSetLayoutTexture;
VkDescriptorSetLayout DescriptorSetLayoutSampler;
VkPipelineLayout PipelineLayout;
VkPipeline Pipeline; // pipeline for main render pass (created by app)
VkShaderModule ShaderModuleVert;
@@ -278,7 +290,10 @@ struct ImGui_ImplVulkan_Data
ImVector<VkFormat> PipelineRenderingCreateInfoColorAttachmentFormats; // Deep copy of format array
// Texture management
VkSampler TexSamplerLinear;
VkSampler SamplerLinear;
VkSampler SamplerNearest;
VkDescriptorSet SamplerLinearDS;
VkDescriptorSet SamplerNearestDS;
VkCommandPool TexCommandPool;
VkCommandBuffer TexCommandBuffer;
@@ -318,7 +333,7 @@ void main()
*/
static uint32_t __glsl_shader_vert_spv[] =
{
0x07230203,0x00010000,0x00080001,0x0000002e,0x00000000,0x00020011,0x00000001,0x0006000b,
0x07230203,0x00010000,0x0008000b,0x0000002e,0x00000000,0x00020011,0x00000001,0x0006000b,
0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
0x000a000f,0x00000000,0x00000004,0x6e69616d,0x00000000,0x0000000b,0x0000000f,0x00000015,
0x0000001b,0x0000001c,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d,
@@ -331,10 +346,10 @@ static uint32_t __glsl_shader_vert_spv[] =
0x00050006,0x0000001e,0x00000000,0x61635375,0x0000656c,0x00060006,0x0000001e,0x00000001,
0x61725475,0x616c736e,0x00006574,0x00030005,0x00000020,0x00006370,0x00040047,0x0000000b,
0x0000001e,0x00000000,0x00040047,0x0000000f,0x0000001e,0x00000002,0x00040047,0x00000015,
0x0000001e,0x00000001,0x00050048,0x00000019,0x00000000,0x0000000b,0x00000000,0x00030047,
0x00000019,0x00000002,0x00040047,0x0000001c,0x0000001e,0x00000000,0x00050048,0x0000001e,
0x00000000,0x00000023,0x00000000,0x00050048,0x0000001e,0x00000001,0x00000023,0x00000008,
0x00030047,0x0000001e,0x00000002,0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,
0x0000001e,0x00000001,0x00030047,0x00000019,0x00000002,0x00050048,0x00000019,0x00000000,
0x0000000b,0x00000000,0x00040047,0x0000001c,0x0000001e,0x00000000,0x00030047,0x0000001e,
0x00000002,0x00050048,0x0000001e,0x00000000,0x00000023,0x00000000,0x00050048,0x0000001e,
0x00000001,0x00000023,0x00000008,0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,
0x00030016,0x00000006,0x00000020,0x00040017,0x00000007,0x00000006,0x00000004,0x00040017,
0x00000008,0x00000006,0x00000002,0x0004001e,0x00000009,0x00000007,0x00000008,0x00040020,
0x0000000a,0x00000003,0x00000009,0x0004003b,0x0000000a,0x0000000b,0x00000003,0x00040015,
@@ -366,39 +381,44 @@ static uint32_t __glsl_shader_vert_spv[] =
/*
#version 450 core
layout(location = 0) out vec4 fColor;
layout(set=0, binding=0) uniform sampler2D sTexture;
layout(set=0, binding=0) uniform texture2D _Texture;
layout(set=1, binding=0) uniform sampler _Sampler;
layout(location = 0) in struct { vec4 Color; vec2 UV; } In;
void main()
{
fColor = In.Color * texture(sTexture, In.UV.st);
fColor = In.Color * texture(sampler2D(_Texture, _Sampler), In.UV.st);
}
*/
static uint32_t __glsl_shader_frag_spv[] =
{
0x07230203,0x00010000,0x00080001,0x0000001e,0x00000000,0x00020011,0x00000001,0x0006000b,
0x07230203,0x00010000,0x0008000b,0x00000023,0x00000000,0x00020011,0x00000001,0x0006000b,
0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
0x0007000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x00000009,0x0000000d,0x00030010,
0x00000004,0x00000007,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d,
0x00000000,0x00040005,0x00000009,0x6c6f4366,0x0000726f,0x00030005,0x0000000b,0x00000000,
0x00050006,0x0000000b,0x00000000,0x6f6c6f43,0x00000072,0x00040006,0x0000000b,0x00000001,
0x00005655,0x00030005,0x0000000d,0x00006e49,0x00050005,0x00000016,0x78655473,0x65727574,
0x00000000,0x00040047,0x00000009,0x0000001e,0x00000000,0x00040047,0x0000000d,0x0000001e,
0x00000000,0x00040047,0x00000016,0x00000022,0x00000000,0x00040047,0x00000016,0x00000021,
0x00000000,0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,0x00030016,0x00000006,
0x00000020,0x00040017,0x00000007,0x00000006,0x00000004,0x00040020,0x00000008,0x00000003,
0x00000007,0x0004003b,0x00000008,0x00000009,0x00000003,0x00040017,0x0000000a,0x00000006,
0x00000002,0x0004001e,0x0000000b,0x00000007,0x0000000a,0x00040020,0x0000000c,0x00000001,
0x0000000b,0x0004003b,0x0000000c,0x0000000d,0x00000001,0x00040015,0x0000000e,0x00000020,
0x00000001,0x0004002b,0x0000000e,0x0000000f,0x00000000,0x00040020,0x00000010,0x00000001,
0x00000007,0x00090019,0x00000013,0x00000006,0x00000001,0x00000000,0x00000000,0x00000000,
0x00000001,0x00000000,0x0003001b,0x00000014,0x00000013,0x00040020,0x00000015,0x00000000,
0x00000014,0x0004003b,0x00000015,0x00000016,0x00000000,0x0004002b,0x0000000e,0x00000018,
0x00000001,0x00040020,0x00000019,0x00000001,0x0000000a,0x00050036,0x00000002,0x00000004,
0x00000000,0x00000003,0x000200f8,0x00000005,0x00050041,0x00000010,0x00000011,0x0000000d,
0x0000000f,0x0004003d,0x00000007,0x00000012,0x00000011,0x0004003d,0x00000014,0x00000017,
0x00000016,0x00050041,0x00000019,0x0000001a,0x0000000d,0x00000018,0x0004003d,0x0000000a,
0x0000001b,0x0000001a,0x00050057,0x00000007,0x0000001c,0x00000017,0x0000001b,0x00050085,
0x00000007,0x0000001d,0x00000012,0x0000001c,0x0003003e,0x00000009,0x0000001d,0x000100fd,
0x00005655,0x00030005,0x0000000d,0x00006e49,0x00050005,0x00000015,0x7865545f,0x65727574,
0x00000000,0x00050005,0x00000019,0x6d61535f,0x72656c70,0x00000000,0x00040047,0x00000009,
0x0000001e,0x00000000,0x00040047,0x0000000d,0x0000001e,0x00000000,0x00040047,0x00000015,
0x00000021,0x00000000,0x00040047,0x00000015,0x00000022,0x00000000,0x00040047,0x00000019,
0x00000021,0x00000000,0x00040047,0x00000019,0x00000022,0x00000001,0x00020013,0x00000002,
0x00030021,0x00000003,0x00000002,0x00030016,0x00000006,0x00000020,0x00040017,0x00000007,
0x00000006,0x00000004,0x00040020,0x00000008,0x00000003,0x00000007,0x0004003b,0x00000008,
0x00000009,0x00000003,0x00040017,0x0000000a,0x00000006,0x00000002,0x0004001e,0x0000000b,
0x00000007,0x0000000a,0x00040020,0x0000000c,0x00000001,0x0000000b,0x0004003b,0x0000000c,
0x0000000d,0x00000001,0x00040015,0x0000000e,0x00000020,0x00000001,0x0004002b,0x0000000e,
0x0000000f,0x00000000,0x00040020,0x00000010,0x00000001,0x00000007,0x00090019,0x00000013,
0x00000006,0x00000001,0x00000000,0x00000000,0x00000000,0x00000001,0x00000000,0x00040020,
0x00000014,0x00000000,0x00000013,0x0004003b,0x00000014,0x00000015,0x00000000,0x0002001a,
0x00000017,0x00040020,0x00000018,0x00000000,0x00000017,0x0004003b,0x00000018,0x00000019,
0x00000000,0x0003001b,0x0000001b,0x00000013,0x0004002b,0x0000000e,0x0000001d,0x00000001,
0x00040020,0x0000001e,0x00000001,0x0000000a,0x00050036,0x00000002,0x00000004,0x00000000,
0x00000003,0x000200f8,0x00000005,0x00050041,0x00000010,0x00000011,0x0000000d,0x0000000f,
0x0004003d,0x00000007,0x00000012,0x00000011,0x0004003d,0x00000013,0x00000016,0x00000015,
0x0004003d,0x00000017,0x0000001a,0x00000019,0x00050056,0x0000001b,0x0000001c,0x00000016,
0x0000001a,0x00050041,0x0000001e,0x0000001f,0x0000000d,0x0000001d,0x0004003d,0x0000000a,
0x00000020,0x0000001f,0x00050057,0x00000007,0x00000021,0x0000001c,0x00000020,0x00050085,
0x00000007,0x00000022,0x00000012,0x00000021,0x0003003e,0x00000009,0x00000022,0x000100fd,
0x00010038
};
@@ -481,9 +501,7 @@ static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
// Bind pipeline:
{
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
}
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
// Bind Vertex And Index Buffer:
if (draw_data->TotalVtxCount > 0)
@@ -495,31 +513,33 @@ static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline
}
// Setup viewport:
{
VkViewport viewport;
viewport.x = 0;
viewport.y = 0;
viewport.width = (float)fb_width;
viewport.height = (float)fb_height;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
vkCmdSetViewport(command_buffer, 0, 1, &viewport);
}
VkViewport viewport;
viewport.x = 0;
viewport.y = 0;
viewport.width = (float)fb_width;
viewport.height = (float)fb_height;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
vkCmdSetViewport(command_buffer, 0, 1, &viewport);
// Setup scale and translation:
// Our visible imgui space lies from draw_data->DisplayPps (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
{
float scale[2];
scale[0] = 2.0f / draw_data->DisplaySize.x;
scale[1] = 2.0f / draw_data->DisplaySize.y;
float translate[2];
translate[0] = -1.0f - draw_data->DisplayPos.x * scale[0];
translate[1] = -1.0f - draw_data->DisplayPos.y * scale[1];
vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale);
vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate);
}
float constants[4];
constants[0] = 2.0f / draw_data->DisplaySize.x; // Scale
constants[1] = 2.0f / draw_data->DisplaySize.y;
constants[2] = -1.0f - draw_data->DisplayPos.x * constants[0]; // Translate
constants[3] = -1.0f - draw_data->DisplayPos.y * constants[1];
vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(float) * 4, constants);
// Setup sampler
vkCmdBindDescriptorSets(bd->RenderState->CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 1, 1, &bd->SamplerLinearDS, 0, nullptr);
}
// Draw callbacks
static void ImGui_ImplVulkan_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
static void ImGui_ImplVulkan_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); vkCmdBindDescriptorSets(bd->RenderState->CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 1, 1, &bd->SamplerLinearDS, 0, nullptr); }
static void ImGui_ImplVulkan_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); vkCmdBindDescriptorSets(bd->RenderState->CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 1, 1, &bd->SamplerNearestDS, 0, nullptr); }
// Render function
void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline)
{
@@ -591,16 +611,16 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
vkUnmapMemory(v->Device, rb->IndexBufferMemory);
}
// Setup desired Vulkan state
ImGui_ImplVulkan_SetupRenderState(draw_data, pipeline, command_buffer, rb, fb_width, fb_height);
// Setup render state structure (for callbacks and custom texture bindings)
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
ImGui_ImplVulkan_RenderState render_state;
render_state.CommandBuffer = command_buffer;
render_state.Pipeline = pipeline;
render_state.PipelineLayout = bd->PipelineLayout;
platform_io.Renderer_RenderState = &render_state;
platform_io.Renderer_RenderState = bd->RenderState = &render_state;
// Setup desired Vulkan state
ImGui_ImplVulkan_SetupRenderState(draw_data, pipeline, command_buffer, rb, fb_width, fb_height);
// Will project scissor/clipping rectangles into framebuffer space
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
@@ -608,7 +628,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
// Render command lists
// (Because we merged all buffers into a single one, we maintain our own offset into them)
VkDescriptorSet last_desc_set = VK_NULL_HANDLE;
VkDescriptorSet last_image_view = VK_NULL_HANDLE;
int global_vtx_offset = 0;
int global_idx_offset = 0;
for (const ImDrawList* draw_list : draw_data->CmdLists)
@@ -619,12 +639,13 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
if (pcmd->UserCallback != nullptr)
{
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
if (pcmd->UserCallback == ImGui_ImplVulkan_DrawCallback_ResetRenderState)
{
ImGui_ImplVulkan_SetupRenderState(draw_data, pipeline, command_buffer, rb, fb_width, fb_height);
last_image_view = VK_NULL_HANDLE;
}
else
pcmd->UserCallback(draw_list, pcmd);
last_desc_set = VK_NULL_HANDLE;
}
else
{
@@ -635,8 +656,8 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
// Clamp to viewport as vkCmdSetScissor() won't accept values that are off bounds
if (clip_min.x < 0.0f) { clip_min.x = 0.0f; }
if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }
if (clip_max.x > fb_width) { clip_max.x = (float)fb_width; }
if (clip_max.y > fb_height) { clip_max.y = (float)fb_height; }
if (clip_max.x > (float)fb_width) { clip_max.x = (float)fb_width; }
if (clip_max.y > (float)fb_height) { clip_max.y = (float)fb_height; }
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue;
@@ -648,11 +669,11 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
scissor.extent.height = (uint32_t)(clip_max.y - clip_min.y);
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
// Bind DescriptorSet with font or user texture
VkDescriptorSet desc_set = (VkDescriptorSet)pcmd->GetTexID();
if (desc_set != last_desc_set)
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 0, 1, &desc_set, 0, nullptr);
last_desc_set = desc_set;
// Bind DescriptorSets for image view (font or user texture) and samplers
VkDescriptorSet image_view = (VkDescriptorSet)pcmd->GetTexID();
if (image_view != last_image_view)
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 0, 1, &image_view, 0, nullptr);
last_image_view = image_view;
// Draw
vkCmdDrawIndexed(command_buffer, pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
@@ -661,7 +682,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
global_idx_offset += draw_list->IdxBuffer.Size;
global_vtx_offset += draw_list->VtxBuffer.Size;
}
platform_io.Renderer_RenderState = nullptr;
platform_io.Renderer_RenderState = bd->RenderState = nullptr;
// Note: at this point both vkCmdSetViewport() and vkCmdSetScissor() have been called.
// Our last values will leak into user/application rendering IF:
@@ -755,7 +776,7 @@ void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex)
}
// Create the Descriptor Set
backend_tex->DescriptorSet = ImGui_ImplVulkan_AddTexture(bd->TexSamplerLinear, backend_tex->ImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
backend_tex->DescriptorSet = ImGui_ImplVulkan_AddTexture(backend_tex->ImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
// Store identifiers
tex->SetTexID((ImTextureID)backend_tex->DescriptorSet);
@@ -1050,15 +1071,83 @@ static VkPipeline ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAlloc
return pipeline;
}
static void ImGui_ImplVulkan_CreateDescriptorSetLayout(VkDescriptorSetLayout* p_layout, VkDescriptorType descriptor_type)
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
VkDescriptorSetLayoutBinding binding[1] = {};
binding[0].descriptorType = descriptor_type;
binding[0].descriptorCount = 1;
binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
VkDescriptorSetLayoutCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
info.bindingCount = 1;
info.pBindings = binding;
VkResult err = vkCreateDescriptorSetLayout(v->Device, &info, v->Allocator, p_layout);
check_vk_result(err);
}
static VkDescriptorSet ImGui_ImplVulkan_CreateSamplerDS(VkSampler sampler)
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
VkDescriptorSet descriptor_set;
VkDescriptorSetAllocateInfo alloc_info = {};
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
alloc_info.descriptorPool = bd->DescriptorPool ? bd->DescriptorPool : v->DescriptorPool;
alloc_info.descriptorSetCount = 1;
alloc_info.pSetLayouts = &bd->DescriptorSetLayoutSampler;
VkResult err = vkAllocateDescriptorSets(v->Device, &alloc_info, &descriptor_set);
check_vk_result(err);
VkDescriptorImageInfo desc_image = {};
desc_image.sampler = sampler;
VkWriteDescriptorSet sampler_write_desc = {};
sampler_write_desc.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
sampler_write_desc.dstSet = descriptor_set;
sampler_write_desc.descriptorCount = 1;
sampler_write_desc.dstBinding = 0;
sampler_write_desc.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
sampler_write_desc.pImageInfo = &desc_image;
vkUpdateDescriptorSets(v->Device, 1, &sampler_write_desc, 0, nullptr);
return descriptor_set;
}
bool ImGui_ImplVulkan_CreateDeviceObjects()
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
VkResult err;
if (!bd->TexSamplerLinear)
if (!bd->DescriptorSetLayoutTexture)
ImGui_ImplVulkan_CreateDescriptorSetLayout(&bd->DescriptorSetLayoutTexture, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
if (!bd->DescriptorSetLayoutSampler)
ImGui_ImplVulkan_CreateDescriptorSetLayout(&bd->DescriptorSetLayoutSampler, VK_DESCRIPTOR_TYPE_SAMPLER);
if (v->DescriptorPoolSize != 0)
{
IM_ASSERT(v->DescriptorPoolSize >= IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE);
VkDescriptorPoolSize pool_sizes[] =
{
{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, v->DescriptorPoolSize },
{ VK_DESCRIPTOR_TYPE_SAMPLER, IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE },
};
VkDescriptorPoolCreateInfo pool_info = {};
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
pool_info.maxSets = v->DescriptorPoolSize + IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE;
pool_info.poolSizeCount = (uint32_t)IM_COUNTOF(pool_sizes);
pool_info.pPoolSizes = pool_sizes;
err = vkCreateDescriptorPool(v->Device, &pool_info, v->Allocator, &bd->DescriptorPool);
check_vk_result(err);
}
// Create samplers
// Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
if (!bd->SamplerLinear || !bd->SamplerNearest)
{
// Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
VkSamplerCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
info.magFilter = VK_FILTER_LINEAR;
@@ -1070,37 +1159,16 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
info.minLod = -1000;
info.maxLod = 1000;
info.maxAnisotropy = 1.0f;
err = vkCreateSampler(v->Device, &info, v->Allocator, &bd->TexSamplerLinear);
err = vkCreateSampler(v->Device, &info, v->Allocator, &bd->SamplerLinear);
check_vk_result(err);
}
bd->SamplerLinearDS = ImGui_ImplVulkan_CreateSamplerDS(bd->SamplerLinear);
if (!bd->DescriptorSetLayout)
{
VkDescriptorSetLayoutBinding binding[1] = {};
binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
binding[0].descriptorCount = 1;
binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
VkDescriptorSetLayoutCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
info.bindingCount = 1;
info.pBindings = binding;
err = vkCreateDescriptorSetLayout(v->Device, &info, v->Allocator, &bd->DescriptorSetLayout);
check_vk_result(err);
}
if (v->DescriptorPoolSize != 0)
{
IM_ASSERT(v->DescriptorPoolSize >= IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE);
VkDescriptorPoolSize pool_size = { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, v->DescriptorPoolSize };
VkDescriptorPoolCreateInfo pool_info = {};
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
pool_info.maxSets = v->DescriptorPoolSize;
pool_info.poolSizeCount = 1;
pool_info.pPoolSizes = &pool_size;
err = vkCreateDescriptorPool(v->Device, &pool_info, v->Allocator, &bd->DescriptorPool);
info.magFilter = VK_FILTER_NEAREST;
info.minFilter = VK_FILTER_NEAREST;
info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
err = vkCreateSampler(v->Device, &info, v->Allocator, &bd->SamplerNearest);
check_vk_result(err);
bd->SamplerNearestDS = ImGui_ImplVulkan_CreateSamplerDS(bd->SamplerNearest);
}
if (!bd->PipelineLayout)
@@ -1110,10 +1178,10 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
push_constants[0].offset = sizeof(float) * 0;
push_constants[0].size = sizeof(float) * 4;
VkDescriptorSetLayout set_layout[1] = { bd->DescriptorSetLayout };
VkDescriptorSetLayout set_layout[2] = { bd->DescriptorSetLayoutTexture, bd->DescriptorSetLayoutSampler };
VkPipelineLayoutCreateInfo layout_info = {};
layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
layout_info.setLayoutCount = 1;
layout_info.setLayoutCount = 2;
layout_info.pSetLayouts = set_layout;
layout_info.pushConstantRangeCount = 1;
layout_info.pPushConstantRanges = push_constants;
@@ -1193,10 +1261,12 @@ void ImGui_ImplVulkan_DestroyDeviceObjects()
if (bd->TexCommandBuffer) { vkFreeCommandBuffers(v->Device, bd->TexCommandPool, 1, &bd->TexCommandBuffer); bd->TexCommandBuffer = VK_NULL_HANDLE; }
if (bd->TexCommandPool) { vkDestroyCommandPool(v->Device, bd->TexCommandPool, v->Allocator); bd->TexCommandPool = VK_NULL_HANDLE; }
if (bd->TexSamplerLinear) { vkDestroySampler(v->Device, bd->TexSamplerLinear, v->Allocator); bd->TexSamplerLinear = VK_NULL_HANDLE; }
if (bd->SamplerLinear) { vkDestroySampler(v->Device, bd->SamplerLinear, v->Allocator); bd->SamplerLinear = VK_NULL_HANDLE; }
if (bd->SamplerNearest) { vkDestroySampler(v->Device, bd->SamplerNearest, v->Allocator); bd->SamplerNearest = VK_NULL_HANDLE; }
if (bd->ShaderModuleVert) { vkDestroyShaderModule(v->Device, bd->ShaderModuleVert, v->Allocator); bd->ShaderModuleVert = VK_NULL_HANDLE; }
if (bd->ShaderModuleFrag) { vkDestroyShaderModule(v->Device, bd->ShaderModuleFrag, v->Allocator); bd->ShaderModuleFrag = VK_NULL_HANDLE; }
if (bd->DescriptorSetLayout) { vkDestroyDescriptorSetLayout(v->Device, bd->DescriptorSetLayout, v->Allocator); bd->DescriptorSetLayout = VK_NULL_HANDLE; }
if (bd->DescriptorSetLayoutTexture) { vkDestroyDescriptorSetLayout(v->Device, bd->DescriptorSetLayoutTexture, v->Allocator); bd->DescriptorSetLayoutTexture = VK_NULL_HANDLE; }
if (bd->DescriptorSetLayoutSampler) { vkDestroyDescriptorSetLayout(v->Device, bd->DescriptorSetLayoutSampler, v->Allocator); bd->DescriptorSetLayoutSampler = VK_NULL_HANDLE; }
if (bd->PipelineLayout) { vkDestroyPipelineLayout(v->Device, bd->PipelineLayout, v->Allocator); bd->PipelineLayout = VK_NULL_HANDLE; }
if (bd->Pipeline) { vkDestroyPipeline(v->Device, bd->Pipeline, v->Allocator); bd->Pipeline = VK_NULL_HANDLE; }
if (bd->DescriptorPool) { vkDestroyDescriptorPool(v->Device, bd->DescriptorPool, v->Allocator); bd->DescriptorPool = VK_NULL_HANDLE; }
@@ -1292,6 +1362,11 @@ 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.
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.DrawCallback_ResetRenderState = ImGui_ImplVulkan_DrawCallback_ResetRenderState;
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplVulkan_DrawCallback_SetSamplerLinear;
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplVulkan_DrawCallback_SetSamplerNearest;
// Sanity checks
IM_ASSERT(info->Instance != VK_NULL_HANDLE);
IM_ASSERT(info->PhysicalDevice != VK_NULL_HANDLE);
@@ -1357,7 +1432,7 @@ void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count)
// Register a texture by creating a descriptor
// FIXME: This is experimental in the sense that we are unsure how to best design/tackle this problem, please post to https://github.com/ocornut/imgui/pull/914 if you have suggestions.
VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView image_view, VkImageLayout image_layout)
VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkImageView image_view, VkImageLayout image_layout)
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
@@ -1370,28 +1445,36 @@ VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView image
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
alloc_info.descriptorPool = pool;
alloc_info.descriptorSetCount = 1;
alloc_info.pSetLayouts = &bd->DescriptorSetLayout;
alloc_info.pSetLayouts = &bd->DescriptorSetLayoutTexture;
VkResult err = vkAllocateDescriptorSets(v->Device, &alloc_info, &descriptor_set);
check_vk_result(err);
}
// Update the Descriptor Set:
if (descriptor_set != VK_NULL_HANDLE)
{
VkDescriptorImageInfo desc_image[1] = {};
desc_image[0].sampler = sampler;
desc_image[0].imageView = image_view;
desc_image[0].imageLayout = image_layout;
VkWriteDescriptorSet write_desc[1] = {};
write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
write_desc[0].dstSet = descriptor_set;
write_desc[0].descriptorCount = 1;
write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
write_desc[0].pImageInfo = desc_image;
vkUpdateDescriptorSets(v->Device, 1, write_desc, 0, nullptr);
}
return descriptor_set;
}
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView image_view, VkImageLayout image_layout)
{
IM_UNUSED(sampler);
return ImGui_ImplVulkan_AddTexture(image_view, image_layout);
}
#endif
void ImGui_ImplVulkan_RemoveTexture(VkDescriptorSet descriptor_set)
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
@@ -1792,7 +1875,6 @@ void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevic
VkCommandPoolCreateInfo pool_info = {};
pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
pool_info.queueFamilyIndex = queue_family;
pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
VkResult err = vkCreateCommandPool(device, &pool_info, allocator, &command_pool);
check_vk_result(err);
+11 -8
View File
@@ -2,7 +2,7 @@
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
// Implemented features:
// [!] Renderer: User texture binding. Use 'VkDescriptorSet' as texture identifier. Call ImGui_ImplVulkan_AddTexture() to register one. Read the FAQ about ImTextureID/ImTextureRef + https://github.com/ocornut/imgui/pull/914 for discussions.
// [!] Renderer: User texture binding. Use a VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE 'VkDescriptorSet' as texture identifier. Call ImGui_ImplVulkan_AddTexture() to register one. Read the FAQ about ImTextureID/ImTextureRef + https://github.com/ocornut/imgui/pull/914 for discussions.
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
@@ -78,7 +78,8 @@
#endif
// 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
#define IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE (8) // Minimum per atlas
#define IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE (2) // Minimum for linear + nearest
// Specify settings to create pipeline and swapchain
struct ImGui_ImplVulkan_PipelineInfo
@@ -109,7 +110,7 @@ struct ImGui_ImplVulkan_InitInfo
uint32_t QueueFamily;
VkQueue Queue;
VkDescriptorPool DescriptorPool; // See requirements in note above; ignored if using DescriptorPoolSize > 0
uint32_t DescriptorPoolSize; // Optional: set to create internal descriptor pool automatically instead of using DescriptorPool.
uint32_t DescriptorPoolSize; // Optional: set to create internal ImageView descriptor pool automatically instead of using DescriptorPool.
uint32_t MinImageCount; // >= 2
uint32_t ImageCount; // >= MinImageCount
VkPipelineCache PipelineCache; // Optional
@@ -152,12 +153,14 @@ IMGUI_IMPL_API void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
IMGUI_IMPL_API void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex);
// Register a texture (VkDescriptorSet == ImTextureID)
// FIXME: This is experimental in the sense that we are unsure how to best design/tackle this problem
// Please post to https://github.com/ocornut/imgui/pull/914 if you have suggestions.
IMGUI_IMPL_API VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView image_view, VkImageLayout image_layout);
// Register a texture (VkDescriptorSet for a VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE == ImTextureID)
IMGUI_IMPL_API VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkImageView image_view, VkImageLayout image_layout);
IMGUI_IMPL_API void ImGui_ImplVulkan_RemoveTexture(VkDescriptorSet descriptor_set);
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
IMGUI_IMPL_API VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView image_view, VkImageLayout image_layout); // Ignore VkSampler
#endif
// Optional: load Vulkan functions with a custom function loader
// This is only useful with IMGUI_IMPL_VULKAN_NO_PROTOTYPES / VK_NO_PROTOTYPES
IMGUI_IMPL_API bool ImGui_ImplVulkan_LoadFunctions(uint32_t api_version, PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data = nullptr);
@@ -254,7 +257,7 @@ struct ImGui_ImplVulkanH_Window
memset((void*)this, 0, sizeof(*this));
// Parameters to create SwapChain
PresentMode = (VkPresentModeKHR)~0; // Ensure we get an error if user doesn't set this.
PresentMode = VK_PRESENT_MODE_MAX_ENUM_KHR; // Ensure we get an error if user doesn't set this.
// Parameters to create RenderPass
AttachmentDesc.format = VK_FORMAT_UNDEFINED; // Will automatically use wd->SurfaceFormat.format.
+159 -44
View File
@@ -20,6 +20,8 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
// 2026-03-25: Added support for WGVK native backend via IMGUI_IMPL_WEBGPU_BACKEND_WGVK define, with SPIRV shaders if WGSL is not available. (#9316, #9246, #9257)
// 2026-03-09: Removed support for Emscripten < 4.0.10. (#9281)
// 2025-10-16: Update to compile with Dawn and Emscripten's 4.0.10+ '--use-port=emdawnwebgpu' ports. (#8381, #8898)
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
@@ -56,14 +58,14 @@
#include <stdio.h>
// One of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be provided. See imgui_impl_wgpu.h for more details.
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) == defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#error Exactly one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be defined!
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) && !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) && !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
#error Exactly one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN, IMGUI_IMPL_WEBGPU_BACKEND_WGPU or IMGUI_IMPL_WEBGPU_BACKEND_WGVK must be defined!
#endif
#if defined(__EMSCRIPTEN__) && defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#error Emscripten <4.0.10 with '-sUSE_WEBGPU=1' is not supported anymore.
#endif
#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN
#if defined IMGUI_IMPL_WEBGPU_BACKEND_DAWN || defined IMGUI_IMPL_WEBGPU_BACKEND_WGVK
// Dawn renamed WGPUProgrammableStageDescriptor to WGPUComputeState (see: https://github.com/webgpu-native/webgpu-headers/pull/413)
// Using type alias until WGPU adopts the same naming convention (#8369)
using WGPUProgrammableStageDescriptor = WGPUComputeState;
@@ -82,11 +84,13 @@ struct ImGui_ImplWGPU_Texture
struct RenderResources
{
WGPUSampler Sampler = nullptr; // Sampler for textures
WGPUBuffer Uniforms = nullptr; // Shader uniforms
WGPUBindGroup CommonBindGroup = nullptr; // Resources bind-group to bind the common resources to pipeline
ImGuiStorage ImageBindGroups; // Resources bind-group to bind the font/image resources to pipeline (this is a key->value map)
WGPUBindGroupLayout ImageBindGroupLayout = nullptr; // Cache layout used for the image bind group. Avoids allocating unnecessary JS objects when working with WebASM
WGPUSampler SamplerLinear = nullptr; // Bilinear sampler
WGPUSampler SamplerNearest = nullptr; // Nearest/point sampler
WGPUBuffer Uniforms = nullptr; // Shader uniforms
WGPUBindGroup CommonBindGroupLinear = nullptr; // Common bind-group bound to group 0 (uniforms + SamplerLinear)
WGPUBindGroup CommonBindGroupNearest = nullptr; // Common bind-group bound to group 0 (uniforms + SamplerNearest)
ImGuiStorage ImageBindGroups; // Resources bind-group to bind the font/image resources to pipeline (this is a key->value map)
WGPUBindGroupLayout ImageBindGroupLayout = nullptr; // Cache layout used for the image bind group. Avoids allocating unnecessary JS objects when working with WebASM
};
struct FrameResources
@@ -113,6 +117,7 @@ struct ImGui_ImplWGPU_Data
WGPUTextureFormat renderTargetFormat = WGPUTextureFormat_Undefined;
WGPUTextureFormat depthStencilFormat = WGPUTextureFormat_Undefined;
WGPURenderPipeline pipelineState = nullptr;
ImGui_ImplWGPU_RenderState* RenderState = nullptr; // == ImGui::GetPlatformIO().Renderer_RenderState during rendering.
RenderResources renderResources;
FrameResources* pFrameResources = nullptr;
@@ -185,6 +190,60 @@ fn main(in: VertexOutput) -> @location(0) vec4<f32> {
}
)";
// Same shader as __shader_vert_wgsl[] but compiled as SPIRV.
// 'wgslc -o vert.spv vert.wgsl' + 'binary_to_compressed_c -u8 -nocompress vert.spv'
static const unsigned char __shader_vert_spirv[1996] =
{
3,2,35,7,0,3,1,0,1,0,23,0,90,0,0,0,0,0,0,0,17,0,2,0,1,0,0,0,14,0,3,0,0,0,0,0,1,0,0,0,15,0,12,0,0,0,0,0,78,0,0,0,109,97,105,110,0,0,0,0,8,0,0,0,12,0,0,0,13,0,0,0,16,0,0,0,18,0,0,0,19,
0,0,0,21,0,0,0,71,0,4,0,4,0,0,0,6,0,0,0,16,0,0,0,72,0,5,0,3,0,0,0,0,0,0,0,35,0,0,0,0,0,0,0,71,0,3,0,3,0,0,0,2,0,0,0,71,0,4,0,1,0,0,0,34,0,0,0,0,0,0,0,71,0,4,0,1,0,0,0,33,0,0,0,0,0,
0,0,71,0,3,0,1,0,0,0,24,0,0,0,71,0,4,0,8,0,0,0,30,0,0,0,0,0,0,0,71,0,4,0,12,0,0,0,30,0,0,0,1,0,0,0,71,0,4,0,13,0,0,0,30,0,0,0,2,0,0,0,71,0,4,0,16,0,0,0,11,0,0,0,0,0,0,0,71,0,4,0,18,
0,0,0,30,0,0,0,0,0,0,0,71,0,4,0,19,0,0,0,30,0,0,0,1,0,0,0,71,0,4,0,21,0,0,0,11,0,0,0,1,0,0,0,21,0,4,0,6,0,0,0,32,0,0,0,0,0,0,0,23,0,4,0,5,0,0,0,6,0,0,0,4,0,0,0,43,0,4,0,6,0,0,0,7,0,
0,0,5,0,0,0,28,0,4,0,4,0,0,0,5,0,0,0,7,0,0,0,30,0,3,0,3,0,0,0,4,0,0,0,32,0,4,0,2,0,0,0,2,0,0,0,3,0,0,0,59,0,4,0,2,0,0,0,1,0,0,0,2,0,0,0,22,0,3,0,11,0,0,0,32,0,0,0,23,0,4,0,10,0,0,0,
11,0,0,0,2,0,0,0,32,0,4,0,9,0,0,0,1,0,0,0,10,0,0,0,59,0,4,0,9,0,0,0,8,0,0,0,1,0,0,0,59,0,4,0,9,0,0,0,12,0,0,0,1,0,0,0,23,0,4,0,15,0,0,0,11,0,0,0,4,0,0,0,32,0,4,0,14,0,0,0,1,0,0,0,15,
0,0,0,59,0,4,0,14,0,0,0,13,0,0,0,1,0,0,0,32,0,4,0,17,0,0,0,3,0,0,0,15,0,0,0,59,0,4,0,17,0,0,0,16,0,0,0,3,0,0,0,59,0,4,0,17,0,0,0,18,0,0,0,3,0,0,0,32,0,4,0,20,0,0,0,3,0,0,0,10,0,0,0,
59,0,4,0,20,0,0,0,19,0,0,0,3,0,0,0,32,0,4,0,22,0,0,0,3,0,0,0,11,0,0,0,59,0,4,0,22,0,0,0,21,0,0,0,3,0,0,0,30,0,5,0,24,0,0,0,15,0,0,0,15,0,0,0,10,0,0,0,30,0,5,0,25,0,0,0,10,0,0,0,10,
0,0,0,15,0,0,0,33,0,4,0,27,0,0,0,24,0,0,0,25,0,0,0,32,0,4,0,30,0,0,0,7,0,0,0,24,0,0,0,46,0,3,0,24,0,0,0,31,0,0,0,32,0,4,0,33,0,0,0,7,0,0,0,15,0,0,0,43,0,4,0,6,0,0,0,34,0,0,0,0,0,0,
0,24,0,4,0,36,0,0,0,15,0,0,0,4,0,0,0,43,0,4,0,11,0,0,0,40,0,0,0,0,0,0,0,43,0,4,0,11,0,0,0,41,0,0,0,0,0,128,63,43,0,4,0,6,0,0,0,44,0,0,0,1,0,0,0,32,0,4,0,47,0,0,0,7,0,0,0,10,0,0,0,43,
0,4,0,6,0,0,0,48,0,0,0,2,0,0,0,33,0,4,0,52,0,0,0,36,0,0,0,6,0,0,0,43,0,4,0,6,0,0,0,55,0,0,0,16,0,0,0,32,0,4,0,57,0,0,0,2,0,0,0,5,0,0,0,43,0,4,0,6,0,0,0,66,0,0,0,32,0,0,0,43,0,4,0,6,
0,0,0,72,0,0,0,48,0,0,0,19,0,2,0,79,0,0,0,33,0,3,0,80,0,0,0,79,0,0,0,54,0,5,0,24,0,0,0,23,0,0,0,0,0,0,0,27,0,0,0,55,0,3,0,25,0,0,0,26,0,0,0,248,0,2,0,28,0,0,0,59,0,5,0,30,0,0,0,29,
0,0,0,7,0,0,0,31,0,0,0,65,0,5,0,33,0,0,0,32,0,0,0,29,0,0,0,34,0,0,0,57,0,5,0,36,0,0,0,35,0,0,0,37,0,0,0,34,0,0,0,81,0,5,0,10,0,0,0,38,0,0,0,26,0,0,0,0,0,0,0,80,0,6,0,15,0,0,0,39,0,
0,0,38,0,0,0,40,0,0,0,41,0,0,0,145,0,5,0,15,0,0,0,42,0,0,0,35,0,0,0,39,0,0,0,62,0,4,0,32,0,0,0,42,0,0,0,0,0,0,0,65,0,5,0,33,0,0,0,43,0,0,0,29,0,0,0,44,0,0,0,81,0,5,0,15,0,0,0,45,0,
0,0,26,0,0,0,2,0,0,0,62,0,4,0,43,0,0,0,45,0,0,0,0,0,0,0,65,0,5,0,47,0,0,0,46,0,0,0,29,0,0,0,48,0,0,0,81,0,5,0,10,0,0,0,49,0,0,0,26,0,0,0,1,0,0,0,62,0,4,0,46,0,0,0,49,0,0,0,0,0,0,0,
61,0,5,0,24,0,0,0,50,0,0,0,29,0,0,0,0,0,0,0,254,0,2,0,50,0,0,0,56,0,1,0,54,0,5,0,36,0,0,0,37,0,0,0,0,0,0,0,52,0,0,0,55,0,3,0,6,0,0,0,51,0,0,0,248,0,2,0,53,0,0,0,134,0,5,0,6,0,0,0,54,
0,0,0,51,0,0,0,55,0,0,0,65,0,6,0,57,0,0,0,56,0,0,0,1,0,0,0,34,0,0,0,54,0,0,0,61,0,5,0,5,0,0,0,58,0,0,0,56,0,0,0,0,0,0,0,124,0,4,0,15,0,0,0,59,0,0,0,58,0,0,0,128,0,5,0,6,0,0,0,60,0,
0,0,55,0,0,0,51,0,0,0,134,0,5,0,6,0,0,0,61,0,0,0,60,0,0,0,55,0,0,0,65,0,6,0,57,0,0,0,62,0,0,0,1,0,0,0,34,0,0,0,61,0,0,0,61,0,5,0,5,0,0,0,63,0,0,0,62,0,0,0,0,0,0,0,124,0,4,0,15,0,0,
0,64,0,0,0,63,0,0,0,128,0,5,0,6,0,0,0,65,0,0,0,66,0,0,0,51,0,0,0,134,0,5,0,6,0,0,0,67,0,0,0,65,0,0,0,55,0,0,0,65,0,6,0,57,0,0,0,68,0,0,0,1,0,0,0,34,0,0,0,67,0,0,0,61,0,5,0,5,0,0,0,
69,0,0,0,68,0,0,0,0,0,0,0,124,0,4,0,15,0,0,0,70,0,0,0,69,0,0,0,128,0,5,0,6,0,0,0,71,0,0,0,72,0,0,0,51,0,0,0,134,0,5,0,6,0,0,0,73,0,0,0,71,0,0,0,55,0,0,0,65,0,6,0,57,0,0,0,74,0,0,0,
1,0,0,0,34,0,0,0,73,0,0,0,61,0,5,0,5,0,0,0,75,0,0,0,74,0,0,0,0,0,0,0,124,0,4,0,15,0,0,0,76,0,0,0,75,0,0,0,80,0,7,0,36,0,0,0,77,0,0,0,59,0,0,0,64,0,0,0,70,0,0,0,76,0,0,0,254,0,2,0,77,
0,0,0,56,0,1,0,54,0,5,0,79,0,0,0,78,0,0,0,0,0,0,0,80,0,0,0,248,0,2,0,81,0,0,0,61,0,5,0,10,0,0,0,82,0,0,0,8,0,0,0,0,0,0,0,61,0,5,0,10,0,0,0,83,0,0,0,12,0,0,0,0,0,0,0,61,0,5,0,15,0,0,
0,84,0,0,0,13,0,0,0,0,0,0,0,80,0,6,0,25,0,0,0,85,0,0,0,82,0,0,0,83,0,0,0,84,0,0,0,57,0,5,0,24,0,0,0,86,0,0,0,23,0,0,0,85,0,0,0,81,0,5,0,15,0,0,0,87,0,0,0,86,0,0,0,0,0,0,0,62,0,4,0,
16,0,0,0,87,0,0,0,0,0,0,0,81,0,5,0,15,0,0,0,88,0,0,0,86,0,0,0,1,0,0,0,62,0,4,0,18,0,0,0,88,0,0,0,0,0,0,0,81,0,5,0,10,0,0,0,89,0,0,0,86,0,0,0,2,0,0,0,62,0,4,0,19,0,0,0,89,0,0,0,0,0,
0,0,62,0,4,0,21,0,0,0,41,0,0,0,0,0,0,0,253,0,1,0,56,0,1,0,
};
// Same shader as __shader_frag_wgsl[] but compiled as SPIRV.
// 'wgslc -o frag.spv frag.wgsl' + 'binary_to_compressed_c -u8 -nocompress frag.spv'
static const unsigned char __shader_frag_spirv[1392] =
{
3,2,35,7,0,3,1,0,1,0,23,0,60,0,0,0,0,0,0,0,17,0,2,0,1,0,0,0,11,0,6,0,48,0,0,0,71,76,83,76,46,115,116,100,46,52,53,48,0,0,0,0,14,0,3,0,0,0,0,0,1,0,0,0,15,0,9,0,4,0,0,0,51,0,0,0,109,
97,105,110,0,0,0,0,15,0,0,0,18,0,0,0,19,0,0,0,22,0,0,0,16,0,3,0,51,0,0,0,7,0,0,0,71,0,4,0,4,0,0,0,6,0,0,0,16,0,0,0,72,0,5,0,3,0,0,0,0,0,0,0,35,0,0,0,0,0,0,0,71,0,3,0,3,0,0,0,2,0,0,
0,71,0,4,0,1,0,0,0,34,0,0,0,0,0,0,0,71,0,4,0,1,0,0,0,33,0,0,0,0,0,0,0,71,0,3,0,1,0,0,0,24,0,0,0,71,0,4,0,8,0,0,0,34,0,0,0,0,0,0,0,71,0,4,0,8,0,0,0,33,0,0,0,1,0,0,0,71,0,4,0,11,0,0,
0,34,0,0,0,1,0,0,0,71,0,4,0,11,0,0,0,33,0,0,0,0,0,0,0,71,0,4,0,15,0,0,0,11,0,0,0,15,0,0,0,71,0,4,0,18,0,0,0,30,0,0,0,0,0,0,0,71,0,4,0,19,0,0,0,30,0,0,0,1,0,0,0,71,0,4,0,22,0,0,0,30,
0,0,0,0,0,0,0,21,0,4,0,6,0,0,0,32,0,0,0,0,0,0,0,23,0,4,0,5,0,0,0,6,0,0,0,4,0,0,0,43,0,4,0,6,0,0,0,7,0,0,0,5,0,0,0,28,0,4,0,4,0,0,0,5,0,0,0,7,0,0,0,30,0,3,0,3,0,0,0,4,0,0,0,32,0,4,0,
2,0,0,0,2,0,0,0,3,0,0,0,59,0,4,0,2,0,0,0,1,0,0,0,2,0,0,0,26,0,2,0,10,0,0,0,32,0,4,0,9,0,0,0,0,0,0,0,10,0,0,0,59,0,4,0,9,0,0,0,8,0,0,0,0,0,0,0,22,0,3,0,14,0,0,0,32,0,0,0,25,0,9,0,13,
0,0,0,14,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,32,0,4,0,12,0,0,0,0,0,0,0,13,0,0,0,59,0,4,0,12,0,0,0,11,0,0,0,0,0,0,0,23,0,4,0,17,0,0,0,14,0,0,0,4,0,0,0,32,0,4,0,16,
0,0,0,1,0,0,0,17,0,0,0,59,0,4,0,16,0,0,0,15,0,0,0,1,0,0,0,59,0,4,0,16,0,0,0,18,0,0,0,1,0,0,0,23,0,4,0,21,0,0,0,14,0,0,0,2,0,0,0,32,0,4,0,20,0,0,0,1,0,0,0,21,0,0,0,59,0,4,0,20,0,0,0,
19,0,0,0,1,0,0,0,32,0,4,0,23,0,0,0,3,0,0,0,17,0,0,0,59,0,4,0,23,0,0,0,22,0,0,0,3,0,0,0,30,0,5,0,25,0,0,0,17,0,0,0,17,0,0,0,21,0,0,0,33,0,4,0,27,0,0,0,17,0,0,0,25,0,0,0,27,0,3,0,34,
0,0,0,13,0,0,0,23,0,4,0,38,0,0,0,14,0,0,0,3,0,0,0,32,0,4,0,40,0,0,0,2,0,0,0,5,0,0,0,43,0,4,0,6,0,0,0,41,0,0,0,0,0,0,0,43,0,4,0,6,0,0,0,42,0,0,0,4,0,0,0,19,0,2,0,52,0,0,0,33,0,3,0,53,
0,0,0,52,0,0,0,54,0,5,0,17,0,0,0,24,0,0,0,0,0,0,0,27,0,0,0,55,0,3,0,25,0,0,0,26,0,0,0,248,0,2,0,28,0,0,0,81,0,5,0,17,0,0,0,29,0,0,0,26,0,0,0,1,0,0,0,61,0,5,0,13,0,0,0,30,0,0,0,11,0,
0,0,0,0,0,0,61,0,5,0,10,0,0,0,31,0,0,0,8,0,0,0,0,0,0,0,81,0,5,0,21,0,0,0,32,0,0,0,26,0,0,0,2,0,0,0,86,0,5,0,34,0,0,0,33,0,0,0,30,0,0,0,31,0,0,0,87,0,6,0,17,0,0,0,35,0,0,0,33,0,0,0,
32,0,0,0,0,0,0,0,133,0,5,0,17,0,0,0,36,0,0,0,29,0,0,0,35,0,0,0,79,0,8,0,38,0,0,0,37,0,0,0,36,0,0,0,36,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,65,0,6,0,40,0,0,0,39,0,0,0,1,0,0,0,41,0,0,0,42,0,
0,0,61,0,5,0,5,0,0,0,43,0,0,0,39,0,0,0,0,0,0,0,81,0,5,0,6,0,0,0,44,0,0,0,43,0,0,0,0,0,0,0,124,0,4,0,14,0,0,0,45,0,0,0,44,0,0,0,80,0,6,0,38,0,0,0,46,0,0,0,45,0,0,0,45,0,0,0,45,0,0,0,
12,0,7,0,38,0,0,0,47,0,0,0,48,0,0,0,26,0,0,0,37,0,0,0,46,0,0,0,81,0,5,0,14,0,0,0,49,0,0,0,36,0,0,0,3,0,0,0,80,0,5,0,17,0,0,0,50,0,0,0,47,0,0,0,49,0,0,0,254,0,2,0,50,0,0,0,56,0,1,0,
54,0,5,0,52,0,0,0,51,0,0,0,0,0,0,0,53,0,0,0,248,0,2,0,54,0,0,0,61,0,5,0,17,0,0,0,55,0,0,0,15,0,0,0,0,0,0,0,61,0,5,0,17,0,0,0,56,0,0,0,18,0,0,0,0,0,0,0,61,0,5,0,21,0,0,0,57,0,0,0,19,
0,0,0,0,0,0,0,80,0,6,0,25,0,0,0,58,0,0,0,55,0,0,0,56,0,0,0,57,0,0,0,57,0,5,0,17,0,0,0,59,0,0,0,24,0,0,0,58,0,0,0,62,0,4,0,22,0,0,0,59,0,0,0,0,0,0,0,253,0,1,0,56,0,1,0,
};
static void SafeRelease(ImDrawIdx*& res)
{
if (res)
@@ -241,9 +300,11 @@ static void SafeRelease(WGPUShaderModule& res)
}
static void SafeRelease(RenderResources& res)
{
SafeRelease(res.Sampler);
SafeRelease(res.SamplerLinear);
SafeRelease(res.SamplerNearest);
SafeRelease(res.Uniforms);
SafeRelease(res.CommonBindGroup);
SafeRelease(res.CommonBindGroupLinear);
SafeRelease(res.CommonBindGroupNearest);
SafeRelease(res.ImageBindGroupLayout);
};
@@ -255,9 +316,10 @@ static void SafeRelease(FrameResources& res)
SafeRelease(res.VertexBufferHost);
}
static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule(const char* wgsl_source)
static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModuleWGSL(const char* wgsl_source)
{
ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData();
IM_UNUSED(bd);
WGPUShaderSourceWGSL wgsl_desc = {};
wgsl_desc.chain.sType = WGPUSType_ShaderSourceWGSL;
@@ -266,6 +328,46 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule(const c
WGPUShaderModuleDescriptor desc = {};
desc.nextInChain = (WGPUChainedStruct*)&wgsl_desc;
// Detect shader compilation errors by using an error scope.
// Flag to be passed into the validation callback `userdata1` pointer.
int validation_error = 0;
wgpuDevicePushErrorScope(bd->wgpuDevice, WGPUErrorFilter_Validation);
WGPUShaderModule module = wgpuDeviceCreateShaderModule(bd->wgpuDevice, &desc);
WGPUPopErrorScopeCallbackInfo pop_cb = {};
pop_cb.mode = WGPUCallbackMode_AllowSpontaneous;
pop_cb.callback = [](WGPUPopErrorScopeStatus, WGPUErrorType type, WGPUStringView, void* userdata1, void*)
{
if (type == WGPUErrorType_Validation)
*static_cast<int*>(userdata1) = 1;
};
pop_cb.userdata1 = &validation_error;
wgpuDevicePopErrorScope(bd->wgpuDevice, pop_cb);
WGPUProgrammableStageDescriptor stage_desc = {};
if (module && !validation_error)
{
stage_desc.module = module;
stage_desc.entryPoint = { "main", WGPU_STRLEN };
}
else if (module)
{
wgpuShaderModuleRelease(module);
}
return stage_desc;
}
static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModuleSPIRV(const void* spirv_binary, size_t spirv_length)
{
ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData();
WGPUShaderSourceSPIRV spirv_desc = {};
spirv_desc.chain.sType = WGPUSType_ShaderSourceSPIRV;
spirv_desc.code = (const uint32_t *)spirv_binary;
spirv_desc.codeSize = ((uint32_t)(spirv_length / 4));
WGPUShaderModuleDescriptor desc = {};
desc.nextInChain = (WGPUChainedStruct*)&spirv_desc;
WGPUProgrammableStageDescriptor stage_desc = {};
stage_desc.module = wgpuDeviceCreateShaderModule(bd->wgpuDevice, &desc);
@@ -344,15 +446,19 @@ static void ImGui_ImplWGPU_SetupRenderState(ImDrawData* draw_data, WGPURenderPas
wgpuRenderPassEncoderSetVertexBuffer(ctx, 0, fr->VertexBuffer, 0, fr->VertexBufferSize * sizeof(ImDrawVert));
wgpuRenderPassEncoderSetIndexBuffer(ctx, fr->IndexBuffer, sizeof(ImDrawIdx) == 2 ? WGPUIndexFormat_Uint16 : WGPUIndexFormat_Uint32, 0, fr->IndexBufferSize * sizeof(ImDrawIdx));
wgpuRenderPassEncoderSetPipeline(ctx, bd->pipelineState);
wgpuRenderPassEncoderSetBindGroup(ctx, 0, bd->renderResources.CommonBindGroup, 0, nullptr);
wgpuRenderPassEncoderSetBindGroup(ctx, 0, bd->renderResources.CommonBindGroupLinear, 0, nullptr);
// Setup blend factor
WGPUColor blend_color = { 0.f, 0.f, 0.f, 0.f };
wgpuRenderPassEncoderSetBlendConstant(ctx, &blend_color);
}
// Draw callbacks
static void ImGui_ImplWGPU_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
static void ImGui_ImplWGPU_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData(); wgpuRenderPassEncoderSetBindGroup(bd->RenderState->RenderPassEncoder, 0, bd->renderResources.CommonBindGroupLinear, 0, nullptr); }
static void ImGui_ImplWGPU_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData(); wgpuRenderPassEncoderSetBindGroup(bd->RenderState->RenderPassEncoder, 0, bd->renderResources.CommonBindGroupNearest, 0, nullptr); }
// Render function
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder pass_encoder)
{
// Avoid rendering when minimized
@@ -436,8 +542,8 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
}
int64_t vb_write_size = MEMALIGN((char*)vtx_dst - (char*)fr->VertexBufferHost, 4);
int64_t ib_write_size = MEMALIGN((char*)idx_dst - (char*)fr->IndexBufferHost, 4);
wgpuQueueWriteBuffer(bd->defaultQueue, fr->VertexBuffer, 0, fr->VertexBufferHost, vb_write_size);
wgpuQueueWriteBuffer(bd->defaultQueue, fr->IndexBuffer, 0, fr->IndexBufferHost, ib_write_size);
wgpuQueueWriteBuffer(bd->defaultQueue, fr->VertexBuffer, 0, fr->VertexBufferHost, (size_t)vb_write_size);
wgpuQueueWriteBuffer(bd->defaultQueue, fr->IndexBuffer, 0, fr->IndexBufferHost, (size_t)ib_write_size);
// Setup desired render state
ImGui_ImplWGPU_SetupRenderState(draw_data, pass_encoder, fr);
@@ -447,7 +553,7 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
ImGui_ImplWGPU_RenderState render_state;
render_state.Device = bd->wgpuDevice;
render_state.RenderPassEncoder = pass_encoder;
platform_io.Renderer_RenderState = &render_state;
platform_io.Renderer_RenderState = bd->RenderState = &render_state;
// Render command lists
// (Because we merged all buffers into a single one, we maintain our own offset into them)
@@ -463,8 +569,7 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
if (pcmd->UserCallback != nullptr)
{
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
if (pcmd->UserCallback == ImGui_ImplWGPU_DrawCallback_ResetRenderState)
ImGui_ImplWGPU_SetupRenderState(draw_data, pass_encoder, fr);
else
pcmd->UserCallback(draw_list, pcmd);
@@ -475,12 +580,11 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
ImTextureID tex_id = pcmd->GetTexID();
ImGuiID tex_id_hash = ImHashData(&tex_id, sizeof(tex_id), 0);
WGPUBindGroup bind_group = (WGPUBindGroup)bd->renderResources.ImageBindGroups.GetVoidPtr(tex_id_hash);
if (!bind_group)
{
bind_group = ImGui_ImplWGPU_CreateImageBindGroup(bd->renderResources.ImageBindGroupLayout, (WGPUTextureView)tex_id);
bd->renderResources.ImageBindGroups.SetVoidPtr(tex_id_hash, bind_group);
}
wgpuRenderPassEncoderSetBindGroup(pass_encoder, 1, (WGPUBindGroup)bind_group, 0, nullptr);
if (!bind_group && tex_id != 0)
if ((bind_group = ImGui_ImplWGPU_CreateImageBindGroup(bd->renderResources.ImageBindGroupLayout, (WGPUTextureView)tex_id)) != 0)
bd->renderResources.ImageBindGroups.SetVoidPtr(tex_id_hash, bind_group);
if (bind_group)
wgpuRenderPassEncoderSetBindGroup(pass_encoder, 1, (WGPUBindGroup)bind_group, 0, nullptr);
// Project scissor/clipping rectangles into framebuffer space
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
@@ -489,8 +593,8 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
// Clamp to viewport as wgpuRenderPassEncoderSetScissorRect() won't accept values that are off bounds
if (clip_min.x < 0.0f) { clip_min.x = 0.0f; }
if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }
if (clip_max.x > fb_width) { clip_max.x = (float)fb_width; }
if (clip_max.y > fb_height) { clip_max.y = (float)fb_height; }
if (clip_max.x > (float)fb_width) { clip_max.x = (float)fb_width; }
if (clip_max.y > (float)fb_height) { clip_max.y = (float)fb_height; }
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue;
@@ -512,7 +616,7 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
}
image_bind_groups.Data.resize(0);
platform_io.Renderer_RenderState = nullptr;
platform_io.Renderer_RenderState = bd->RenderState = nullptr;
}
static void ImGui_ImplWGPU_DestroyTexture(ImTextureData* tex)
@@ -665,14 +769,15 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
graphics_pipeline_desc.layout = wgpuDeviceCreatePipelineLayout(bd->wgpuDevice, &layout_desc);
// Create the vertex shader
WGPUProgrammableStageDescriptor vertex_shader_desc = ImGui_ImplWGPU_CreateShaderModule(__shader_vert_wgsl);
WGPUProgrammableStageDescriptor vertex_shader_desc = ImGui_ImplWGPU_CreateShaderModuleWGSL(__shader_vert_wgsl);
if (!vertex_shader_desc.module) vertex_shader_desc = ImGui_ImplWGPU_CreateShaderModuleSPIRV(__shader_vert_spirv, sizeof(__shader_vert_spirv));
graphics_pipeline_desc.vertex.module = vertex_shader_desc.module;
graphics_pipeline_desc.vertex.entryPoint = vertex_shader_desc.entryPoint;
// Vertex input configuration
WGPUVertexAttribute attribute_desc[] =
{
#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN
#if defined IMGUI_IMPL_WEBGPU_BACKEND_DAWN || defined IMGUI_IMPL_WEBGPU_BACKEND_WGVK
{ nullptr, WGPUVertexFormat_Float32x2, (uint64_t)offsetof(ImDrawVert, pos), 0 },
{ nullptr, WGPUVertexFormat_Float32x2, (uint64_t)offsetof(ImDrawVert, uv), 1 },
{ nullptr, WGPUVertexFormat_Unorm8x4, (uint64_t)offsetof(ImDrawVert, col), 2 },
@@ -693,7 +798,8 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
graphics_pipeline_desc.vertex.buffers = buffer_layouts;
// Create the pixel shader
WGPUProgrammableStageDescriptor pixel_shader_desc = ImGui_ImplWGPU_CreateShaderModule(__shader_frag_wgsl);
WGPUProgrammableStageDescriptor pixel_shader_desc = ImGui_ImplWGPU_CreateShaderModuleWGSL(__shader_frag_wgsl);
if (!pixel_shader_desc.module) pixel_shader_desc = ImGui_ImplWGPU_CreateShaderModuleSPIRV(__shader_frag_spirv, sizeof(__shader_frag_spirv));
// Create the blending setup
WGPUBlendState blend_state = {};
@@ -738,29 +844,35 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
ImGui_ImplWGPU_CreateUniformBuffer();
// Create sampler
// Create samplers (Linear/Nearest)
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
WGPUSamplerDescriptor sampler_desc = {};
sampler_desc.minFilter = WGPUFilterMode_Linear;
sampler_desc.magFilter = WGPUFilterMode_Linear;
sampler_desc.mipmapFilter = WGPUMipmapFilterMode_Linear;
sampler_desc.addressModeU = WGPUAddressMode_ClampToEdge;
sampler_desc.addressModeV = WGPUAddressMode_ClampToEdge;
sampler_desc.addressModeW = WGPUAddressMode_ClampToEdge;
sampler_desc.maxAnisotropy = 1;
bd->renderResources.Sampler = wgpuDeviceCreateSampler(bd->wgpuDevice, &sampler_desc);
sampler_desc.minFilter = WGPUFilterMode_Linear;
sampler_desc.magFilter = WGPUFilterMode_Linear;
sampler_desc.mipmapFilter = WGPUMipmapFilterMode_Linear;
bd->renderResources.SamplerLinear = wgpuDeviceCreateSampler(bd->wgpuDevice, &sampler_desc);
sampler_desc.minFilter = WGPUFilterMode_Nearest;
sampler_desc.magFilter = WGPUFilterMode_Nearest;
sampler_desc.mipmapFilter = WGPUMipmapFilterMode_Nearest;
bd->renderResources.SamplerNearest = wgpuDeviceCreateSampler(bd->wgpuDevice, &sampler_desc);
// Create resource bind group
// Create resource bind groups (one per sampler, otherwise identical)
WGPUBindGroupEntry common_bg_entries[] =
{
{ nullptr, 0, bd->renderResources.Uniforms, 0, MEMALIGN(sizeof(Uniforms), 16), 0, 0 },
{ nullptr, 1, 0, 0, 0, bd->renderResources.Sampler, 0 },
{ nullptr, 1, 0, 0, 0, bd->renderResources.SamplerLinear, 0 },
};
WGPUBindGroupDescriptor common_bg_descriptor = {};
common_bg_descriptor.layout = bg_layouts[0];
common_bg_descriptor.entryCount = sizeof(common_bg_entries) / sizeof(WGPUBindGroupEntry);
common_bg_descriptor.entries = common_bg_entries;
bd->renderResources.CommonBindGroup = wgpuDeviceCreateBindGroup(bd->wgpuDevice, &common_bg_descriptor);
bd->renderResources.CommonBindGroupLinear = wgpuDeviceCreateBindGroup(bd->wgpuDevice, &common_bg_descriptor);
common_bg_entries[1].sampler = bd->renderResources.SamplerNearest;
bd->renderResources.CommonBindGroupNearest = wgpuDeviceCreateBindGroup(bd->wgpuDevice, &common_bg_descriptor);
bd->renderResources.ImageBindGroupLayout = bg_layouts[1];
SafeRelease(vertex_shader_desc.module);
@@ -806,10 +918,17 @@ bool ImGui_ImplWGPU_Init(ImGui_ImplWGPU_InitInfo* init_info)
#endif
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
io.BackendRendererName = "imgui_impl_wgpu (WGPU, Native)";
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
io.BackendRendererName = "imgui_impl_wgpu (WGVK, Native)";
#endif
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.
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.DrawCallback_ResetRenderState = ImGui_ImplWGPU_DrawCallback_ResetRenderState;
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplWGPU_DrawCallback_SetSamplerLinear;
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplWGPU_DrawCallback_SetSamplerNearest;
bd->initInfo = *init_info;
bd->wgpuDevice = init_info->Device;
bd->defaultQueue = wgpuDeviceGetQueue(bd->wgpuDevice);
@@ -818,11 +937,7 @@ bool ImGui_ImplWGPU_Init(ImGui_ImplWGPU_InitInfo* init_info)
bd->numFramesInFlight = init_info->NumFramesInFlight;
bd->frameIndex = UINT_MAX;
bd->renderResources.Sampler = nullptr;
bd->renderResources.Uniforms = nullptr;
bd->renderResources.CommonBindGroup = nullptr;
bd->renderResources.ImageBindGroups.Data.reserve(100);
bd->renderResources.ImageBindGroupLayout = nullptr;
// Create buffers with a default size (they will later be grown as needed)
bd->pFrameResources = new FrameResources[bd->numFramesInFlight];
@@ -877,7 +992,7 @@ void ImGui_ImplWGPU_NewFrame()
bool ImGui_ImplWGPU_IsSurfaceStatusError(WGPUSurfaceGetCurrentTextureStatus status)
{
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
return (status == WGPUSurfaceGetCurrentTextureStatus_Error);
#else
return (status == WGPUSurfaceGetCurrentTextureStatus_OutOfMemory || status == WGPUSurfaceGetCurrentTextureStatus_DeviceLost);
@@ -894,7 +1009,7 @@ bool ImGui_ImplWGPU_IsSurfaceStatusSubOptimal(WGPUSurfaceGetCurrentTextureStatus
}
// Helpers to obtain a string
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
const char* ImGui_ImplWGPU_GetErrorTypeName(WGPUErrorType type)
{
switch (type)
+2 -1
View File
@@ -3,7 +3,7 @@
// (Please note that WebGPU is a recent API, may not be supported by all browser, and its ecosystem is generally a mess)
// When targeting native platforms:
// - One of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU *must* be provided.
// - One of IMGUI_IMPL_WEBGPU_BACKEND_DAWN, IMGUI_IMPL_WEBGPU_BACKEND_WGPU or IMGUI_IMPL_WEBGPU_BACKEND_WGVK *must* be provided.
// When targeting Emscripten:
// - We now defaults to IMGUI_IMPL_WEBGPU_BACKEND_DAWN and requires Emscripten 4.0.10+, which correspond to using Emscripten '--use-port=emdawnwebgpu'.
// - Emscripten < 4.0.10 is not supported anymore (old '-sUSE_WEBGPU=1' option).
@@ -12,6 +12,7 @@
// This requirement may be removed once WebGPU stabilizes and backends converge on a unified interface.
//#define IMGUI_IMPL_WEBGPU_BACKEND_DAWN
//#define IMGUI_IMPL_WEBGPU_BACKEND_WGPU
//#define IMGUI_IMPL_WEBGPU_BACKEND_WGVK
// Implemented features:
// [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID/ImTextureRef!
+11 -4
View File
@@ -21,6 +21,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2026-05-19: DPI: ImGui_ImplWin32_EnableDpiAwareness() helper uses SetProcessDpiAwarenessContext() instead of SetThreadDpiAwarenessContext(), fixes DPI scaling issues with e.g. OpenGL. (#9403)
// 2026-01-28: Inputs: Minor optimization not submitting gamepad input if packet number has not changed (reworked from 2025-09-23 attempt). (#9202, #8556)
// 2025-12-03: Inputs: handle WM_IME_CHAR/WM_IME_COMPOSITION messages to support Unicode inputs on MBCS (non-Unicode) Windows. (#9099, #3653, #5961)
// 2025-10-19: Inputs: Revert previous change to allow for io.ClearInputKeys() on focus-out not losing gamepad state.
@@ -412,7 +413,7 @@ void ImGui_ImplWin32_NewFrame()
// Setup time step
INT64 current_time = 0;
::QueryPerformanceCounter((LARGE_INTEGER*)&current_time);
io.DeltaTime = (float)(current_time - bd->Time) / bd->TicksPerSecond;
io.DeltaTime = (float)((double)(current_time - bd->Time) / (double)bd->TicksPerSecond);
bd->Time = current_time;
// Update OS mouse position
@@ -886,6 +887,7 @@ DECLARE_HANDLE(DPI_AWARENESS_CONTEXT);
typedef HRESULT(WINAPI* PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS); // Shcore.lib + dll, Windows 8.1+
typedef HRESULT(WINAPI* PFN_GetDpiForMonitor)(HMONITOR, MONITOR_DPI_TYPE, UINT*, UINT*); // Shcore.lib + dll, Windows 8.1+
typedef DPI_AWARENESS_CONTEXT(WINAPI* PFN_SetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT); // User32.lib + dll, Windows 10 v1607+ (Creators Update)
typedef BOOL(WINAPI* PFN_SetProcessDpiAwarenessContext)(DPI_AWARENESS_CONTEXT); // User32.lib + dll, Windows 10 v1703+ (Creators Update)
// Helper function to enable DPI awareness without setting up a manifest
void ImGui_ImplWin32_EnableDpiAwareness()
@@ -893,7 +895,12 @@ void ImGui_ImplWin32_EnableDpiAwareness()
if (_IsWindows10OrGreater())
{
static HINSTANCE user32_dll = ::LoadLibraryA("user32.dll"); // Reference counted per-process
if (PFN_SetThreadDpiAwarenessContext SetThreadDpiAwarenessContextFn = (PFN_SetThreadDpiAwarenessContext)::GetProcAddress(user32_dll, "SetThreadDpiAwarenessContext"))
if (PFN_SetProcessDpiAwarenessContext SetProcessDpiAwarenessContextFn = (PFN_SetProcessDpiAwarenessContext)::GetProcAddress(user32_dll, "SetProcessDpiAwarenessContext")) // Windows 10 v1703+
{
SetProcessDpiAwarenessContextFn(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
return;
}
if (PFN_SetThreadDpiAwarenessContext SetThreadDpiAwarenessContextFn = (PFN_SetThreadDpiAwarenessContext)::GetProcAddress(user32_dll, "SetThreadDpiAwarenessContext")) // Windows 10 v1607+
{
SetThreadDpiAwarenessContextFn(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
return;
@@ -930,7 +937,7 @@ float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor)
{
GetDpiForMonitorFn((HMONITOR)monitor, MDT_EFFECTIVE_DPI, &xdpi, &ydpi);
IM_ASSERT(xdpi == ydpi); // Please contact me if you hit this assert!
return xdpi / 96.0f;
return (float)xdpi / 96.0f;
}
}
#ifndef NOGDI
@@ -940,7 +947,7 @@ float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor)
IM_ASSERT(xdpi == ydpi); // Please contact me if you hit this assert!
::ReleaseDC(nullptr, dc);
#endif
return xdpi / 96.0f;
return (float)xdpi / 96.0f;
}
float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd)
+3 -2
View File
@@ -1,7 +1,8 @@
#version 450 core
layout(location = 0) out vec4 fColor;
layout(set=0, binding=0) uniform sampler2D sTexture;
layout(set=0, binding=0) uniform texture2D _Texture;
layout(set=1, binding=0) uniform sampler _Sampler;
layout(location = 0) in struct {
vec4 Color;
@@ -10,5 +11,5 @@ layout(location = 0) in struct {
void main()
{
fColor = In.Color * texture(sTexture, In.UV.st);
fColor = In.Color * texture(sampler2D(_Texture, _Sampler), In.UV.st);
}
+6 -3
View File
@@ -84,6 +84,7 @@ List of Platforms Backends:
List of Renderer Backends:
imgui_impl_cpu.cpp ; Generic packed-pixel CPU framebuffer renderer (RGBA/BGRA/RGB565/indexed, etc. see example_sdl2_cpu, example_apple_cpu)
imgui_impl_dx9.cpp ; DirectX9
imgui_impl_dx10.cpp ; DirectX10
imgui_impl_dx11.cpp ; DirectX11
@@ -94,6 +95,8 @@ List of Renderer Backends:
imgui_impl_sdlgpu3.cpp ; SDL_GPU (portable 3D graphics API of SDL3)
imgui_impl_sdlrenderer2.cpp ; SDL_Renderer (optional component of SDL2 available from SDL 2.0.18+)
imgui_impl_sdlrenderer3.cpp ; SDL_Renderer (optional component of SDL3. Prefer using SDL_GPU!).
imgui_impl_sdlsurface2.cpp ; SDL_Surface CPU renderer for SDL2
imgui_impl_sdlsurface3.cpp ; SDL_Surface CPU renderer for SDL3
imgui_impl_vulkan.cpp ; Vulkan
imgui_impl_wgpu.cpp ; WebGPU (web + desktop)
@@ -103,7 +106,7 @@ List of high-level Frameworks Backends (combining Platform + Renderer):
imgui_impl_null.cpp
Emscripten is also supported!
The SDL2+GL, SDL3+GL, GLFW+GL and GLFW+WebGPU examples are all ready to build and run with Emscripten.
The SDL2+CPU, SDL2+GL, SDL3+GL, SDL2+Surface, SDL3+Surface, GLFW+GL and GLFW+WebGPU examples are all ready to build and run with Emscripten.
### Recommended Backends
@@ -255,8 +258,8 @@ void MyImGuiBackend_RenderDrawData(ImDrawData* draw_data)
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback)
{
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
MyEngineSetupenderState();
if (pcmd->UserCallback == platform_io.DrawCallback_ResetRenderState)
MyEngineSetupSenderState();
else
pcmd->UserCallback(cmd_list, pcmd);
}
+355 -17
View File
@@ -36,12 +36,261 @@ HOW TO UPDATE?
- Please report any issue!
-----------------------------------------------------------------------
VERSION 1.92.7 WIP (In Progress)
VERSION 1.92.9 WIP (In Progress)
-----------------------------------------------------------------------
Breaking Changes:
- Separator(): fixed a legacy quirk where Separator() was submitting a zero-height
- TreeNode: commented out legacy name `ImGuiTreeNodeFlags_SpanTextWidth` which
was obsoleted in 1.90.7 (May 2024). Use `ImGuiTreeNodeFlags_SpanLabelWidth`.
Other Changes:
- Windows:
- Clicking on a window's empty-space to move/focus a window checks
for lack of mouse button ownership. This gives an additional opportunity
for user code to bypass it without using a clickable item. (#9382)
- Clicking on a window's empty-space to move/focus a window checks
for lack of queued focus request. (#9382)
- InputText:
- Added `style.InputTextCursorSize` to configure cursor/caret thickness. (#7031, #9409)
This is automatically scaled by `style.ScaleAllSizes()`.
- Fonts:
- Added `IMGUI_DISABLE_DEFAULT_FONT_BITMAP`/`IMGUI_DISABLE_DEFAULT_FONT_VECTOR` to
disable embedding either fonts separately. (#9407)
- Tweak `CalcTextSize()` awkward width rounding/ceiling code to reduce floating-point
imprecisions altering the result by 1 even at relatively small width. (#791)
- Fixed an issue where passing a manually created ImFontAtlas to CreateContext() would
incorrectly destroy it in DestroyContext() when ref-count gets back to zero. (#9426)
- DrawList:
- Minor optimization to `AddLine()`, `AddLineH()`, `AddLineV()` functions. (#4091)
- Added `ImDrawListFlags_TextNoPixelSnap` to disable snapping of AddText()
coordinates for a given scope. (#3437, #9417, #2291)
- ColorButton:
- Small rendering tweak/optimization for the alpha checkerboard.
- Demo:
- Extract 'Widgets->Tree Nodes->Selectable Nodes' out of the 'Advanced'
demo for clarity (manual reimplementation of basic selection).
- Backends:
- Win32:
- Uses `SetProcessDpiAwarenessContext()` instead of `SetThreadDpiAwarenessContext()`
when available, fixing OpenGL DPI scaling issues as e.g. NVIDIA drivers tends
to spawn multiple-thread to manage OpenGL. (#9403)
-----------------------------------------------------------------------
VERSION 1.92.8 (Released 2026-05-12)
-----------------------------------------------------------------------
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.8
Breaking Changes:
- DrawList: swapped the last two arguments of `AddRect()`, `AddPolyline()`, `PathStroke()`.
- Before: `void ImDrawList::AddRect(ImVec2 p_min, ImVec2 p_max, ImU32 col, float rounding = 0.0f, ImDrawFlags flags = 0, float thickness = 1.0f);`
- After: `void ImDrawList::AddRect(ImVec2 p_min, ImVec2 p_max, ImU32 col, float rounding = 0.0f, float thickness = 1.0f, ImDrawFlags flags = 0);`
- Before: `void ImDrawList::AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness);`
- After: `void ImDrawList::AddPolyline(const ImVec2* points, int num_points, ImU32 col, float thickness, ImDrawFlags flags = 0);`
- Before: `void ImDrawList::PathStroke(ImU32 col, ImDrawFlags flags = 0, float thickness = 1.0f);`
- After: `void ImDrawList::PathStroke(ImU32 col, float thickness = 1.0f, ImDrawFlags flags = 0);`
Added inline redirection functions when IMGUI_DISABLE_OBSOLETE_FUNCTIONS is off.
Marked the old functions are =delete when IMGUI_DISABLE_OBSOLETE_FUNCTIONS is on, to allow for better type-checking.
Effectively the typical call site is changing from:
- Before: `window->DrawList->AddRect(p_min, p_max, color, rounding, ImDrawFlags_None, border_size);`
- After: `window->DrawList->AddRect(p_min, p_max, color, rounding, border_size);`
Notes:
- Users of C++ and other languages with type-checking will be notified at compile-time of any mistakes.
- Users of high-level bindings or languages with no type-checking will be notified at runtime via an assert for invalid flags value.
If you are a binding maintainer consider doing something to facilitate transition or error detection.
- This is perhaps the worst breaking change in our history :( but it makes ImDrawList function signatures consistent.
As we are aiming to add flags and features to variety of ImDrawList functions, that consistency becomes more important.
The new order is also more convenient as `flags` are less frequently used than `thickness` in real code.
- As a general policy in Dear ImGui, all our flags default to 0 so ImDrawFlags_None was likely written 0 in some call sites.
- Consider adding `#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS` in your imconfig.h, even temporarily, to clean up legacy code.
- Reminder: you do NOT need to specify `ImDrawFlags_RoundCornersAll` for rounding, it is already the default!
- DrawList: obsoleted `ImDrawCallback_ResetRenderState` in favor of using `ImGui::GetPlatformIO().DrawCallback_ResetRenderState`,
which is part of our new standard draw callbacks. (#9378)
Redirecting the earlier value into the later one when set, so both old and new code should work.
- DrawList: changed value of `ImDrawFlags_Closed`. It was previously advertised as "always == 1" when introduced
in 1.82 (2021/02), in order to facilitate backward compatibility with the legacy `bool closed` flag. This
guarantee has been removed. The bit is reserved, and `AddPolyline()`, `PathStroke()` will assert when it is used.
- Backends:
- Vulkan: redesigned to use separate ImageView + Sampler instead of Combined Image Sampler. (#914)
This change allows us to facilitate changing samplers, in line with other backends. [@yaz0r, @ocornut]
- When creating your own descriptor pool (instead of letting backend creates its own):
- Before: need at least `IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE` descriptors of type `VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER`.
- After: need at least `IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE` descriptors of type `VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE`.
+ `IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE` descriptors of type `VK_DESCRIPTOR_TYPE_SAMPLER`.
- When registering custom textures: changed ImGui_ImplVulkan_AddTexture() signature to remove Sampler.
- Before: `ImGui_ImplVulkan_AddTexture(VkSampler, VkImageView, VkImageLayout)`
- After: `ImGui_ImplVulkan_AddTexture(VkImageView, VkImageLayout)`
- Kept inline redirection function that ignores the sampler (will obsolete).
- DirectX10, DirectX11, SDLGPU3, Vulkan: removed samplers from `ImGui_ImplXXXX_RenderState`.
Prefer to use backend-agnostic DrawCallback_SetSamplerLinear which works everywhere! (#9378)
If there is a legit need/request for them or any render state we can always add them back.
Other Changes:
- DrawList:
- Added room in `ImGuiPlatformIO` for standard backend-agnostic draw callbacks. Those callbacks
are setup/provided by the backend and available in most of our standard backends.
They allow backend-agnostic code from e.g. switching to a Nearest/Point sampler without
messing with custom Renderer-specific callbacks.
platform_io.DrawCallback_ResetRenderState; // Request to reset the graphics/render state.
platform_io.DrawCallback_SetSamplerLinear; // Request to set current texture sampling to Linear
platform_io.DrawCallback_SetSamplerNearest; // Request to set current texture sampling to Nearest/Point
Note that some backends might not support all callbacks.
(#9378, #9371, #3590, #8926, #2973, #7485, #7468, #6969, #5118, #7616, #9173, #8322, #7230,
#5999, #6452, #5156, #7342, #7592, #7511)
- Made `AddCallback()` user data default to Null for convenience.
- Added `AddLineH()`, `AddLineV()` helpers to draw horizontal and vertical lines. [@memononen]
The new functions are more optimal and will be part of a larger effort in 1.93 to fix
inconsistencies and improve the DrawList API. In the current API, `AddLine()` adds a "magic" +0.5f
offset and then center the line, whereas AddLineH()/AddLineV() use the right side of the line to expand.
For thickness=1.0f lines this is equivalent:
`AddLine({10,3}, {20,3}, ...)` --> `AddLineH(x1=10, x2=20, y=3, ...)`.
`AddLine({3,10}, {3,20}, ...)` --> `AddLineV(x=3, y1=10, y2=20, ...)`.
For larger integer thickness, AddLine() will center but may be blurry, AddLineH()/AddLineV()
will expand "inside" (to the right side) and will always be sharp.
A subsequent release will expand on those concepts and add new options.
- InputText:
- InputTextMultiline: fixed an issue processing deactivation logic when an active
multi-line edit is clipped due to being out of view.
- Fixed a crash when toggling ReadOnly while active. (#9354)
- `CharFilter` callback event sets CursorPos/SelectionStart/SelectionEnd. (#816)
- Tables:
- Fixed issues reporting ideal size to parent window/container: (#9352, #7651)
- When both scrollbars are visible but only one of ScrollX/ScrollY was explicitly requested.
- When vertical scrollbar was not at the top, the computation was often incorrect.
- Windows:
- Fixed a single-axis auto-resizing feedback loop issue with nested containers
and varying scrollbar visibility. (#9352)
- Detect and report error when calling End() instead of EndPopup() on a popup. (#9351)
- Child windows with only `ImGuiChildFlags_AutoResizeY` flag keep using the proportional
default `ItemWidth`. (#9355)
- Using mouse wheel to scroll takes and keeps ownership of the corresponding keys
(e.g. `ImGuiKey_MouseWheelY`) while a wheeling window is locked. (#2604, #3795)
- InputInt, InputFloat, InputScalar:
- Reinstated `ImGuiInputTextFlags_EnterReturnsTrue` support which was removed in 1.91.4.
(#8665, #9299, #8065, #3946, #6284, #9117)
- Fixed the fact that it didn't return true when validating same value.
- Fixed losing value when tabbing out or losing focus.
- Made it that pressing +/- step buttons also return true, which is in line
with 1.91.4 behavior.
- In a majority of cases you should use `IsItemDeactivatedAfterEdit()` instead,
but it still has a few edge cases flaws (to be addressed soon).
- Allow passing a format string that does not display the scalar value.
Parsing input with default format for the type. (#9385) [@FireFox2000000]
- Multi-Select:
- Fixed an issue using Multi-Select within a Table causing column width measurement to
be invalid when trailing column contents is not submitted in the last row. (#9341, #8250)
- Fixed an issue using Multi-Select within a Table with the right-most column visible,
which could lead to an extra vertical offset in the Header row. (#8250)
- Multi-Select + Box-Select:
- Fixed an issue using `ImGuiMultiSelectFlags_BoxSelect1d` mode while scrolling.
Notably, using mouse wheel while holding a box-selection could lead items close to windows
edges from not being correctly unselected. (#7994, #8250, #7821, #7850, #7970)
- Improved dirty/unclip rectangle logic for `ImGuiMultiSelectFlags_BoxSelect2d`.
- Fixed an issue using `ImGuiMultiSelectFlags_BoxSelect2d` mode, where
items out of view wouldn't be properly selected while scrolling while mouse cursor
is hovering outside of selection scope. (#7994, #1861, #6518)
- Fixed an issue where items out of horizontal view would sometimes lead
to incorrect merging of sequential selection requests while also scrolling fast
enough to overlap multiple rows during a frame. (#7994, #1861, #6518)
- Fixed an issue using `ImGuiMultiSelectFlags_BoxSelect2d` mode in a Table
while relying on the `TableNextColumn()` return value to perform coarse clipping. (#7994)
- Disabled merging consecutive selection requests as we have no reliable
way of detecting if user has submitted all consecutive items without clipping gaps,
and `ImGuiSelectionUserData` is technically opaque storage. (#7994, #1861)
(we will probably bring this back as a minor optimization if we have a way to for
user to tell us `ImGuiSelectionUserData` are indices)
- Fixes for using across nested child windows. (#8364)
- Box-Select + Clipper: fixed an issue selecting items while scrolling while a clipper
active. (#7994, #8250, #7821, #7850, #7970)
- Box-Select + Tables: fixed an issue using box-selection in a tables with
items straying out of columns boundaries. (#7994, #2221)
- Box-Select + Tables: fixed an issue when calling `BeginMultiSelect()` in a table
before layout has been locked (first row or headers row submitted). (#8250)
- Menus:
- BeginMenu()/MenuItem(): fixed accidental triggering of child menu items when
opening a menu inside a small host window forcing the child menu window to be
repositioned under the mouse cursor. (#8233, #9394)
Done by reworking `BeginMenu()`/`MenuItem()`: they previously avoiding taking
ActiveID + key/click ownership (in order to allow releasing button on another item).
Now they take them and release them once the mouse is moved outside item boundaries.
- Inputs:
- SetItemKeyOwner(): return true if ownership has been requested, which typically
needs to to checked for gating further tests. This is important as the function
may fail. (#456, #2637, #2620, #2891, #3370, #3724, #4828, #5108, #5242, #5641)
- SetItemKeyOwner(): does not set ownership is key is already taken. Effectively
this makes using `SetItemKeyOwner(ImGuiKey_MouseWheelY)` over an item work as
expected while not having item react if a scroll wheel is actively in progress.
May be subject to further redesign, e.g. conditional flags. Feedback welcome!
- Style:
- Checkbox: added `ImGuiCol_CheckboxSelectedBg` to change or accentuate the
background color of checked/mixed checkboxes. (#9392)
- Added `ImGuiStyleVar_DragDropTargetRounding`. (#9056)
- Fixed vertical scrollbar top coordinates when using thick borders on windows
with no title bar and no menu bar. (#9366)
- Fonts:
- imgui_freetype: add FreeType headers & compiled version in 'About Dear ImGui' details.
- Assert when using MergeMode with an explicit size over a target font with an implicit
size, as scale factor are likely erroneous. (#9361)
- Clipper:
- Improved error reporting when misusing the clipper inside a table (prioritize
reporting the common clipper error over a table sanity check assert). (#9350)
- Tweaked assert triggering when first item height measurement fails, and made it
a better recoverable error. (#9350)
- Misc:
- Minor optimization: reduce redundant label scanning in common widgets.
- Added missing Test Engine hooks for `PlotLines()`, `PlotHistogram()`, `VSliderXXX()`
and `TableHeader()` functions.
- Demo:
- Added simple demo for a scrollable/zoomable image viewer with a grid.
Available in `Examples->Image Viewer` and `Widgets->Images`.
- Backends:
- Added support for new standardized draw callbacks in most backends: (#9378)
- Allegro5: Reset n/a n/a
- DX9: Reset SetSamplerLinear SetSamplerNearest
- DX10: Reset SetSamplerLinear SetSamplerNearest
- DX11: Reset SetSamplerLinear SetSamplerNearest
- DX12: Reset SetSamplerLinear SetSamplerNearest
- Metal: Reset SetSamplerLinear SetSamplerNearest
- OpenGL2: Reset SetSamplerLinear SetSamplerNearest
- OpenGL3+: Reset SetSamplerLinear SetSamplerNearest
- SDLGPU3: Reset SetSamplerLinear SetSamplerNearest
- SDLRenderer2: Reset n/a n/a
- SDLRenderer3: Reset SetSamplerLinear SetSamplerNearest
- Vulkan: Reset SetSamplerLinear SetSamplerNearest
- WebGPU: Reset SetSamplerLinear SetSamplerNearest
(Vulkan backend by @yaz0r, Metal by @ssh4net, others by @ocornut)
- GLFW: added a Win32-specific implementation of `ImGui_ImplGlfw_GetContentScaleXXXX`
functions for legacy GLFW 3.2. (#9003)
- Metal: avoid redundant vertex buffer bind in `SetupRenderState()`, which leads
to validation issue. (#9343) [@Hunam6]
- Metal: use a dedicated `bufferCacheLock` to avoid crashing when `bufferCache` is
replaced by a new object while being used for `@synchronize()`. (#9367) [@andygrundman]
- SDL2: made `ImGui_ImplSDL2_GetContentScaleForWindow()`/`ImGui_ImplSDL2_GetContentScaleForDisplay()`
helpers return a minimum of 1.0f, as some Linux setup seems to report <1.0f value
and this breaks scaling border size. (#9369)
- WebGPU: rework choice/detection of using WGSL/SPIR-V shader on WGVK. (#9316, #9246, #9257, #9387)
- Examples:
- Update VS toolset in all .vcxproj from VS2015 (v140) to VS2017 (v141). The later is the
first that supports vcpkg. Onward we will likely stop testing building the library with VS2015.
- GLFW+Vulkan, SDL2+Vulkan, SDL3+Vulkan, Win32+Vulkan: reworked to create a descriptor pool with:
- `IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE` descriptors of type `VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE`.
- `IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE` descriptors of type `VK_DESCRIPTOR_TYPE_SAMPLER`.
-----------------------------------------------------------------------
VERSION 1.92.7 (Released 2026-04-02)
-----------------------------------------------------------------------
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.7
Breaking Changes:
- Separator: fixed a legacy quirk where `Separator()` was submitting a zero-height
item for layout purpose, even though it draws a 1-pixel separator.
The fix could affect code e.g. computing height from multiple widgets in order to
allocate vertical space for a footer or multi-line status bar. (#2657, #9263)
@@ -53,16 +302,18 @@ Breaking Changes:
BeginChild("ScrollingRegion", { 0, -footer_height });
When such idiom was used and assuming zero-height Separator, it is likely that
in 1.92.7 the resulting window will have unexpected 1 pixel scrolling range.
- Multi-Select: renamed `ImGuiMultiSelectFlags_SelectOnClick` to `ImGuiMultiSelectFlags_SelectOnAuto`.
Kept inline redirection enum (will obsolete).
- Combo(), ListBox(): commented out legacy signatures which were obsoleted in 1.90
(Nov 2023), when the getter callback type was changed from:
getter type: bool (*getter)(void* user_data, int idx, const char** out_text)
bool (*getter)(void* user_data, int idx, const char** out_text)
To:
getter type: const char* (*getter)(void* user_data, int idx)
const char* (*getter)(void* user_data, int idx)
Other Changes:
- TreeNode:
- Moved TreeNodeGetOpen() helper to public API. I was hesitant to make this public
- Moved `TreeNodeGetOpen()` helper to public API. I was hesitant to make this public
because I intend to provide a more generic and feature-full version, but in the meanwhile
this will do. (#3823, #9251, #7553, #6754, #5423, #2958, #2079, #1947, #1131, #722)
- In 'Demo->Property Editor' demonstrate a way to perform tree clipping by fast-forwarding
@@ -71,30 +322,113 @@ Other Changes:
it was prior to 1.91.
- InputText:
- Shift+Enter in multi-line editor always adds a new line, regardless of
ImGuiInputTextFlags_CtrlEnterForNewLine being set or not. (#9239)
`ImGuiInputTextFlags_CtrlEnterForNewLine` being set or not. (#9239)
- Reworked `io.ConfigInputTextEnterKeepActive` mode so that pressing Enter will
deactivate/reactivate the item in order for e.g. `IsItemDeactivatedAfterEdit()`
signals to be emitted the same way regardless of that setting. (#9001, #9115)
- Fixed a glitch when using `ImGuiInputTextFlags_ElideLeft` where the local x offset
would be incorrect during the deactivation frame. (#9298)
- Fixed a crash introduced in 1.92.6 when handling `ImGuiInputTextFlags_CallbackResize`
in certain situations. (#9174)
- Fixed selection highlight Y1 offset being very slightly off (since 1.92.3). (#9311) [@v-ein]
- InputTextMultiline: fixed an issue introduced in 1.92.3 where line count calculated
for vertical scrollbar range would be +1 when the widget is inactive, word-wrap is
disabled and the text buffer ends with '\n'. Fixed a similar issue related to clipping
large amount of text.
- InputTextMultiline: avoid going through reactivation code and fixed losing revert value
when activating scrollbar.
- InputTextMultiline: fixed an issue where edit buffer wouldn't be reapplied to back
buffer on the `IsItemDeactivatedAfterEdit()` frame. This could create issues when
using the idiom of not applying edits before `IsItemDeactivatedAfterEdit()`.
(#9308, #8915, #8273)
- Tables:
- Allow reordering columns by dragging them in the context menu. (#9312)
- Context menu now presents columns in display order. (#9312)
- Fixed and clarified the behavior of using `TableSetupScrollFreeze()` with columns>1,
and where some of the columns within that range were Hidable.
- Before: `TableSetupScrollFreeze(N, 0)`: include the N left-most visible columns as
part of the scroll freeze. So if you intentionally hide columns <N, the scroll
freeze area would start covering the subsequent/following columns (N+1) etc.
- After: `TableSetupScrollFreeze(N, 0)`: include the N left-most columns (regardless of visibility),
as part of the scroll freeze. So if you intentionally hide columns <N, the scroll
freeze area will cover less columns.
- This is generally more sane and logical.
- Fixed dragging a header to reorder outside of visible bounds (due to horizontal scrolling)
from losing active id.
- Angled Headers: angled section for column being reordered via the regular headers
stays highlighted during reordering.
- Style:
- Border sizes are now scaled (and rounded) by ScaleAllSizes().
- When using large values with ScallAllSizes(), the following items thickness
- Fonts: fixed an issue introduced in 1.92.6 where `style.FontBaseSize` would be
cleared during the first frame if no fonts was explicitly added before.
- Border sizes are now scaled (and rounded) by `ScaleAllSizes()`.
- When using large values with `ScallAllSizes()`, the following items thickness
are scaled to integer amounts:
- InputText Caret/cursor thickness. (#7031)
- CloseButton() thickness.
- TextLink() underline thickness.
- ColorButton() border thickness.
- Separator() thickness, via scaling newly added style.SeparatorSize. (#2657, #9263)
- `InputText()` caret/cursor thickness. (#7031)
- `CloseButton()` thickness.
- `TextLink()` underline thickness.
- `ColorButton()` border thickness.
- `Separator()` thickness, via scaling newly added `style.SeparatorSize`. (#2657, #9263)
- Nav:
- Popups: Shift+F10 or Menu key can now open popups menus when using
`BeginPopupContextItem()`, `BeginPopupContextWindow()` or `OpenPopupOnItemClick()`.
(#8803, #9270) [@exelix11, @ocornut]
- Changed Gamepad mapping for "Activate with Text Input" action: (#8803, #787)
- Previously: press North button (PS4/PS5 triangle, Switch X, Xbox Y).
- Now: long press (hold) Activate button (PS4/PS5 cross, Switch B, Xbox A) for ~0.60 secs.
This is rarely used, somehow easier to discover, and frees a button for other uses.
See updated Gamepad Control Sheets: https://www.dearimgui.com/controls_sheets
- Short Gamepad Activation press on InputText() always activate with Text Input mode.
- Popups: pressing North button (PS4/PS5 triangle, SwitchX, Xbox Y) also open popups menus.
- Multi-Select:
- Added `ImGuiMultiSelectFlags_SelectOnClickAlways` mode (rarely used).
This prevents Drag and Drop of multiple items, but it allows to start a new Box-Selection
from inside an existing selection (Excel style). (#9307, #1861)
- Clipper:
- Clear `DisplayStart`/`DisplayEnd` fields when `Step()` returns false.
- Added `UserIndex` helper storage. This is solely a convenience for cases where
you may want to carry an index around.
- Always pulls current context on `ImGuiListClipper::Begin()`, consistent with public
API design, and avoids issues with clipper instances outliving contexts. (#9324, #5856)
- Scrollbar:
- Implemented a custom tweak to extend hit-testing bounding box when window is sitting
at the edge of a viewport (e.g. fullscreen or docked window), so that e.g. mouse the
mouse at the extreme of the screen will reach the scrollbar. (#9276)
- Demo: fixed IMGUI_DEMO_MARKER locations for examples applets. (#9261, #3689) [@pthom]
- Fixed an issue which could lead initial click to move the current scroll by a pixel.
- Button:
- Moved `ImGuiButtonFlags_AllowOverlap` from imgui_internal.h to imgui.h,
as a convenience for when using e.g. `InvisibleButton()`.
- Focus: fixed fallback "Debug" window temporarily taking focus and setting `io.WantCaptureKeyboard`
for one frame on e.g. application boot if no other windows are submitted. (#9243)
- DrawList:
- PathArcTo(): fixed erroneous segment count for pathologically small arcs on large
circles. (#9331, #9313) [@thedmd, @epajarre]
- Memory:
- Discard/GC of ImDrawList buffers for unused windows favor restoring them to
~Size*1.05 instead of Capacity when awakening again. Facilitate releasing ImDrawList
buffers after unusual usage spike. (#9303)
- Fixed `GetForegroundDrawList()`/`GetBackgroundDrawList()` per-viewport buffers not being
collected when unused for `io.ConfigMemoryCompactTimer` amount of time. (#9303)
- Demo: fixed `IMGUI_DEMO_MARKER` locations for examples applets. (#9261, #3689) [@pthom]
- Misc: added missing ImVec2/ImVec4 operators. (#9339, #8258) [@dkosmari, @ArashPartow]
- Internals:
- ButtonBehavior: fixed internal/low-level `ImGuiButtonFlags_PressedOnRelease`
(as well as equivalent `ImGuiSelectableFlags_SelectOnRelease` for Selectable) from
not taking current active id. `ImGuiButtonFlags_NoHoldingActiveID` allows that.
This was only used internally by MenuItem().
- Backends:
- SDLGPU3: removed unnecessary call to SDL_WaitForGPUIdle when releasing
- DirectX9, OpenGL2, OpenGL3, Metal, SDLGPU3, SDLRenderer2, SDLRenderer3: fixed easy-to-fix
issues in code assuming ImTextureID_Invalid is always defined to 0. (#9295, #9310)
- GLFW: mouse cursor is properly restored if changed by user app/code while using
`glfwSetInputMode(..., GLFW_CURSOR_DISABLED)` or `ImGuiConfigFlags_NoMouseCursorChange`.
Amend optimization done in 1.92.6.
- SDLGPU3: removed unnecessary call to `SDL_WaitForGPUIdle()` when releasing
vertex/index buffers. (#9262) [@jaenis]
- WebGPU: fixed version check for Emscripten 5.0.0+.
- WebGPU: removed support for Emscripten <4.0.10. (#9281) [@ypujante]
- WebGPU: added support for WGVK native backend via `IMGUI_IMPL_WEBGPU_BACKEND_WGVK`,
using SPIRV shaders if WGSL is not available. (#9316, #9246, #9257) [@r-lyeh]
(WGVK is a lightweight alternative to Dawn or WGPU for native applications,
which is easier to build/setup, see: https://github.com/manuel5975p/WGVK)
- Examples:
- Emscripten: added `tabindex=-1` to canvas in our shell_minimal.htm. Without it,
the canvas was not focusable in the DOM, which in turn make some backends
@@ -102,11 +436,15 @@ Other Changes:
- Emscripten: fixed minor rendering issues with our HTML shell. (#9281) [@ypujante]
- hidden small blue outline when canvas is focused on Chrome.
- hidden scrollbar in Firefox.
- Vulkan: added ImGui_ImplVulkan_PipelineInfo::ExtraDynamicStates[] to allow specifying
- Vulkan: added `ImGui_ImplVulkan_PipelineInfo::ExtraDynamicStates[]` to allow specifying
extra dynamic states to add when creating the VkPipeline. (#9211) [@DziubanMaciej]
- Vulkan: `ImGui_ImplVulkan_AddTexture()` skips updating descriptor_set if failing
to allocate one. (#8677) [@micb25]
- WebGPU: fixed undefined behaviors in example code for requesting adapter
and device. (#9246, #9256) [@r-lyeh]
- GLFW/SDL2/SDL3+WebGPU: removed suport for Emscripten <4.0.10. (#9281) [@ypujante]
- SDL2+WebGPU: fixed hi-dpi handling. (#9300) [@ypujante]
- GLFW/SDL2/SDL3+WebGPU: added support for WGVK. (#9316, #9246, #9257) [@r-lyeh, @ocornut]
- GLFW/SDL2/SDL3+WebGPU: removed support for Emscripten <4.0.10. (#9281) [@ypujante]
-----------------------------------------------------------------------
+21 -1
View File
@@ -71,6 +71,11 @@ OSX + OpenGL2 example. <BR>
(NB: imgui_impl_osx.mm is currently not as feature complete as other platforms backends.
You may prefer to use the GLFW Or SDL backends, which will also support Windows and Linux.)
[example_apple_cpu/](https://github.com/ocornut/imgui/blob/master/examples/example_apple_cpu/) <BR>
OSX + CPU framebuffer example. <BR>
= main.mm + imgui_impl_osx.mm + imgui_impl_cpu.cpp <BR>
This is a native Cocoa example, renders to a native BGRA framebuffer, and does not use SDL.<BR>
[example_glfw_wgpu/](https://github.com/ocornut/imgui/blob/master/examples/example_glfw_wgpu/) <BR>
GLFW + WebGPU example. Supports Emscripten (web), Dawn (native), WGPU (native). <BR>
= main.cpp + imgui_impl_glfw.cpp + imgui_impl_wgpu.cpp
@@ -145,6 +150,17 @@ SDL2 (Win32, Mac, Linux, etc.) + SDL_Renderer for SDL2 example.<BR>
= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_sdlrenderer2.cpp <BR>
This requires SDL 2.0.18+ (released November 2021) <BR>
[example_sdl2_surface/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_surface/) <BR>
SDL2 (Win32, Mac, Linux, etc.) + SDL_Surface CPU renderer example.<BR>
= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_sdlsurface2.cpp <BR>
This supports building with Emscripten.<BR>
[example_sdl2_cpu/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_cpu/) <BR>
SDL2 (Win32, Mac, Linux, etc.) + caller-owned packed-pixel CPU framebuffer renderer example.<BR>
= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_cpu.cpp <BR>
This derives the CPU framebuffer format from the current SDL window surface.<BR>
This supports building with Emscripten.<BR>
[example_sdl2_vulkan/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_vulkan/) <BR>
SDL2 (Win32, Mac, Linux, etc.) + Vulkan example. <BR>
= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_vulkan.cpp <BR>
@@ -178,6 +194,11 @@ SDL3 (Win32, Mac, Linux, etc.) + SDL_GPU for SDL3 example.<BR>
SDL3 (Win32, Mac, Linux, etc.) + SDL_Renderer for SDL3 example.<BR>
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_sdlrenderer3.cpp <BR>
[example_sdl3_surface/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_surface/) <BR>
SDL3 (Win32, Mac, Linux, etc.) + SDL_Surface CPU renderer example.<BR>
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_sdlsurface3.cpp <BR>
This supports building with Emscripten.<BR>
[example_sdl3_vulkan/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_vulkan/) <BR>
SDL3 (Win32, Mac, Linux, etc.) + Vulkan example. <BR>
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_vulkan.cpp <BR>
@@ -253,4 +274,3 @@ when an interactive drag is in progress.
Note that some setup configurations or GPU drivers may introduce additional display lag depending on their settings.
If you notice that dragging windows is laggy and you are not sure what the cause is: try drawing a simple
2D shape directly under the mouse cursor to help identify the issue!
+98 -24
View File
@@ -25,7 +25,7 @@ or view this file with any Markdown viewer.
| [I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around...](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-clipping-or-disappearing-when-i-move-windows-around) |
| [I integrated Dear ImGui in my engine and some elements are displaying outside their expected windows boundaries...](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-displaying-outside-their-expected-windows-boundaries) |
| **Q&A: Usage** |
| **[About the ID Stack system..<br>Why is my widget not reacting when I click on it?<br>Why is the wrong widget reacting when I click on one?<br>How can I have widgets with an empty label?<br>How can I have multiple widgets with the same label?<br>How can I have multiple windows with the same label?](#q-about-the-id-stack-system)** |
| **[About the ID Stack system...](#q-about-the-id-stack-system)**<br>**[How can I have multiple widgets with the same label?](#q-how-can-i-have-multiple-widgets-with-the-same-label) (using `##` or `PushID()`)**<br>**[How can I have widgets with an empty label?](#q-how-can-i-have-widgets-with-an-empty-label) (using `##`)**<br>**[How can I animate the label of an existing widget?](#q-how-can-i-change-the-label-of-an-existing-widget) (using `###`)**<br>**[General description of the label and ID Stack system.](#general-description-of-the-label-and-id-stack-system)** |
| [How can I display an image?](#q-how-can-i-display-an-image)<br>[What are ImTextureID/ImTextureRef?](#q-what-are-imtextureidimtextureref)|
| [How can I use maths operators with ImVec2?](#q-how-can-i-use-maths-operators-with-imvec2) |
| [How can I use my own maths types instead of ImVec2/ImVec4?](#q-how-can-i-use-my-own-maths-types-instead-of-imvec2imvec4) |
@@ -263,15 +263,19 @@ ctx->RSSetScissorRects(1, &r);
# Q&A: Usage
### Q: About the ID Stack system...
### Q: Why is my widget not reacting when I click on it?
### Q: Why is the wrong widget reacting when I click on one?
### Q: How can I have widgets with an empty label?
### Q: How can I have multiple widgets with the same label?
### Q: How can I have multiple windows with the same label?
## Q: About the ID Stack system...
**USING THE SAME LABEL+ID IS THE MOST COMMON USER MISTAKE!**
<br>**USING AN EMPTY LABEL IS THE SAME AS USING THE SAME LABEL AS YOUR PARENT WIDGET!**
<br>Read the questions in this section for a more general understand of how labels and ID works in Dear ImGui.
TL;DR;
- Widgets labels are also used to compute Widgets unique identifiers.
- Unique identifiers are hashes of the label + of the parent scope (e.g. parent window or parent tree node labels).
- You can use `PushID()` to append to the identifier without making it visible.
- You can use `"##something"` in a label to append to the identifier without making it visible.
- You can use `"###something"` in a label to make the identifier ignore the visible part.
<table>
<tr>
<td><img src="https://github.com/user-attachments/assets/776a8315-1164-4178-9a8c-df52e0ff28aa"></td>
@@ -302,16 +306,99 @@ ImGui::End();
</tr>
</table>
A primer on labels and the ID Stack...
### Q: How can I have multiple widgets with the same label?
A. When widgets are in a same scope and finite, you can use a `"##something"` suffix which will be part of the identifier but not visible as a label.
```cpp
Button("Play"); // Label = "Play", ID = hash of ("MyWindow", "Play")
Button("Play##foo1"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo1") // Different from other buttons
Button("Play##foo2"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo2") // Different from other buttons
```
B. More generally, e.g. in loops, you can use `PushID()/PopID()` to push a prefix which will be part of the identifier.
```cpp
// Using PushID() with a string
for (int i = 0; i < 100; i++)
{
MyObject* obj = Objects[i];
PushID(obj->Name);
Button("Click"); // Label = "Click", ID = hash of ("Window", obj->Name, "Click")
PopID();
}
```
```cpp
// Using PushID() with an index
for (int i = 0; i < 100; i++)
{
PushID(i);
Button("Click"); // Label = "Click", ID = hash of ("Window", i, "Click")
PopID();
}
```
### Q: How can I have widgets with an empty label?
If you want to completely hide the label, but still need an ID:
```cpp
Checkbox("##On", &b); // Label = "", ID = hash of (..., "##On") // No visible label, just a checkbox!
```
##### [Return to Index](#index)
### Q: How can I make a label dynamic?
Dear ImGui is very dynamic so you can submit different widgets every frame.
However, in order to preserve widget state (eg. which tree node is open; which button is focused) the library internaly refers to their unique ID.
Occasionally you might want to change a label while preserving a constant ID. This allows you to change/animate labels while persisting associated state.
For example, you may want to include varying information in a window title bar or button label.
Using "###" exclude the preceeding part from ID computation:
```cpp
Button("Hello###ID"); // Label = "Enable", ID = hash of (..., "ID")
Button("World###ID"); // Label = "Disable", ID = hash of (..., "ID") // Same ID, different label
```
Using a same ID ensure that associated related e.g. weither the widget is focused, won't be lost when the label changes.
<table>
<tr>
<td><img src="https://github.com/user-attachments/assets/2bf18756-e122-498d-bbd4-5c44bb1018d5"></td>
<td>
<pre lang="cpp">
// Window label has animating FPS counter
// Window ID stays the same = hash of "MyGame"
char buf[128];
sprintf(buf, "My game (%.1f FPS)###MyGame", io.Framerate);
ImGui::Begin(buf);
&nbsp;
// Label changes between "Enable" and "Disable"
// ID stays the same = hash of ("MyGame", "MyButton")
if (ImGui::Button(enabled ? "Disable###MyButton" : "Enable###MyButton", { -FLT_MIN, 0.0f }))
enabled = !enabled;
&nbsp;
ImGui::End();
</pre>
</td>
</tr>
</table>
(Hint: I'd suggest wrapping sprintf in something more compact to use, e.g. [ocornut/Str](https://github.com/ocornut/Str) for what I personally use).
##### [Return to Index](#index)
### General description of the label and ID Stack system
Dear ImGui internally needs to uniquely identify UI elements.
Elements that are typically not clickable (such as calls to the Text functions) don't need an ID.
Interactive widgets (such as calls to Button buttons) need a unique ID.
Elements that are typically not clickable (such as calls to Text() functions) don't need an ID.
Interactive widgets (such as calls to Button() functions) need a unique ID.
**Unique IDs are used internally to track active widgets and occasionally associate state to widgets.<BR>
Unique IDs are implicitly built from the hash of multiple elements that identify the "path" to the UI element.**
Since Dear ImGui 1.85, you can use `Demo>Tools>ID Stack Tool` or call `ImGui::ShowIDStackToolWindow()`. The tool display intermediate values leading to the creation of a unique ID, making things easier to debug and understand.
You can use `Demo>Tools>ID Stack Tool` or call `ImGui::ShowIDStackToolWindow()`. The tool display intermediate values leading to the creation of a unique ID, making things easier to debug and understand.
![Stack tool](https://user-images.githubusercontent.com/8225057/136235657-a0ea5665-dcd1-423f-9be6-dc3f8ced8f12.png)
@@ -365,20 +452,7 @@ Button("Play##foo2"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo
Button("##foo"); // Label = "", ID = hash of ("MyWindow", "##foo") // Different from window
End();
```
- If you want to completely hide the label, but still need an ID:
```cpp
Checkbox("##On", &b); // Label = "", ID = hash of (..., "##On") // No visible label, just a checkbox!
```
- Occasionally/rarely you might want to change a label while preserving a constant ID. This allows
you to animate labels. For example, you may want to include varying information in a window title bar,
but windows are uniquely identified by their ID. Use "###" to pass a label that isn't part of ID:
```cpp
Button("Hello###ID"); // Label = "Hello", ID = hash of (..., "###ID")
Button("World###ID"); // Label = "World", ID = hash of (..., "###ID") // Same ID, different label
sprintf(buf, "My game (%f FPS)###MyGame", fps);
Begin(buf); // Variable title, ID = hash of "MyGame"
```
- Solving ID conflict in a more general manner:
Use `PushID()` / `PopID()` to create scopes and manipulate the ID stack, as to avoid ID conflicts
within the same window. This is the most convenient way of distinguishing ID when iterating and
+11
View File
@@ -77,6 +77,17 @@ Some solutions:
You can use the `ImFontGlyphRangesBuilder` for this purpose and rebuilding your atlas between frames when new characters are needed. This will be the biggest win!
- Set `io.Fonts.Flags |= ImFontAtlasFlags_NoPowerOfTwoHeight;` to disable rounding the texture height to the next power of two.
### (5) Reduce texture resizes/copy on startup
🆕 Since 1.92, the ImFontAtlas is initially created using a 512x128 texture, then grows as glyphs and fonts are used. Atlas growth leads to alloc+copy, and both the old and new sized textures are present in memory for a short time (typically one frame). If you use known fonts and want to reduce initial growth, you may set `TexMinWidth` and `TexMinHeight` during initializaton.
```cpp
ImFontAtlas* atlas = io.Fonts;
atlas->TexMinWidth = 1024;
atlas->TexMinHeight = 1024;
atlas->AddFont(...);
```
##### [Return to Index](#index)
---------------------------------------
+6 -6
View File
@@ -43,7 +43,7 @@ Dear ImGui is particularly suited to integration in game engines (for tooling),
**Backends for a variety of graphics API and rendering platforms** are provided in the [backends/](https://github.com/ocornut/imgui/tree/master/backends) folder, along with example applications in the [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder. You may also create your own backend. Anywhere where you can render textured triangles, you can render Dear ImGui.
C++20 users wishing to use a module may the use [stripe2933/imgui-module](https://github.com/stripe2933/imgui-module) third-party extension.
C++20 users wishing to use a module may use the [stripe2933/imgui-module](https://github.com/stripe2933/imgui-module) third-party extension.
See the [Getting Started & Integration](#getting-started--integration) section of this document for more details.
@@ -55,8 +55,8 @@ if (ImGui::Button("Save"))
ImGui::InputText("string", buf, IM_COUNTOF(buf));
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
```
<img width="412" height="236" alt="sample code output (dark)" src="https://github.com/user-attachments/assets/f075e2b0-98de-4be8-acb4-99ba0c9966cd" />
<img width="412" height="236" alt="sample code output (light)" src="https://github.com/user-attachments/assets/32b838df-6378-498b-84a8-9a79ee6264a7" />
<img width="412" height="236" alt="sample code output (dark)" src="https://github.com/user-attachments/assets/32b838df-6378-498b-84a8-9a79ee6264a7" />
<img width="412" height="236" alt="sample code output (light)" src="https://github.com/user-attachments/assets/f075e2b0-98de-4be8-acb4-99ba0c9966cd" />
```cpp
// Create a window called "My First Tool", with a menu bar.
@@ -150,10 +150,10 @@ Officially maintained backends (in repository):
- 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 our newer [dear_bindings](https://github.com/dearimgui/dear_bindings)), you can use their metadata output to generate bindings for other languages.
<img width="878" height="220" alt="Useful extensions" src="https://github.com/user-attachments/assets/e6b0aa7c-bf53-41c5-ac69-bea3098b1dee" />
[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).
[![Useful extensions thumbnails](https://github.com/user-attachments/assets/e6b0aa7c-bf53-41c5-ac69-bea3098b1dee)](https://github.com/ocornut/imgui/wiki/Useful-Extensions)
- 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), [ImPlot3d](https://github.com/brenocq/implot3d) and [Dear ImGui Test Engine](https://github.com/ocornut/imgui_test_engine).
Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas.
+17
View File
@@ -0,0 +1,17 @@
# Security Policy
Dear ImGui is primarily designed for developer tools and technical applications running trusted code and trusted data.
Given that the library was not designed as a hardened security boundary against hostile or intentionally malformed inputs:
consider not using it in a context where a crash (through e.g. intentionally malformed inputs) could lead to privilege elevation.
E.g. running in a privileged process and interacting with non-privileged clients feeding code or data to Dear ImGui.
Dear ImGui development efforts are focused on improving developer experience, usability, correctness, and robustness in real-world applications.
We will do our best to reduce e.g. crashes caused by common programmer mistakes.
However, the project does not specifically focus on adversarial fuzzing scenarios, allocation-failure hardening, or highly artificial edge cases that are unlikely to occur in normal usage.
## Reporting a Vulnerability
Considering the above policy, most things may be reported in GitHub Issues.
If you have a reason to disclose privately, please reach out to the contact address listed in README.
+13 -29
View File
@@ -2,12 +2,14 @@ dear imgui
ISSUES & TODO LIST
Issue numbers (#) refer to GitHub issues listed at https://github.com/ocornut/imgui/issues/XXXX
THIS LIST IS NOT WELL MAINTAINED. MOST OF THE WORK HAPPENS ON GITHUB NOWADAYS.
The list below consist mostly of ideas noted down before they are requested/discussed by users (at which point they usually exist on the github issue tracker).
It's mostly a bunch of personal notes, probably incomplete. Feel free to query if you have any questions.
- doc: add a proper documentation system (maybe relying on automation? #435)
- doc: checklist app to verify backends/integration of imgui (test inputs, rendering, callback, etc.).
- doc: add a proper documentation system (maybe relying on automation? #435)
- doc/tips: tips of the day: website? applet in imgui_club?
- window: preserve/restore relative focus ordering (persistent or not), and e.g. of multiple reappearing windows (#2304) -> also see docking reference to same #.
@@ -29,9 +31,9 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- window/clipping: some form of clipping when DisplaySize (or corresponding viewport) is zero.
- window/tabbing: add a way to signify that a window or docked window requires attention (e.g. blinking title bar, trying to click behind a modal).
- window/id_stack: add e.g. window->GetIDFromPath() with support for leading / and ../ (#1390, #331) -> model from test engine.
! scrolling: exposing horizontal scrolling with Shift+Wheel even when scrollbar is disabled expose lots of issues (#2424, #1463)
! scrolling: exposing horizontal scrolling with Shift+Wheel even when scrollbar is disabled expose various issues (#2424, #1463)
- scrolling: while holding down a scrollbar, try to keep the same contents visible (at least while not moving mouse)
- scrolling: allow immediately effective change of scroll after Begin() if we haven't appended items yet.
- scrolling: forward mouse wheel scrolling to parent window when at the edge of scrolling limits? (useful for listbox,tables?)
- scrolling/style: shadows on scrollable areas to denote that there is more contents (see e.g. DaVinci Resolve ui)
@@ -51,38 +53,32 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- widgets: display mode: widget-label, label-widget (aligned on column or using fixed size), label-newline-tab-widget etc. (#395)
- widgets: clean up widgets internal toward exposing everything and stabilizing imgui_internals.h.
- widgets: add always-allow-overlap mode. This should perhaps be the default? one problem is that highlight after mouse-wheel scrolling gets deferred, makes scrolling more flickery.
- widgets: start exposing PushItemFlag() and ImGuiItemFlags
- widgets: alignment options in style (e.g. center Selectable, Right-Align within Button, etc.) #1260
- widgets: activate by identifier (trigger button, focus given id)
- widgets: custom glyph/shapes replacements for stock shapes. (also #6090 #2431 #2235 #6517)
- widgets: coloredit: keep reporting as active when picker is on?
- widgets: group/scalarn functions: expose more per-component information. e.g. store NextItemData.ComponentIdx set by scalarn function, groups can expose them back somehow.
- widgets: group/ScalarN functions: expose more per-component information. e.g. store NextItemData.ComponentIdx set by scalarn function, groups can expose them back somehow.
- selectable: using (size.x == 0.0f) and (SelectableTextAlign.x > 0.0f) followed by SameLine() is currently not supported.
- selectable: generic BeginSelectable()/EndSelectable() mechanism. (work out alongside range-select branch)
- selectable: a way to visualize partial/mixed selection (e.g. parent tree node has children with mixed selection)
- input text: flag to disable live update of the user buffer (also applies to float/int text input) (#701)
- input text: preserve scrolling when unfocused?
- input text: reorganize event handling, allow CharFilter to modify buffers, allow multiple events? (#541)
- input text: expose CursorPos in char filter event (#816)
- input text: try usage idiom of using InputText with data only exposed through get/set accessors, without extraneous copy/alloc. (#3009)
- input text: access public fields via a non-callback API e.g. InputTextGetState("xxx") that may return nullptr if not active (available in internals)
- input text: flag to disable live update of the user buffer (also applies to float/int text input) (#701)
- input text: hover tooltip could show unclamped text
- input text: support for INSERT key to toggle overwrite mode. currently disabled because stb_textedit behavior is unsatisfactory on multi-line. (#2863)
- input text: option to Tab after an Enter validation.
- input text: add ImGuiInputTextFlags_EnterToApply? (off #218)
- input text: easier ways to update buffer (from source char*) while owned. preserve some sort of cursor position for multi-line text.
- input text: add discard flag (e.g. ImGuiInputTextFlags_DiscardActiveBuffer) or make it easier to clear active focus for text replacement during edition (#725)
- input text: display bug when clicking a drag/slider after an input text in a different window has all-selected text (order dependent). actually a very old bug but no one appears to have noticed it.
- input text: allow centering/positioning text so that ctrl+clicking Drag or Slider keeps the textual value at the same pixel position.
- input text: decorrelate display layout from inputs with custom template - e.g. what's the easiest way to implement a nice IP/Mac address input editor?
- input text: global callback system so user can plug in an expression evaluator easily. (#1691)
- input text: callback system (global) so user can plug in an expression evaluator easily. (#1691)
- input text: force scroll to end or scroll to a given line/contents (so user can implement a log or a search feature)
- input text: a way to preview completion (e.g. disabled text completing from the cursor)
- input text: a side bar that could e.g. preview where errors are. probably left to the user to draw but we'd need to give them the info there.
- input text: a way for the user to provide syntax coloring.
- input text: Shift+TAB with ImGuiInputTextFlags_AllowTabInput could eat preceding blanks, up to tab_count.
- input text multi-line: don't directly call AddText() which does an unnecessary vertex reserve for character count prior to clipping. and/or more line-based clipping to AddText(). and/or reorganize TextUnformatted/RenderText for more efficiency for large text (e.g TextUnformatted could clip and log separately, etc).
- input text multi-line: support for copy/cut without selection (copy/cut current line?)
- input text multi-line: line numbers? status bar? (follow up on #200)
- input text multi-line: behave better when user changes input buffer while editing is active (even though it is illegal behavior). namely, the change of buffer can create a scrollbar glitch (#725)
@@ -111,11 +107,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
!- color: the color conversion helpers/types are a mess and needs sorting out.
- color: (api breaking) ImGui::ColorConvertXXX functions should be loose ImColorConvertXX to match imgui_internals.h
- plot: full featured plot/graph api w/ scrolling, zooming etc. --> promote using ImPlot
- (plot: deleted all other todo lines on 2023-06-28)
- clipper: ability to disable the clipping through a simple flag/bool.
- clipper: ability to run without knowing full count in advance.
- clipper: horizontal clipping support. (#2580)
- separator: expose flags (#759)
@@ -141,22 +133,19 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- knob: rotating knob widget (#942)
- drag float: support for reversed drags (min > max) (removed is_locked, also see fdc526e)
- drag float: up/down axis
- drag float: power != 0.0f with current value being outside the range keeps the value stuck.
- drag float: added leeway on edge (e.g. a few invisible steps past the clamp limits)
- combo: a way/helper to customize the combo preview (#1658) -> experimental BeginComboPreview()
- combo/listbox: keyboard control. need InputText-like non-active focus + key handling. considering keyboard for custom listbox (pr #203)
- listbox: multiple selection (WIP range-select branch)
- listbox: unselect option (#1208)
- listbox: make it easier/more natural to implement range-select (need some sort of info/ref about the last clicked/focused item that user can translate to an index?) (WIP range-select branch)
- listbox: user may want to initial scroll to focus on the one selected value?
- listbox: disable capturing mouse wheel if the listbox has no scrolling. (#1681)
- listbox: scrolling should track modified selection.
- listbox: future api should allow to enable horizontal scrolling (#2510)
!- popups/menus: clarify usage of popups id, how MenuItem/Selectable closing parent popups affects the ID, etc. this is quite fishy needs improvement! (#331, #402)
- modals: make modal title bar blink when trying to click outside the modal
- modals: technically speaking, we could make Begin() with ImGuiWindowFlags_Modal work without involving popup. May help untangle a few things, as modals are more like regular windows than popups.
- modals: make modal title bar blink when trying to click outside the modal.
- modals: technically speaking, we could make Begin() with ImGuiWindowFlags_Modal work without involving popup. May help untangle a few things, as modals are more like regular windows than popups. (#402)
- popups: if the popup functions took explicit ImGuiID it would allow the user to manage the scope of those ID. (#331)
- popups: clicking outside (to close popup) and holding shouldn't drag window below.
- popups: add variant using global identifier similar to Begin/End (#402)
@@ -198,7 +187,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- style: FramePadding could be different for up vs down (#584)
- style: WindowPadding needs to be EVEN as the 0.5 multiplier used on this value probably have a subtle effect on clip rectangle
- style: have a more global HSV setter (e.g. alter hue on all elements). consider replacing active/hovered by offset in HSV space? (#438, #707, #1223)
- style: gradients fill (#1223) ~ 2 bg colors for each fill? tricky with rounded shapes and using textures for corners.
- style: gradients fill (#4722, #1223) ~ 2 bg colors for each fill? tricky with rounded shapes and using textures for corners.
- style editor: color child window height expressed in multiple of line height.
- log: improve logging of ArrowButton, ListBox, TabItem
@@ -214,7 +203,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- filters: fuzzy matches (may use code at blog.forrestthewoods.com/4cffeed33fdb)
- drag and drop: focus drag target window on hold (even without open)
- drag and drop: releasing a drop shows the "..." tooltip for one frame - since e13e598 (#1725)
- drag and drop: drag source on a group object (would need e.g. an invisible button covering group in EndGroup) https://twitter.com/paniq/status/1121446364909535233
- drag and drop: have some way to know when a drag begin from BeginDragDropSource() pov. (see 2018/01/11 post in #143)
- drag and drop: allow preview tooltip to be submitted from a different place than the drag source. (#1725)
@@ -247,7 +235,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- font: make it easier to submit own bitmap font (same texture, another texture?). (#2127, #2575)
- font: MemoryTTF taking ownership confusing/not obvious, maybe default should be opposite?
- font: storing MinAdvanceX per font would allow us to skip calculating line width (under a threshold of character count) in loops looking for block width
- font/demo: demonstrate use of ImFontGlyphRangesBuilder.
- font/draw: vertical and/or rotated text renderer (#705) - vertical is easier clipping wise
- font/draw: need to be able to specify wrap start position.
- font/draw: better reserve policy for large horizontal block of text (shouldn't reserve for all clipped lines). also see #3349.
@@ -273,12 +260,11 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- nav: NavFlattened: ESC on a flattened child should select something.
- nav: NavFlattened: broken: in typical usage scenario, the items of a fully clipped child are currently not considered to enter into a NavFlattened child.
- nav: NavFlattened: cannot access menu-bar of a flattened child window with Alt/menu key (not a very common use case..).
- nav: simulate right-click or context activation? (SHIFT+F10, keyboard Menu key?)
- nav/popup: esc/enter default behavior for popups, e.g. be able to mark an "ok" or "cancel" button that would get triggered by those keys, default validation button, etc.
- nav/treenode: left within a tree node block as a fallback (ImGuiTreeNodeFlags_NavLeftJumpsBackHere by default?)
- nav/menus: pressing left-right on a vertically clipped menu bar tends to jump to the collapse/close buttons.
- nav/menus: allow pressing Menu to leave a sub-menu.
- nav/menus: a way to access the main menu bar with Alt? (currently needs CTRL+TAB) or last focused window menu bar?
! nav/menus: a way to access the main menu bar with Alt? (currently needs CTRL+TAB) or last focused window menu bar?
- nav/menus: when using the main menu bar, even though we restore focus after, the underlying window loses its title bar highlight during menu manipulation. could we prevent it?
- nav/menus: main menu bar currently cannot restore a nullptr focus. Could save NavWindow at the time of being focused, similarly to what popup do?
- nav/menus: Alt,Up could open the first menu (e.g. "File") currently it tends to nav into the window/collapse menu. Do do that we would need custom transition?
@@ -297,7 +283,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- misc: no way to run a root-most GetID() with ImGui:: api since there's always a Debug window in the stack. (mentioned in #2960)
- misc: make the ImGuiCond values linear (non-power-of-two). internal storage for ImGuiWindow can use integers to combine into flags (Why?)
- misc: PushItemFlag(): add a flag to disable keyboard capture when used with mouse? (#1682)
- misc: use more size_t in public api?
- misc: support for string view/range instead of char* would e.g. facilitate usage with Rust (#683, #3038, WIP string_view branch)
- demo: demonstrate using PushStyleVar() in more details.
@@ -315,8 +300,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- backends: opengl: could use a single vertex buffer and glBufferSubData for uploads?
- backends: opengl: explicitly disable GL_STENCIL_TEST in bindings.
- backends: vulkan: viewport: support for synchronized swapping of multiple swap chains.
- backends: bgfx: https://gist.github.com/RichardGale/6e2b74bc42b3005e08397236e4be0fd0
- backends: emscripten: with refactored examples, we could provide a direct imgui_impl_emscripten platform layer (see eg. https://github.com/floooh/sokol-samples/blob/master/html5/imgui-emsc.cc#L42)
- backends: emscripten: dedicated backend? (#8178, #9120, eg. https://github.com/floooh/sokol-samples/blob/master/html5/imgui-emsc.cc#L42)
- bindings: ways to use clang ast dump to generate bindings or helpers for bindings? (e.g. clang++ -Xclang -ast-dump=json imgui.h) (--> use https://github.com/dearimgui/dear_bindings)
@@ -28,27 +28,27 @@
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
+23
View File
@@ -0,0 +1,23 @@
# Makefile for example_apple_cpu, for macOS only
CXX = clang++
EXE = example_apple_cpu
IMGUI_DIR = ../..
SOURCES = main.mm
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_osx.mm $(IMGUI_DIR)/backends/imgui_impl_cpu.cpp
OPTFLAGS ?= -O2
CXXFLAGS = -std=c++11 -ObjC++ -fobjc-arc -g $(OPTFLAGS) -Wall -Wextra -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
FRAMEWORKS = -framework Cocoa -framework GameController
all: $(EXE)
@echo Build complete for Mac OS X
$(EXE): $(SOURCES)
$(CXX) $(CXXFLAGS) $(SOURCES) -o $(EXE) $(FRAMEWORKS)
run: all
./$(EXE)
clean:
rm -f $(EXE) *.o
+14
View File
@@ -0,0 +1,14 @@
# How to Build
## macOS
Use the provided `Makefile` or directly:
```sh
clang++ -std=c++11 -ObjC++ -fobjc-arc -I ../.. -I ../../backends \
main.mm ../../backends/imgui_impl_osx.mm ../../backends/imgui_impl_cpu.cpp ../../imgui*.cpp \
-framework Cocoa -framework GameController \
-o example_apple_cpu
```
This example uses Cocoa + `imgui_impl_osx` for windowing/input and `imgui_impl_cpu` for rendering.
It renders to a native BGRA CPU framebuffer and does not use SDL.
Binary file not shown.
+424
View File
@@ -0,0 +1,424 @@
// Dear ImGui: standalone macOS example using Cocoa + CPU framebuffer rendering.
// 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
#import <Cocoa/Cocoa.h>
#include "imgui.h"
#include "imgui_impl_cpu.h"
#include "imgui_impl_osx.h"
#include <chrono>
#include <cmath>
#include <string.h>
struct ExampleTimingHistory
{
double Samples[120];
int Count;
int Offset;
ExampleTimingHistory() : Count(0), Offset(0) { memset(Samples, 0, sizeof(Samples)); }
void AddSample(double value_ms)
{
Samples[Offset] = value_ms;
Offset = (Offset + 1) % IM_ARRAYSIZE(Samples);
if (Count < IM_ARRAYSIZE(Samples))
Count++;
}
double GetAverageMs() const
{
if (Count == 0)
return 0.0;
double total = 0.0;
for (int i = 0; i < Count; i++)
total += Samples[i];
return total / (double)Count;
}
};
struct ExampleFramebuffer
{
ImVector<unsigned char> Storage;
ImGui_ImplCPU_Framebuffer CPU;
CGColorSpaceRef ColorSpace;
CGDataProviderRef DataProvider;
CGImageRef Image;
ExampleFramebuffer() : ColorSpace(nullptr), DataProvider(nullptr), Image(nullptr)
{
CPU.Pixels = nullptr;
CPU.Width = 0;
CPU.Height = 0;
CPU.Pitch = 0;
CPU.Format = nullptr;
}
};
static double ExampleGetTimeMs()
{
typedef std::chrono::steady_clock Clock;
return std::chrono::duration<double, std::milli>(Clock::now().time_since_epoch()).count();
}
static void DestroyFramebuffer(ExampleFramebuffer* framebuffer)
{
if (framebuffer->Image != nullptr)
{
CGImageRelease(framebuffer->Image);
framebuffer->Image = nullptr;
}
if (framebuffer->DataProvider != nullptr)
{
CGDataProviderRelease(framebuffer->DataProvider);
framebuffer->DataProvider = nullptr;
}
if (framebuffer->ColorSpace != nullptr)
{
CGColorSpaceRelease(framebuffer->ColorSpace);
framebuffer->ColorSpace = nullptr;
}
framebuffer->CPU.Pixels = nullptr;
framebuffer->CPU.Width = 0;
framebuffer->CPU.Height = 0;
framebuffer->CPU.Pitch = 0;
framebuffer->Storage.clear();
}
static ImU32 PackBGRA(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
{
#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
return ((ImU32)b << 24) | ((ImU32)g << 16) | ((ImU32)r << 8) | (ImU32)a;
#else
return (ImU32)b | ((ImU32)g << 8) | ((ImU32)r << 16) | ((ImU32)a << 24);
#endif
}
static bool RecreateFramebuffer(ExampleFramebuffer* framebuffer, int width, int height)
{
DestroyFramebuffer(framebuffer);
framebuffer->Storage.resize(width * height * 4);
framebuffer->CPU.Pixels = framebuffer->Storage.Data;
framebuffer->CPU.Width = width;
framebuffer->CPU.Height = height;
framebuffer->CPU.Pitch = width * 4;
framebuffer->CPU.Format = ImGui_ImplCPU_GetBuiltinPixelFormat(ImGui_ImplCPU_BuiltinFormat_BGRA8888);
if (framebuffer->CPU.Pixels == nullptr)
return false;
framebuffer->ColorSpace = CGColorSpaceCreateDeviceRGB();
if (framebuffer->ColorSpace == nullptr)
{
DestroyFramebuffer(framebuffer);
return false;
}
framebuffer->DataProvider = CGDataProviderCreateWithData(nullptr, framebuffer->CPU.Pixels, (size_t)framebuffer->CPU.Pitch * (size_t)framebuffer->CPU.Height, nullptr);
if (framebuffer->DataProvider == nullptr)
{
DestroyFramebuffer(framebuffer);
return false;
}
framebuffer->Image = CGImageCreate((size_t)framebuffer->CPU.Width, (size_t)framebuffer->CPU.Height, 8, 32, (size_t)framebuffer->CPU.Pitch, framebuffer->ColorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst, framebuffer->DataProvider, nullptr, false, kCGRenderingIntentDefault);
if (framebuffer->Image == nullptr)
{
DestroyFramebuffer(framebuffer);
return false;
}
return true;
}
static void ClearFramebuffer(ImGui_ImplCPU_Framebuffer* framebuffer, unsigned char r, unsigned char g, unsigned char b, unsigned char a)
{
const ImU32 pixel = PackBGRA(r, g, b, a);
for (int y = 0; y < framebuffer->Height; y++)
{
ImU32* dst = (ImU32*)(void*)(framebuffer->Pixels + (size_t)y * (size_t)framebuffer->Pitch);
for (int x = 0; x < framebuffer->Width; x++)
dst[x] = pixel;
}
}
//-----------------------------------------------------------------------------------
// AppView
//-----------------------------------------------------------------------------------
@interface AppView : NSView
- (void)shutdownImGui;
@end
@implementation AppView
{
ExampleFramebuffer _framebuffer;
ExampleTimingHistory _rasterTimes;
ExampleTimingHistory _presentTimes;
BOOL _imguiInitialized;
BOOL _frameScheduled;
}
- (instancetype)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
return self;
}
- (BOOL)isFlipped
{
return YES;
}
- (void)viewDidMoveToWindow
{
[super viewDidMoveToWindow];
if (self.window != nil && !_imguiInitialized)
[self initializeImGui];
}
- (void)dealloc
{
[self shutdownImGui];
}
- (void)initializeImGui
{
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
ImGui::StyleColorsDark();
ImGui_ImplOSX_Init(self);
ImGui_ImplCPU_Init();
_imguiInitialized = YES;
[self scheduleNextFrameAfter:0.0];
}
- (void)shutdownImGui
{
if (!_imguiInitialized)
return;
DestroyFramebuffer(&_framebuffer);
ImGui_ImplCPU_Shutdown();
ImGui_ImplOSX_Shutdown();
ImGui::DestroyContext();
_imguiInitialized = NO;
}
// Queue the next draw on the main loop instead of pacing to display refresh.
- (void)scheduleNextFrameAfter:(double)delay_seconds
{
if (_frameScheduled)
return;
_frameScheduled = YES;
dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay_seconds * (double)NSEC_PER_SEC));
dispatch_after(when, dispatch_get_main_queue(), ^{
self->_frameScheduled = NO;
[self setNeedsDisplay:YES];
});
}
- (void)renderFrame
{
if (!_imguiInitialized)
return;
if (self.window == nil || [self.window isMiniaturized])
{
[self scheduleNextFrameAfter:0.01];
return;
}
const CGFloat scale = self.window.backingScaleFactor > 0.0 ? self.window.backingScaleFactor : 1.0;
const int logical_w = (int)llround(self.bounds.size.width);
const int logical_h = (int)llround(self.bounds.size.height);
const int framebuffer_w = (int)llround(self.bounds.size.width * scale);
const int framebuffer_h = (int)llround(self.bounds.size.height * scale);
if (framebuffer_w <= 0 || framebuffer_h <= 0)
{
[self scheduleNextFrameAfter:0.01];
return;
}
if (_framebuffer.CPU.Width != framebuffer_w || _framebuffer.CPU.Height != framebuffer_h)
if (!RecreateFramebuffer(&_framebuffer, framebuffer_w, framebuffer_h))
return;
// Start the Dear ImGui frame
ImGui_ImplCPU_NewFrame();
ImGui_ImplOSX_NewFrame(self);
ImGui::NewFrame();
// Our state
static bool show_demo_window = true;
static bool show_another_window = false;
static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
// 1. Show the big demo window
if (show_demo_window)
ImGui::ShowDemoWindow(&show_demo_window);
// 2. Show a simple window that we create ourselves.
{
static float f = 0.0f;
static int counter = 0;
ImGuiIO& io = ImGui::GetIO();
ImGui::Begin("Hello, world!");
ImGui::Text("This is some useful text.");
ImGui::Checkbox("Demo Window", &show_demo_window);
ImGui::Checkbox("Another Window", &show_another_window);
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
ImGui::ColorEdit3("clear color", (float*)&clear_color);
if (ImGui::Button("Button"))
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);
ImGui::Text("Raster %.3f ms | Present %.3f ms", _rasterTimes.GetAverageMs(), _presentTimes.GetAverageMs());
ImGui::Text("Window %d x %d | Framebuffer %d x %d (scale %.2f)", logical_w, logical_h, framebuffer_w, framebuffer_h, scale);
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);
ImGui::Text("Hello from another window!");
if (ImGui::Button("Close Me"))
show_another_window = false;
ImGui::End();
}
// Rendering
ImGui::Render();
const double raster_start_ms = ExampleGetTimeMs();
ClearFramebuffer(&_framebuffer.CPU,
(unsigned char)(clear_color.x * 255),
(unsigned char)(clear_color.y * 255),
(unsigned char)(clear_color.z * 255),
(unsigned char)(clear_color.w * 255));
ImGui_ImplCPU_RenderDrawData(ImGui::GetDrawData(), &_framebuffer.CPU);
_rasterTimes.AddSample(ExampleGetTimeMs() - raster_start_ms);
}
- (void)drawRect:(NSRect)dirtyRect
{
IM_UNUSED(dirtyRect);
[self renderFrame];
if (_framebuffer.Image != nullptr)
{
CGContextRef context = NSGraphicsContext.currentContext.CGContext;
// CGImage draws with a bottom-up raster convention here, while the CPU framebuffer is top-down.
const double present_start_ms = ExampleGetTimeMs();
CGContextSaveGState(context);
CGContextTranslateCTM(context, 0.0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextDrawImage(context, CGRectMake(0.0, 0.0, self.bounds.size.width, self.bounds.size.height), _framebuffer.Image);
CGContextRestoreGState(context);
_presentTimes.AddSample(ExampleGetTimeMs() - present_start_ms);
}
[self scheduleNextFrameAfter:0.0];
}
@end
//-----------------------------------------------------------------------------------
// AppDelegate
//-----------------------------------------------------------------------------------
@interface AppDelegate : NSObject <NSApplicationDelegate>
@property (nonatomic, readonly) NSWindow* window;
@property (nonatomic, readonly) AppView* view;
@end
@implementation AppDelegate
{
NSWindow* _window;
AppView* _view;
}
@synthesize window = _window;
@synthesize view = _view;
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)application
{
IM_UNUSED(application);
return YES;
}
- (void)setupMenu
{
NSMenu* main_menu_bar = [[NSMenu alloc] init];
NSMenu* app_menu = [[NSMenu alloc] initWithTitle:@"Dear ImGui macOS+CPU Example"];
NSMenuItem* menu_item = [app_menu addItemWithTitle:@"Quit Dear ImGui macOS+CPU Example" action:@selector(terminate:) keyEquivalent:@"q"];
[menu_item setKeyEquivalentModifierMask:NSEventModifierFlagCommand];
menu_item = [[NSMenuItem alloc] init];
[menu_item setSubmenu:app_menu];
[main_menu_bar addItem:menu_item];
[NSApp setMainMenu:main_menu_bar];
}
- (void)applicationDidFinishLaunching:(NSNotification*)notification
{
IM_UNUSED(notification);
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
[self setupMenu];
NSRect view_rect = NSMakeRect(100.0, 100.0, 1280.0, 720.0);
_window = [[NSWindow alloc] initWithContentRect:view_rect styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable | NSWindowStyleMaskClosable backing:NSBackingStoreBuffered defer:NO];
[_window setTitle:@"Dear ImGui macOS+CPU Example"];
[_window setAcceptsMouseMovedEvents:YES];
[_window setOpaque:YES];
_view = [[AppView alloc] initWithFrame:_window.contentView.bounds];
[_view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
[_window setContentView:_view];
[_window makeKeyAndOrderFront:NSApp];
[NSApp activateIgnoringOtherApps:YES];
}
- (void)applicationWillTerminate:(NSNotification*)notification
{
IM_UNUSED(notification);
[_view shutdownImGui];
}
@end
int main(int argc, char** argv)
{
IM_UNUSED(argc);
IM_UNUSED(argv);
@autoreleasepool
{
NSApplication* application = [NSApplication sharedApplication];
AppDelegate* delegate = [AppDelegate new];
[application setDelegate:delegate];
[application run];
}
return 0;
}
@@ -28,27 +28,27 @@
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -28,27 +28,27 @@
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -28,27 +28,27 @@
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
+2 -1
View File
@@ -193,7 +193,8 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
{
VkDescriptorPoolSize pool_sizes[] =
{
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE },
{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE },
{ VK_DESCRIPTOR_TYPE_SAMPLER, IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE },
};
VkDescriptorPoolCreateInfo pool_info = {};
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+59 -15
View File
@@ -1,19 +1,24 @@
# Building for desktop (WebGPU-native) with Dawn:
# Building for desktop with Dawn:
# 1. git clone https://github.com/google/dawn dawn
# 2. cmake -B build -DIMGUI_DAWN_DIR=dawn
# 3. cmake --build build
# The resulting binary will be found at one of the following locations:
# * build/Debug/example_glfw_wgpu[.exe]
# * build/example_glfw_wgpu[.exe]
# * build/example_glfw_wgpu[.exe] or build/Debug/example_glfw_wgpu[.exe]
# Building for desktop (WGPU-Native) with WGPU-Native:
# Building for desktop with WGPU-Native:
# 1. download WGPU-Native autogenerated binary modules for your platform/compiler from: https://github.com/gfx-rs/wgpu-native/releases
# 2. unzip the downloaded file in your_preferred_folder
# 3. cmake -B build -DIMGUI_WGPU_DIR=your_preferred_folder ("full path" or "relative" starting from current directory)
# 4. cmake --build build
# The resulting binary will be found at one of the following locations:
# * build/Debug/example_glfw_wgpu[.exe]
# * build/example_glfw_wgpu[.exe]
# * build/example_glfw_wgpu[.exe] or build/Debug/example_glfw_wgpu[.exe]
# Building for desktop with WGVK (MUCH EASIER)
# 1. git clone https://github.com/manuel5975p/WGVK dawn
# 2. cmake -B build -DIMGUI_WGVK_DIR=wgvk
# 3. cmake --build build
# The resulting binary will be found at one of the following locations:
# * build/example_glfw_wgpu[.exe] or build/Debug/example_glfw_wgpu[.exe]
# Building for Emscripten:
# 1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html
@@ -66,13 +71,14 @@ if(EMSCRIPTEN)
set(LIBRARIES glfw)
add_compile_options(-sDISABLE_EXCEPTION_CATCHING=1 -DIMGUI_DISABLE_FILE_FUNCTIONS=1)
else() # Native/Desktop build
# Check DAWN/WGPU directory
if(NOT IMGUI_DAWN_DIR AND NOT IMGUI_WGPU_DIR) # if it's Native/Desktop build, IMGUI_DAWN_DIR or IMGUI_WGPU_DIR must be specified
message(FATAL_ERROR "Please specify the Dawn or WGPU base directory")
endif()
if(IMGUI_DAWN_DIR AND IMGUI_WGPU_DIR) # both IMGUI_DAWN_DIR and IMGUI_WGPU_DIR cannot be set
message(FATAL_ERROR "Please specify only one between Dawn / WGPU base directory")
# Check DAWN/WGPU/WGVK directory
# If it's Native/Desktop build, IMGUI_DAWN_DIR or IMGUI_WGPU_DIR or IMGUI_WGVK_DIR must be specified
if(NOT IMGUI_DAWN_DIR AND NOT IMGUI_WGPU_DIR AND NOT IMGUI_WGVK_DIR)
message(FATAL_ERROR "Please specify one of IMGUI_DAWN_DIR/IMGUI_WGPU_DIR/IMGUI_WGVK_DIR base directory.")
endif()
if((IMGUI_DAWN_DIR AND (IMGUI_WGPU_DIR OR IMGUI_WGVK_DIR)) OR (IMGUI_WGPU_DIR AND IMGUI_WGVK_DIR))
message(FATAL_ERROR "Please specify only one of IMGUI_DAWN_DIR/IMGUI_WGPU_DIR/IMGUI_WGVK_DIR base directory.")
endif()
if(APPLE) # Add SDL2 module to get Surface, with libs and file property for MacOS build
@@ -82,7 +88,7 @@ else() # Native/Desktop build
find_package(glfw3 REQUIRED)
if(IMGUI_DAWN_DIR) # DAWN-Native build options
if(IMGUI_DAWN_DIR)
list(APPEND CMAKE_PREFIX_PATH ${IMGUI_DAWN_DIR})
find_package(Dawn) # Search for a Dawn installation using IMGUI_DAWN_DIR in CMAKE_PREFIX_PATH
if(Dawn_FOUND)
@@ -125,7 +131,9 @@ else() # Native/Desktop build
set(LIBRARIES webgpu_dawn glfw)
endif()
else() # WGPU-Native build options
endif()
if(IMGUI_WGPU_DIR)
set(WGPU_NATIVE_LIB_DIR ${IMGUI_WGPU_DIR}/lib)
find_library(WGPU_LIBRARY NAMES libwgpu_native.a wgpu_native.lib wgpu_native HINTS ${WGPU_NATIVE_LIB_DIR} REQUIRED)
if(WIN32)
@@ -136,6 +144,31 @@ else() # Native/Desktop build
set(LIBRARIES glfw ${WGPU_LIBRARY} ${OS_LIBRARIES})
endif()
if(IMGUI_WGVK_DIR)
find_package(Vulkan REQUIRED)
set(WGVK_PLATFORM_LIBS)
set(WGVK_PLATFORM_DEFS)
if(WIN32)
list(APPEND WGVK_PLATFORM_DEFS SUPPORT_WIN32_SURFACE=1)
elseif(APPLE)
list(APPEND WGVK_PLATFORM_DEFS SUPPORT_METAL_SURFACE=1)
elseif(UNIX)
find_package(PkgConfig QUIET)
pkg_check_modules(WAYLAND_CLIENT QUIET wayland-client)
if(WAYLAND_CLIENT_FOUND)
list(APPEND WGVK_PLATFORM_DEFS SUPPORT_WAYLAND_SURFACE=1)
list(APPEND WGVK_PLATFORM_LIBS ${WAYLAND_CLIENT_LIBRARIES})
endif()
find_package(X11 QUIET)
if(X11_FOUND)
list(APPEND WGVK_PLATFORM_DEFS SUPPORT_XLIB_SURFACE=1)
list(APPEND WGVK_PLATFORM_LIBS X11::X11)
endif()
list(APPEND WGVK_PLATFORM_LIBS m dl pthread)
endif()
set(LIBRARIES glfw Vulkan::Vulkan ${WGVK_PLATFORM_LIBS})
endif()
endif()
add_executable(${IMGUI_EXECUTABLE} ${IMGUI_EXAMPLE_SOURCE_FILES})
@@ -168,10 +201,21 @@ if(NOT EMSCRIPTEN) # WegGPU-Native settings
if(NOT Dawn_FOUND)
target_link_libraries(${IMGUI_EXECUTABLE} INTERFACE webgpu_cpp)
endif()
else()
endif()
if(IMGUI_WGPU_DIR)
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGPU_DIR}/include)
endif()
if(IMGUI_WGVK_DIR)
target_sources(${IMGUI_EXECUTABLE} PRIVATE ${IMGUI_WGVK_DIR}/src/wgvk.c)
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGVK")
target_compile_definitions(${IMGUI_EXECUTABLE} PRIVATE ${WGVK_PLATFORM_DEFS})
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGVK_DIR}/include)
if (MSVC)
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC /std:clatest /experimental:c11atomics)
endif()
endif()
target_link_libraries(${IMGUI_EXECUTABLE} PUBLIC ${LIBRARIES})
else() # Emscripten settings
+9 -5
View File
@@ -65,8 +65,8 @@ int main(int, char**)
// Create window
float main_scale = ImGui_ImplGlfw_GetContentScaleForMonitor(glfwGetPrimaryMonitor()); // Valid on GLFW 3.3+ only
wgpu_surface_width *= main_scale;
wgpu_surface_height *= main_scale;
wgpu_surface_width = (int)(wgpu_surface_width * main_scale);
wgpu_surface_height = (int)(wgpu_surface_height * main_scale);
GLFWwindow* window = glfwCreateWindow(wgpu_surface_width, wgpu_surface_height, "Dear ImGui GLFW+WebGPU example", nullptr, nullptr);
if (window == nullptr)
return 1;
@@ -340,9 +340,10 @@ static WGPUDevice RequestDevice(wgpu::Instance& instance, wgpu::Adapter& adapter
IM_ASSERT(acquired_device != nullptr && waitStatusDevice == wgpu::WaitStatus::Success && "Error on Device request");
return acquired_device.MoveToCHandle();
}
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void* userdata1, void* userdata2)
{
IM_UNUSED(userdata2);
if (status == WGPURequestAdapterStatus_Success)
{
WGPUAdapter* extAdapter = (WGPUAdapter*)userdata1;
@@ -356,6 +357,7 @@ static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter
static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void* userdata1, void* userdata2)
{
IM_UNUSED(userdata2);
if (status == WGPURequestDeviceStatus_Success)
{
WGPUDevice* extDevice = (WGPUDevice*)userdata1;
@@ -439,17 +441,19 @@ bool InitWGPU(GLFWwindow* window)
preferred_fmt = surface_capabilities.formats[0];
// WGPU backend: Adapter and Device acquisition, Surface creation
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
WGPUInstanceDescriptor instanceDesc = {};
WGPUInstanceFeatureName timedWaitAny = WGPUInstanceFeatureName_TimedWaitAny;
instanceDesc.requiredFeatureCount = 1;
instanceDesc.requiredFeatures = &timedWaitAny;
wgpu_instance = wgpuCreateInstance(&instanceDesc);
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
wgpuSetLogCallback(
[](WGPULogLevel level, WGPUStringView msg, void* userdata) { fprintf(stderr, "%s: %.*s\n", ImGui_ImplWGPU_GetLogLevelName(level), (int)msg.length, msg.data); }, nullptr
);
wgpuSetLogLevel(WGPULogLevel_Warn);
#endif
WGPUAdapter adapter = RequestAdapter(wgpu_instance);
ImGui_ImplWGPU_DebugPrintAdapterInfo(adapter);
@@ -549,7 +553,7 @@ WGPUSurface CreateWGPUSurface(const WGPUInstance& instance, GLFWwindow* window)
}
#else
#error "Unsupported WebGPU native platform!"
#endif
return nullptr;
#endif
}
#endif // #ifndef __EMSCRIPTEN__
@@ -28,27 +28,27 @@
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
+5 -4
View File
@@ -21,33 +21,34 @@
<PropertyGroup Label="Globals">
<ProjectGuid>{1A0BF63C-18EF-4BAE-A8DA-055481B11F5D}</ProjectGuid>
<RootNamespace>example_win32_directx11</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
+73
View File
@@ -0,0 +1,73 @@
#
# Cross Platform Makefile (example_sdl2_cpu)
# Compatible with MSYS2/MINGW, Linux and macOS
#
# You will need SDL2 (http://www.libsdl.org):
# Linux: apt-get install libsdl2-dev
# macOS: brew install sdl2
# MSYS2: pacman -S mingw-w64-i686-SDL2
#
EXE = example_sdl2_cpu
IMGUI_DIR = ../..
SOURCES = main.cpp
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl2.cpp $(IMGUI_DIR)/backends/imgui_impl_cpu.cpp
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
UNAME_S := $(shell uname -s)
SDL2_CONFIG ?= $(shell if command -v sdl2-config >/dev/null 2>&1; then command -v sdl2-config; elif [ -x /opt/homebrew/bin/sdl2-config ]; then echo /opt/homebrew/bin/sdl2-config; elif [ -x /usr/local/bin/sdl2-config ]; then echo /usr/local/bin/sdl2-config; else echo sdl2-config; fi)
CXXFLAGS = -std=c++11 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
OPTFLAGS ?= -O2
CXXFLAGS += -g $(OPTFLAGS) -Wall -Wformat
LIBS =
##---------------------------------------------------------------------
## BUILD FLAGS PER PLATFORM
##---------------------------------------------------------------------
ifeq ($(UNAME_S), Linux) #LINUX
ECHO_MESSAGE = "Linux"
LIBS += `$(SDL2_CONFIG) --libs`
CXXFLAGS += `$(SDL2_CONFIG) --cflags`
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(UNAME_S), Darwin) #APPLE
ECHO_MESSAGE = "Mac OS X"
LIBS += `$(SDL2_CONFIG) --libs`
CXXFLAGS += `$(SDL2_CONFIG) --cflags`
CXXFLAGS += -I/usr/local/include -I/opt/local/include
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(OS), Windows_NT)
ECHO_MESSAGE = "MinGW"
LIBS += -lgdi32 `pkg-config --static --libs sdl2`
CXXFLAGS += `pkg-config --cflags sdl2`
CFLAGS = $(CXXFLAGS)
endif
##---------------------------------------------------------------------
## BUILD RULES
##---------------------------------------------------------------------
%.o:%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
%.o:$(IMGUI_DIR)/%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
%.o:$(IMGUI_DIR)/backends/%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
all: $(EXE)
@echo Build complete for $(ECHO_MESSAGE)
$(EXE): $(OBJS)
$(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS)
clean:
rm -f $(EXE) $(OBJS)
@@ -0,0 +1,54 @@
CC = emcc
CXX = em++
WEB_DIR = web
EXE = $(WEB_DIR)/index.html
IMGUI_DIR = ../..
SOURCES = main.cpp
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl2.cpp $(IMGUI_DIR)/backends/imgui_impl_cpu.cpp
OBJS = $(addprefix em_,$(addsuffix .o, $(basename $(notdir $(SOURCES)))))
CPPFLAGS =
LDFLAGS =
EMS =
EMS += -s USE_SDL=2
EMS += -s DISABLE_EXCEPTION_CATCHING=1
LDFLAGS += -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s ASSERTIONS=1
USE_FILE_SYSTEM ?= 0
ifeq ($(USE_FILE_SYSTEM), 0)
LDFLAGS += -s NO_FILESYSTEM=1
CPPFLAGS += -DIMGUI_DISABLE_FILE_FUNCTIONS
endif
ifeq ($(USE_FILE_SYSTEM), 1)
LDFLAGS += --no-heap-copy --preload-file ../../misc/fonts@/fonts
endif
CPPFLAGS += -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
CPPFLAGS += -Wall -Wformat -O2 $(EMS)
LDFLAGS += --shell-file ../libs/emscripten/shell_minimal.html
LDFLAGS += $(EMS)
em_%.o:%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
em_%.o:$(IMGUI_DIR)/%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
em_%.o:$(IMGUI_DIR)/backends/%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
all: $(EXE)
@echo Build complete for $(EXE)
$(WEB_DIR):
mkdir $@
serve: all
python3 -m http.server -d $(WEB_DIR)
$(EXE): $(OBJS) $(WEB_DIR)
$(CXX) -o $@ $(OBJS) $(LDFLAGS)
clean:
rm -rf $(OBJS) $(WEB_DIR)
+47
View File
@@ -0,0 +1,47 @@
# How to Build
## Windows with Visual Studio's IDE
Use the provided project file (`example_sdl2_cpu.vcxproj`) or open `imgui_examples.sln`.
## Windows with Visual Studio's CLI
Use `build_win32.bat` or directly:
```
set SDL2_DIR=path_to_your_sdl2_folder
cl /Zi /MD /utf-8 /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl2.cpp ..\..\backends\imgui_impl_cpu.cpp ..\..\imgui*.cpp /FeDebug/example_sdl2_cpu.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib /subsystem:console
# ^^ include paths ^^ source files ^^ output exe ^^ output dir ^^ libraries
# or for 64-bit:
cl /Zi /MD /utf-8 /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl2.cpp ..\..\backends\imgui_impl_cpu.cpp ..\..\imgui*.cpp /FeDebug/example_sdl2_cpu.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x64 SDL2.lib SDL2main.lib /subsystem:console
```
## Linux and similar Unixes
Use the provided `Makefile` or directly:
```
c++ `sdl2-config --cflags` -I .. -I ../.. -I ../../backends \
main.cpp ../../backends/imgui_impl_sdl2.cpp ../../backends/imgui_impl_cpu.cpp ../../imgui*.cpp \
`sdl2-config --libs`
```
## macOS
Use the provided `Makefile` or directly:
```
brew install sdl2
c++ `sdl2-config --cflags` -I .. -I ../.. -I ../../backends \
main.cpp ../../backends/imgui_impl_sdl2.cpp ../../backends/imgui_impl_cpu.cpp ../../imgui*.cpp \
`sdl2-config --libs`
```
## Emscripten
Use `Makefile.emscripten`:
```sh
source /path/to/emsdk/emsdk_env.sh
make -f Makefile.emscripten
```
This makes `web/index.html`, `web/index.js`, and `web/index.wasm`.
This example keeps Dear ImGui on the CPU and allocates its framebuffer in the active SDL window surface format, rather than forcing a fixed RGBA32 output format.
@@ -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_sdl2_cpu
@set INCLUDES=/I..\.. /I..\..\backends /I%SDL2_DIR%\include
@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl2.cpp ..\..\backends\imgui_impl_cpu.cpp ..\..\imgui*.cpp
@set LIBS=/LIBPATH:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib
mkdir %OUT_DIR%
cl /nologo /Zi /O2 /MD /utf-8 %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
Binary file not shown.
@@ -0,0 +1,187 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{1E9DB182-9BF1-4C7D-8930-85ACAEAC2458}</ProjectGuid>
<RootNamespace>example_sdl2_cpu</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
<ProjectName>example_sdl2_cpu</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>%SDL2_DIR%\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
<IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>%SDL2_DIR%\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
<IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>%SDL2_DIR%\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
<IgnoreSpecificDefaultLibraries>
</IgnoreSpecificDefaultLibraries>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>%SDL2_DIR%\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
<IgnoreSpecificDefaultLibraries>
</IgnoreSpecificDefaultLibraries>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\imgui.cpp" />
<ClCompile Include="..\..\imgui_demo.cpp" />
<ClCompile Include="..\..\imgui_draw.cpp" />
<ClCompile Include="..\..\imgui_tables.cpp" />
<ClCompile Include="..\..\imgui_widgets.cpp" />
<ClCompile Include="..\..\backends\imgui_impl_sdl2.cpp" />
<ClCompile Include="..\..\backends\imgui_impl_cpu.cpp" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\imconfig.h" />
<ClInclude Include="..\..\imgui.h" />
<ClInclude Include="..\..\imgui_internal.h" />
<ClInclude Include="..\..\backends\imgui_impl_sdl2.h" />
<ClInclude Include="..\..\backends\imgui_impl_cpu.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\misc\debuggers\imgui.natstepfilter" />
<None Include="..\..\misc\debuggers\imgui.natvis" />
<None Include="..\README.txt" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="imgui">
<UniqueIdentifier>{20b90ce4-7fcb-4731-b9a0-075f875de82d}</UniqueIdentifier>
</Filter>
<Filter Include="sources">
<UniqueIdentifier>{f18ab499-84e1-499f-8eff-9754361e0e52}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\imgui.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="..\..\imgui_demo.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="..\..\imgui_draw.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="main.cpp">
<Filter>sources</Filter>
</ClCompile>
<ClCompile Include="..\..\imgui_tables.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="..\..\imgui_widgets.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="..\..\backends\imgui_impl_sdl2.cpp">
<Filter>sources</Filter>
</ClCompile>
<ClCompile Include="..\..\backends\imgui_impl_cpu.cpp">
<Filter>sources</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\imconfig.h">
<Filter>imgui</Filter>
</ClInclude>
<ClInclude Include="..\..\imgui.h">
<Filter>imgui</Filter>
</ClInclude>
<ClInclude Include="..\..\imgui_internal.h">
<Filter>imgui</Filter>
</ClInclude>
<ClInclude Include="..\..\backends\imgui_impl_cpu.h">
<Filter>sources</Filter>
</ClInclude>
<ClInclude Include="..\..\backends\imgui_impl_sdl2.h">
<Filter>sources</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\README.txt" />
<None Include="..\..\misc\debuggers\imgui.natvis">
<Filter>imgui</Filter>
</None>
<None Include="..\..\misc\debuggers\imgui.natstepfilter">
<Filter>imgui</Filter>
</None>
</ItemGroup>
</Project>
+321
View File
@@ -0,0 +1,321 @@
// main.cpp
// Example program using imgui_impl_cpu backend
#include "imgui.h"
#include "imgui_impl_cpu.h"
#include "imgui_impl_sdl2.h"
#include <SDL.h>
#include <chrono>
#include <stdio.h>
#include <string.h>
#ifdef __EMSCRIPTEN__
#include "../libs/emscripten/emscripten_mainloop_stub.h"
#endif
struct ExampleTimingHistory
{
double Samples[120];
int Count;
int Offset;
ExampleTimingHistory() : Count(0), Offset(0) { memset(Samples, 0, sizeof(Samples)); }
void AddSample(double value_ms)
{
Samples[Offset] = value_ms;
Offset = (Offset + 1) % IM_ARRAYSIZE(Samples);
if (Count < IM_ARRAYSIZE(Samples))
Count++;
}
double GetAverageMs() const
{
if (Count == 0)
return 0.0;
double total = 0.0;
for (int i = 0; i < Count; i++)
total += Samples[i];
return total / (double)Count;
}
};
struct ExampleFramebuffer
{
ImVector<unsigned char> Storage;
ImVector<ImU32> Palette;
ImGui_ImplCPU_PixelFormat Format;
ImGui_ImplCPU_Framebuffer CPU;
SDL_Surface* Surface;
Uint32 SDLFormat;
ExampleFramebuffer() { memset((void*)this, 0, sizeof(*this)); }
};
static double ExampleGetTimeMs()
{
typedef std::chrono::steady_clock Clock;
return std::chrono::duration<double, std::milli>(Clock::now().time_since_epoch()).count();
}
static void InitCPUFormatFromSDL(ImGui_ImplCPU_PixelFormat* out, ImVector<ImU32>* out_palette, const SDL_PixelFormat* format)
{
memset(out, 0, sizeof(*out));
out->BitsPerPixel = format->BitsPerPixel;
out->BytesPerPixel = format->BytesPerPixel;
out->Rmask = format->Rmask;
out->Gmask = format->Gmask;
out->Bmask = format->Bmask;
out->Amask = format->Amask;
out->Rshift = (ImU8)format->Rshift;
out->Gshift = (ImU8)format->Gshift;
out->Bshift = (ImU8)format->Bshift;
out->Ashift = (ImU8)format->Ashift;
out->Rloss = (ImU8)format->Rloss;
out->Gloss = (ImU8)format->Gloss;
out->Bloss = (ImU8)format->Bloss;
out->Aloss = (ImU8)format->Aloss;
out->Palette = nullptr;
out->PaletteSize = 0;
out->MapColorFn = nullptr;
out_palette->clear();
if (format->palette != nullptr && format->palette->colors != nullptr && format->palette->ncolors > 0)
{
out_palette->resize(format->palette->ncolors);
for (int i = 0; i < format->palette->ncolors; i++)
{
const SDL_Color& c = format->palette->colors[i];
(*out_palette)[i] = IM_COL32(c.r, c.g, c.b, c.a);
}
out->Palette = out_palette->Data;
out->PaletteSize = out_palette->Size;
}
}
static bool RecreateFramebuffer(ExampleFramebuffer* framebuffer, SDL_Surface* window_surface)
{
if (framebuffer->Surface != nullptr)
{
SDL_FreeSurface(framebuffer->Surface);
framebuffer->Surface = nullptr;
}
const int width = window_surface->w;
const int height = window_surface->h;
const int bytes_per_pixel = window_surface->format->BytesPerPixel;
if (width <= 0 || height <= 0 || bytes_per_pixel <= 0)
return false;
InitCPUFormatFromSDL(&framebuffer->Format, &framebuffer->Palette, window_surface->format);
framebuffer->Storage.resize(width * height * bytes_per_pixel);
framebuffer->CPU.Pixels = framebuffer->Storage.Data;
framebuffer->CPU.Width = width;
framebuffer->CPU.Height = height;
framebuffer->CPU.Pitch = width * bytes_per_pixel;
framebuffer->CPU.Format = &framebuffer->Format;
framebuffer->SDLFormat = window_surface->format->format;
framebuffer->Surface = SDL_CreateRGBSurfaceWithFormatFrom(framebuffer->CPU.Pixels, width, height, window_surface->format->BitsPerPixel, framebuffer->CPU.Pitch, window_surface->format->format);
return framebuffer->Surface != nullptr;
}
int main(int, char**)
{
// Setup SDL
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
{
printf("Error: %s\n", SDL_GetError());
return -1;
}
// From 2.0.18: Enable native IME.
#ifdef SDL_HINT_IME_SHOW_UI
SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");
#endif
// Create window
float main_scale = ImGui_ImplSDL2_GetContentScaleForDisplay(0);
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_SHOWN);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+CPU Example",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
(int)(1280 * main_scale), (int)(720 * main_scale), window_flags);
if (!window)
{
printf("Error creating window: %s\n", SDL_GetError());
return -1;
}
SDL_Surface* window_surface = SDL_GetWindowSurface(window);
if (!window_surface)
{
printf("Error getting window surface: %s\n", SDL_GetError());
return -1;
}
int win_w = window_surface->w;
int win_h = window_surface->h;
ExampleFramebuffer framebuffer;
if (!RecreateFramebuffer(&framebuffer, window_surface))
{
printf("Error creating framebuffer: %s\n", SDL_GetError());
return -1;
}
// 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
#ifdef __EMSCRIPTEN__
io.IniFilename = nullptr;
#endif
// Setup Dear ImGui style
ImGui::StyleColorsDark();
// Setup scaling
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale); // Bake a fixed style scale.
style.FontScaleDpi = main_scale;
// Setup Platform/Renderer backends
ImGui_ImplSDL2_InitForOther(window);
ImGui_ImplSDL2_SetGamepadMode(ImGui_ImplSDL2_GamepadMode_AutoFirst, nullptr, 0);
ImGui_ImplCPU_Init();
// Our state
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
ExampleTimingHistory raster_times;
ExampleTimingHistory present_times;
// Main loop
bool done = false;
#ifdef __EMSCRIPTEN__
EMSCRIPTEN_MAINLOOP_BEGIN
#else
while (!done)
#endif
{
// Poll and handle events (inputs, window resize, etc.)
SDL_Event event;
while (SDL_PollEvent(&event))
{
ImGui_ImplSDL2_ProcessEvent(&event);
if (event.type == SDL_QUIT)
done = true;
if (event.type == SDL_WINDOWEVENT)
{
if (event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
done = true;
if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED || event.window.event == SDL_WINDOWEVENT_RESIZED)
{
// Recreate framebuffer at new size
window_surface = SDL_GetWindowSurface(window);
int new_w = window_surface->w;
int new_h = window_surface->h;
if (new_w != win_w || new_h != win_h || window_surface->format->format != framebuffer.SDLFormat)
{
if (!RecreateFramebuffer(&framebuffer, window_surface))
{
printf("Error creating framebuffer after resize: %s\n", SDL_GetError());
return -1;
}
win_w = new_w;
win_h = new_h;
}
}
}
}
// Skip rendering when minimized to avoid busy-looping
if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED)
{
SDL_Delay(10);
continue;
}
// Start the Dear ImGui frame
ImGui_ImplCPU_NewFrame();
ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();
int logical_w = 0;
int logical_h = 0;
SDL_GetWindowSize(window, &logical_w, &logical_h);
// 1. Show the big demo window
if (show_demo_window)
ImGui::ShowDemoWindow(&show_demo_window);
// 2. Show a simple window that we create ourselves. Mirror the SDL_Renderer example.
{
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
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
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);
ImGui::Text("Raster %.3f ms | Present %.3f ms", raster_times.GetAverageMs(), present_times.GetAverageMs());
ImGui::Text("Window %d x %d | Framebuffer %d x %d", logical_w, logical_h, framebuffer.CPU.Width, framebuffer.CPU.Height);
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 double raster_start_ms = ExampleGetTimeMs();
SDL_FillRect(framebuffer.Surface, nullptr, SDL_MapRGBA(framebuffer.Surface->format,
(Uint8)(clear_color.x * 255),
(Uint8)(clear_color.y * 255),
(Uint8)(clear_color.z * 255),
(Uint8)(clear_color.w * 255)));
ImGui_ImplCPU_RenderDrawData(ImGui::GetDrawData(), &framebuffer.CPU);
raster_times.AddSample(ExampleGetTimeMs() - raster_start_ms);
const double present_start_ms = ExampleGetTimeMs();
SDL_BlitSurface(framebuffer.Surface, nullptr, window_surface, nullptr);
SDL_UpdateWindowSurface(window);
present_times.AddSample(ExampleGetTimeMs() - present_start_ms);
}
#ifdef __EMSCRIPTEN__
EMSCRIPTEN_MAINLOOP_END;
#endif
ImGui_ImplCPU_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();
if (framebuffer.Surface != nullptr)
SDL_FreeSurface(framebuffer.Surface);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
@@ -29,27 +29,27 @@
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -28,27 +28,27 @@
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -28,27 +28,27 @@
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -29,27 +29,27 @@
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -184,4 +184,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>
+2 -1
View File
@@ -17,7 +17,8 @@ OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
UNAME_S := $(shell uname -s)
CXXFLAGS = -std=c++11 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
CXXFLAGS += -g -Wall -Wformat
OPTFLAGS ?= -O2
CXXFLAGS += -g $(OPTFLAGS) -Wall -Wformat
LIBS =
##---------------------------------------------------------------------
@@ -0,0 +1,54 @@
CC = emcc
CXX = em++
WEB_DIR = web
EXE = $(WEB_DIR)/index.html
IMGUI_DIR = ../..
SOURCES = main.cpp
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl2.cpp $(IMGUI_DIR)/backends/imgui_impl_sdlsurface2.cpp
OBJS = $(addprefix em_,$(addsuffix .o, $(basename $(notdir $(SOURCES)))))
CPPFLAGS =
LDFLAGS =
EMS =
EMS += -s USE_SDL=2
EMS += -s DISABLE_EXCEPTION_CATCHING=1
LDFLAGS += -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s ASSERTIONS=1
USE_FILE_SYSTEM ?= 0
ifeq ($(USE_FILE_SYSTEM), 0)
LDFLAGS += -s NO_FILESYSTEM=1
CPPFLAGS += -DIMGUI_DISABLE_FILE_FUNCTIONS
endif
ifeq ($(USE_FILE_SYSTEM), 1)
LDFLAGS += --no-heap-copy --preload-file ../../misc/fonts@/fonts
endif
CPPFLAGS += -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
CPPFLAGS += -Wall -Wformat -O2 $(EMS)
LDFLAGS += --shell-file ../libs/emscripten/shell_minimal.html
LDFLAGS += $(EMS)
em_%.o:%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
em_%.o:$(IMGUI_DIR)/%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
em_%.o:$(IMGUI_DIR)/backends/%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
all: $(EXE)
@echo Build complete for $(EXE)
$(WEB_DIR):
mkdir $@
serve: all
python3 -m http.server -d $(WEB_DIR)
$(EXE): $(OBJS) $(WEB_DIR)
$(CXX) -o $@ $(OBJS) $(LDFLAGS)
clean:
rm -rf $(OBJS) $(WEB_DIR)
+10
View File
@@ -33,3 +33,13 @@ c++ `sdl2-config --cflags` -I .. -I ../.. -I ../../backends \
main.cpp ../../backends/imgui_impl_sdl2.cpp ../../backends/imgui_impl_sdlsurface2.cpp ../../imgui*.cpp \
`sdl2-config --libs`
```
## Emscripten
Use `Makefile.emscripten`:
```sh
source /path/to/emsdk/emsdk_env.sh
make -f Makefile.emscripten
```
This makes `web/index.html`, `web/index.js`, and `web/index.wasm`.
@@ -5,4 +5,4 @@
@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl2.cpp ..\..\backends\imgui_impl_sdlsurface2.cpp ..\..\imgui*.cpp
@set LIBS=/LIBPATH:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.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
cl /nologo /Zi /O2 /MD /utf-8 %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
+60
View File
@@ -5,7 +5,45 @@
#include "imgui_impl_sdl2.h"
#include "imgui_impl_sdlsurface2.h"
#include <SDL.h>
#include <chrono>
#include <stdio.h>
#include <string.h>
#ifdef __EMSCRIPTEN__
#include "../libs/emscripten/emscripten_mainloop_stub.h"
#endif
struct ExampleTimingHistory
{
double Samples[120];
int Count;
int Offset;
ExampleTimingHistory() : Count(0), Offset(0) { memset(Samples, 0, sizeof(Samples)); }
void AddSample(double value_ms)
{
Samples[Offset] = value_ms;
Offset = (Offset + 1) % IM_ARRAYSIZE(Samples);
if (Count < IM_ARRAYSIZE(Samples))
Count++;
}
double GetAverageMs() const
{
if (Count == 0)
return 0.0;
double total = 0.0;
for (int i = 0; i < Count; i++)
total += Samples[i];
return total / (double)Count;
}
};
static double ExampleGetTimeMs()
{
typedef std::chrono::steady_clock Clock;
return std::chrono::duration<double, std::milli>(Clock::now().time_since_epoch()).count();
}
int main(int, char**)
{
@@ -55,6 +93,9 @@ int main(int, char**)
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
#ifdef __EMSCRIPTEN__
io.IniFilename = nullptr;
#endif
// Setup Dear ImGui style
ImGui::StyleColorsDark();
@@ -73,10 +114,16 @@ int main(int, char**)
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
ExampleTimingHistory raster_times;
ExampleTimingHistory present_times;
// Main loop
bool done = false;
#ifdef __EMSCRIPTEN__
EMSCRIPTEN_MAINLOOP_BEGIN
#else
while (!done)
#endif
{
// Poll and handle events (inputs, window resize, etc.)
SDL_Event event;
@@ -123,6 +170,10 @@ int main(int, char**)
ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();
int logical_w = 0;
int logical_h = 0;
SDL_GetWindowSize(window, &logical_w, &logical_h);
// 1. Show the big demo window
if (show_demo_window)
ImGui::ShowDemoWindow(&show_demo_window);
@@ -146,6 +197,8 @@ int main(int, char**)
ImGui::SameLine();
ImGui::Text("counter = %d", counter);
ImGui::Text("Raster %.3f ms | Present %.3f ms", raster_times.GetAverageMs(), present_times.GetAverageMs());
ImGui::Text("Window %d x %d | Framebuffer %d x %d", logical_w, logical_h, framebuffer->w, framebuffer->h);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
ImGui::End();
}
@@ -163,6 +216,7 @@ int main(int, char**)
// Rendering
ImGui::Render();
const double raster_start_ms = ExampleGetTimeMs();
SDL_FillRect(framebuffer, nullptr, SDL_MapRGBA(framebuffer->format,
(Uint8)(clear_color.x * 255),
(Uint8)(clear_color.y * 255),
@@ -170,10 +224,16 @@ int main(int, char**)
(Uint8)(clear_color.w * 255)));
ImGui_ImplSDLSurface2_RenderDrawData(ImGui::GetDrawData());
raster_times.AddSample(ExampleGetTimeMs() - raster_start_ms);
const double present_start_ms = ExampleGetTimeMs();
SDL_BlitSurface(framebuffer, nullptr, window_surface, nullptr);
SDL_UpdateWindowSurface(window);
present_times.AddSample(ExampleGetTimeMs() - present_start_ms);
}
#ifdef __EMSCRIPTEN__
EMSCRIPTEN_MAINLOOP_END;
#endif
ImGui_ImplSDLSurface2_Shutdown();
ImGui_ImplSDL2_Shutdown();
@@ -28,27 +28,27 @@
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -187,4 +187,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>
+2 -1
View File
@@ -184,7 +184,8 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
{
VkDescriptorPoolSize pool_sizes[] =
{
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE },
{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE },
{ VK_DESCRIPTOR_TYPE_SAMPLER, IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE },
};
VkDescriptorPoolCreateInfo pool_info = {};
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+58 -14
View File
@@ -1,19 +1,24 @@
# Building for desktop (WebGPU-native) with Dawn:
# Building for desktop with Dawn:
# 1. git clone https://github.com/google/dawn dawn
# 2. cmake -B build -DIMGUI_DAWN_DIR=dawn
# 3. cmake --build build
# The resulting binary will be found at one of the following locations:
# * build/Debug/example_sdl2_wgpu[.exe]
# * build/example_sdl2_wgpu[.exe]
# * build/example_sdl2_wgpu[.exe] or build/Debug/example_sdl2_wgpu[.exe]
# Building for desktop (WGPU-Native) with WGPU-Native:
# Building for desktop with WGPU-Native:
# 1. download WGPU-Native autogenerated binary modules for your platform/compiler from: https://github.com/gfx-rs/wgpu-native/releases
# 2. unzip the downloaded file in your_preferred_folder
# 3. cmake -B build -DIMGUI_WGPU_DIR=your_preferred_folder ("full path" or "relative" starting from current directory)
# 4. cmake --build build
# The resulting binary will be found at one of the following locations:
# * build/Debug/example_sdl2_wgpu[.exe]
# * build/example_sdl2_wgpu[.exe]
# * build/example_sdl2_wgpu[.exe] or build/Debug/example_sdl2_wgpu[.exe]
# Building for desktop with WGVK (MUCH EASIER)
# 1. git clone https://github.com/manuel5975p/WGVK dawn
# 2. cmake -B build -DIMGUI_WGVK_DIR=wgvk
# 3. cmake --build build
# The resulting binary will be found at one of the following locations:
# * build/example_sdl2_wgpu[.exe] or build/Debug/example_sdl2_wgpu[.exe]
# Building for Emscripten:
# 1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html
@@ -60,12 +65,14 @@ if(EMSCRIPTEN)
add_compile_options(-sDISABLE_EXCEPTION_CATCHING=1 -DIMGUI_DISABLE_FILE_FUNCTIONS=1)
else() # Native/Desktop build
if(NOT IMGUI_DAWN_DIR AND NOT IMGUI_WGPU_DIR) # if it's Native/Desktop build, IMGUI_DAWN_DIR or IMGUI_WGPU_DIR must be specified
message(FATAL_ERROR "Please specify the Dawn or WGPU base directory")
endif()
if(IMGUI_DAWN_DIR AND IMGUI_WGPU_DIR) # both IMGUI_DAWN_DIR and IMGUI_WGPU_DIR cannot be set
message(FATAL_ERROR "Please specify only one between Dawn / WGPU base directory")
# Check DAWN/WGPU/WGVK directory
# If it's Native/Desktop build, IMGUI_DAWN_DIR or IMGUI_WGPU_DIR or IMGUI_WGVK_DIR must be specified
if(NOT IMGUI_DAWN_DIR AND NOT IMGUI_WGPU_DIR AND NOT IMGUI_WGVK_DIR)
message(FATAL_ERROR "Please specify one of IMGUI_DAWN_DIR/IMGUI_WGPU_DIR/IMGUI_WGVK_DIR base directory.")
endif()
if((IMGUI_DAWN_DIR AND (IMGUI_WGPU_DIR OR IMGUI_WGVK_DIR)) OR (IMGUI_WGPU_DIR AND IMGUI_WGVK_DIR))
message(FATAL_ERROR "Please specify only one of IMGUI_DAWN_DIR/IMGUI_WGPU_DIR/IMGUI_WGVK_DIR base directory.")
endif()
if(APPLE) # Add SDL2 module to get Surface, with libs and file property for MacOS build
@@ -75,7 +82,7 @@ else() # Native/Desktop build
find_package(SDL2 REQUIRED) # SDL_MAIN_HANDLED
if(IMGUI_DAWN_DIR) # DAWN-Native build options
if(IMGUI_DAWN_DIR)
list(APPEND CMAKE_PREFIX_PATH ${IMGUI_DAWN_DIR})
find_package(Threads) # required from Dawn installation
find_package(Dawn) # Search for a Dawn installation using IMGUI_DAWN_DIR in CMAKE_PREFIX_PATH
@@ -119,8 +126,9 @@ else() # Native/Desktop build
set(LIBRARIES webgpu_dawn ${OS_LIBRARIES})
endif()
else() # WGPU-Native build options
endif()
if(IMGUI_WGPU_DIR)
set(WGPU_NATIVE_LIB_DIR ${IMGUI_WGPU_DIR}/lib)
find_library(WGPU_LIBRARY NAMES libwgpu_native.a wgpu_native.lib wgpu_native HINTS ${WGPU_NATIVE_LIB_DIR} REQUIRED)
if(WIN32)
@@ -131,6 +139,32 @@ else() # Native/Desktop build
set(LIBRARIES ${WGPU_LIBRARY} ${OS_LIBRARIES})
endif()
if(IMGUI_WGVK_DIR)
find_package(Vulkan REQUIRED)
set(WGVK_PLATFORM_LIBS)
set(WGVK_PLATFORM_DEFS)
if(WIN32)
list(APPEND WGVK_PLATFORM_DEFS SUPPORT_WIN32_SURFACE=1)
elseif(APPLE)
list(APPEND WGVK_PLATFORM_DEFS SUPPORT_METAL_SURFACE=1)
elseif(UNIX)
find_package(PkgConfig QUIET)
pkg_check_modules(WAYLAND_CLIENT QUIET wayland-client)
if(WAYLAND_CLIENT_FOUND)
list(APPEND WGVK_PLATFORM_DEFS SUPPORT_WAYLAND_SURFACE=1)
list(APPEND WGVK_PLATFORM_LIBS ${WAYLAND_CLIENT_LIBRARIES})
endif()
find_package(X11 QUIET)
if(X11_FOUND)
list(APPEND WGVK_PLATFORM_DEFS SUPPORT_XLIB_SURFACE=1)
list(APPEND WGVK_PLATFORM_LIBS X11::X11)
endif()
list(APPEND WGVK_PLATFORM_LIBS m dl pthread)
endif()
set(LIBRARIES glfw Vulkan::Vulkan ${WGVK_PLATFORM_LIBS})
endif()
endif()
add_executable(${IMGUI_EXECUTABLE} ${IMGUI_EXAMPLE_SOURCE_FILES})
@@ -163,10 +197,20 @@ if(NOT EMSCRIPTEN) # WegGPU-Native settings
if(NOT Dawn_FOUND)
target_link_libraries(${IMGUI_EXECUTABLE} INTERFACE webgpu_cpp)
endif()
else()
endif()
if(IMGUI_WGPU_DIR)
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGPU_DIR}/include)
endif()
if(IMGUI_WGVK_DIR)
target_sources(${IMGUI_EXECUTABLE} PRIVATE ${IMGUI_WGVK_DIR}/src/wgvk.c)
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGVK")
target_compile_definitions(${IMGUI_EXECUTABLE} PRIVATE ${WGVK_PLATFORM_DEFS})
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGVK_DIR}/include)
if (MSVC)
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC /std:clatest /experimental:c11atomics)
endif()
endif()
target_link_libraries(${IMGUI_EXECUTABLE} PUBLIC ${LIBRARIES} ${SDL2_LIBRARIES})
else() # Emscripten settings
+11 -5
View File
@@ -53,7 +53,9 @@ int main(int, char**)
// Create window with graphics context
float main_scale = ImGui_ImplSDL2_GetContentScaleForDisplay(0);
SDL_WindowFlags window_flags = SDL_WINDOW_RESIZABLE;
wgpu_surface_width = (int)(wgpu_surface_width * main_scale);
wgpu_surface_height = (int)(wgpu_surface_height * main_scale);
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+WebGPU example", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, wgpu_surface_width, wgpu_surface_height, window_flags);
if (window == nullptr)
{
@@ -143,7 +145,7 @@ int main(int, char**)
// React to changes in screen size
int width, height;
SDL_GetWindowSize(window, &width, &height);
SDL_GetWindowSizeInPixels(window, &width, &height);
if (width != wgpu_surface_width || height != wgpu_surface_height)
ResizeSurface(width, height);
@@ -324,9 +326,10 @@ static WGPUDevice RequestDevice(wgpu::Instance& instance, wgpu::Adapter& adapter
IM_ASSERT(acquired_device != nullptr && waitStatusDevice == wgpu::WaitStatus::Success && "Error on Device request");
return acquired_device.MoveToCHandle();
}
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void* userdata1, void* userdata2)
{
IM_UNUSED(userdata2);
if (status == WGPURequestAdapterStatus_Success)
{
WGPUAdapter* extAdapter = (WGPUAdapter*)userdata1;
@@ -340,6 +343,7 @@ static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter
static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void* userdata1, void* userdata2)
{
IM_UNUSED(userdata2);
if (status == WGPURequestDeviceStatus_Success)
{
WGPUDevice* extDevice = (WGPUDevice*)userdata1;
@@ -424,17 +428,19 @@ static bool InitWGPU(SDL_Window* window)
preferred_fmt = surface_capabilities.formats[0];
// WGPU backend: Adapter and Device acquisition, Surface creation
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
WGPUInstanceDescriptor instanceDesc = {};
WGPUInstanceFeatureName timedWaitAny = WGPUInstanceFeatureName_TimedWaitAny;
instanceDesc.requiredFeatureCount = 1;
instanceDesc.requiredFeatures = &timedWaitAny;
wgpu_instance = wgpuCreateInstance(&instanceDesc);
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
wgpuSetLogCallback(
[](WGPULogLevel level, WGPUStringView msg, void* userdata) { fprintf(stderr, "%s: %.*s\n", ImGui_ImplWGPU_GetLogLevelName(level), (int)msg.length, msg.data); }, nullptr
);
wgpuSetLogLevel(WGPULogLevel_Warn);
#endif
WGPUAdapter adapter = RequestAdapter(wgpu_instance);
ImGui_ImplWGPU_DebugPrintAdapterInfo(adapter);
@@ -514,7 +520,7 @@ WGPUSurface CreateWGPUSurface(const WGPUInstance& instance, SDL_Window* window)
}
#else
#error "Unsupported WebGPU native platform!"
#endif
return nullptr;
#endif
}
#endif // #ifndef __EMSCRIPTEN__
@@ -29,27 +29,27 @@
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -28,27 +28,27 @@
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -28,27 +28,27 @@
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -186,4 +186,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>
@@ -28,27 +28,27 @@
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
+54
View File
@@ -0,0 +1,54 @@
EXE = example_sdl3_surface
IMGUI_DIR = ../..
SOURCES = main.cpp
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl3.cpp $(IMGUI_DIR)/backends/imgui_impl_sdlsurface3.cpp
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
UNAME_S := $(shell uname -s)
CXXFLAGS = -std=c++11 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
OPTFLAGS ?= -O2
CXXFLAGS += -g $(OPTFLAGS) -Wall -Wformat
LIBS =
ifeq ($(UNAME_S), Linux)
ECHO_MESSAGE = "Linux"
LIBS += -ldl `pkg-config sdl3 --libs`
CXXFLAGS += `pkg-config sdl3 --cflags`
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(UNAME_S), Darwin)
ECHO_MESSAGE = "Mac OS X"
LIBS += -framework Cocoa -framework IOKit -framework CoreVideo
LIBS += `pkg-config --libs sdl3`
LIBS += -L/usr/local/lib -L/opt/local/lib
CXXFLAGS += `pkg-config --cflags sdl3`
CXXFLAGS += -I/usr/local/include -I/opt/local/include
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(OS), Windows_NT)
ECHO_MESSAGE = "MinGW"
LIBS += -lgdi32 -limm32 `pkg-config --static --libs sdl3`
CXXFLAGS += `pkg-config --cflags sdl3`
CFLAGS = $(CXXFLAGS)
endif
%.o:%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
%.o:$(IMGUI_DIR)/%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
%.o:$(IMGUI_DIR)/backends/%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
all: $(EXE)
@echo Build complete for $(ECHO_MESSAGE)
$(EXE): $(OBJS)
$(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS)
clean:
rm -f $(EXE) $(OBJS)
@@ -0,0 +1,58 @@
CC = emcc
CXX = em++
WEB_DIR = web
EXE = $(WEB_DIR)/index.html
IMGUI_DIR = ../..
SOURCES = main.cpp
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl3.cpp $(IMGUI_DIR)/backends/imgui_impl_sdlsurface3.cpp
OBJS = $(addprefix em_,$(addsuffix .o, $(basename $(notdir $(SOURCES)))))
CPPFLAGS =
LDFLAGS =
EMS =
EMS += -s USE_SDL=3
EMS += -s DISABLE_EXCEPTION_CATCHING=1
LDFLAGS += -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s ASSERTIONS=1
LDFLAGS += -s FORCE_FILESYSTEM=1
ifeq ($(shell $(CXX) --show-ports 2>/dev/null | grep -c 'sdl3 '),0)
$(error This Emscripten toolchain does not provide an SDL3 port. Use an SDL3-capable emsdk to build this example for web)
endif
USE_FILE_SYSTEM ?= 0
ifeq ($(USE_FILE_SYSTEM), 0)
CPPFLAGS += -DIMGUI_DISABLE_FILE_FUNCTIONS
endif
ifeq ($(USE_FILE_SYSTEM), 1)
LDFLAGS += --no-heap-copy --preload-file ../../misc/fonts@/fonts
endif
CPPFLAGS += -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
CPPFLAGS += -Wall -Wformat -O2 $(EMS)
LDFLAGS += --shell-file ../libs/emscripten/shell_minimal.html
LDFLAGS += $(EMS)
em_%.o:%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
em_%.o:$(IMGUI_DIR)/%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
em_%.o:$(IMGUI_DIR)/backends/%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
all: $(EXE)
@echo Build complete for $(EXE)
$(WEB_DIR):
mkdir $@
serve: all
python3 -m http.server -d $(WEB_DIR)
$(EXE): $(OBJS) $(WEB_DIR)
$(CXX) -o $@ $(OBJS) $(LDFLAGS)
clean:
rm -rf $(OBJS) $(WEB_DIR)
+43
View File
@@ -0,0 +1,43 @@
# How to Build
## Windows with Visual Studio's IDE
Use the provided project file (`example_sdl3_surface.vcxproj`) or open `imgui_examples.sln`.
## Windows with Visual Studio's CLI
Use `build_win32.bat` or directly:
```bat
set SDL3_DIR=path_to_your_sdl3_folder
cl /Zi /MD /utf-8 /I.. /I..\.. /I%SDL3_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl3.cpp ..\..\backends\imgui_impl_sdlsurface3.cpp ..\..\imgui*.cpp /FeDebug/example_sdl3_surface.exe /FoDebug/ /link /libpath:%SDL3_DIR%\lib\x86 SDL3.lib /subsystem:console
cl /Zi /MD /utf-8 /I.. /I..\.. /I%SDL3_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl3.cpp ..\..\backends\imgui_impl_sdlsurface3.cpp ..\..\imgui*.cpp /FeDebug/example_sdl3_surface.exe /FoDebug/ /link /libpath:%SDL3_DIR%\lib\x64 SDL3.lib /subsystem:console
```
## Linux and similar Unixes
Use the provided `Makefile` or directly:
```sh
c++ `pkg-config --cflags sdl3` -I .. -I ../.. -I ../../backends \
main.cpp ../../backends/imgui_impl_sdl3.cpp ../../backends/imgui_impl_sdlsurface3.cpp ../../imgui*.cpp \
-ldl `pkg-config --libs sdl3`
```
## macOS
Use the provided `Makefile` or directly:
```sh
brew install sdl3
c++ `pkg-config --cflags sdl3` -I .. -I ../.. -I ../../backends \
main.cpp ../../backends/imgui_impl_sdl3.cpp ../../backends/imgui_impl_sdlsurface3.cpp ../../imgui*.cpp \
-framework Cocoa -framework IOKit -framework CoreVideo `pkg-config --libs sdl3`
```
## Emscripten
Use `Makefile.emscripten`:
```sh
source /path/to/emsdk/emsdk_env.sh
make -f Makefile.emscripten
```
This produces `web/index.html`, `web/index.js`, and `web/index.wasm`.
@@ -0,0 +1,7 @@
@set OUT_DIR=Debug
@set OUT_EXE=example_sdl3_surface
@set INCLUDES=/I..\.. /I..\..\backends /I%SDL3_DIR%\include
@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl3.cpp ..\..\backends\imgui_impl_sdlsurface3.cpp ..\..\imgui*.cpp
@set LIBS=/LIBPATH:%SDL3_DIR%\lib\x86 SDL3.lib
mkdir %OUT_DIR%
cl /nologo /Zi /O2 /MD /utf-8 %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
@@ -0,0 +1,187 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{08DD87C0-C734-45D6-9B44-D23F19F2D4B6}</ProjectGuid>
<RootNamespace>example_sdl3_surface</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
<ProjectName>example_sdl3_surface</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>%SDL3_DIR%\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>SDL3.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
<IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>%SDL3_DIR%\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>SDL3.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
<IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>%SDL3_DIR%\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>SDL3.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
<IgnoreSpecificDefaultLibraries>
</IgnoreSpecificDefaultLibraries>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>%SDL3_DIR%\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>SDL3.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
<IgnoreSpecificDefaultLibraries>
</IgnoreSpecificDefaultLibraries>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\imgui.cpp" />
<ClCompile Include="..\..\imgui_demo.cpp" />
<ClCompile Include="..\..\imgui_draw.cpp" />
<ClCompile Include="..\..\imgui_tables.cpp" />
<ClCompile Include="..\..\imgui_widgets.cpp" />
<ClCompile Include="..\..\backends\imgui_impl_sdl3.cpp" />
<ClCompile Include="..\..\backends\imgui_impl_sdlsurface3.cpp" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\imconfig.h" />
<ClInclude Include="..\..\imgui.h" />
<ClInclude Include="..\..\imgui_internal.h" />
<ClInclude Include="..\..\backends\imgui_impl_sdl3.h" />
<ClInclude Include="..\..\backends\imgui_impl_sdlsurface3.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\misc\debuggers\imgui.natstepfilter" />
<None Include="..\..\misc\debuggers\imgui.natvis" />
<None Include="..\README.txt" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="imgui">
<UniqueIdentifier>{20b90ce4-7fcb-4731-b9a0-075f875de82d}</UniqueIdentifier>
</Filter>
<Filter Include="sources">
<UniqueIdentifier>{f18ab499-84e1-499f-8eff-9754361e0e52}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\imgui.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="..\..\imgui_demo.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="..\..\imgui_draw.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="main.cpp">
<Filter>sources</Filter>
</ClCompile>
<ClCompile Include="..\..\imgui_tables.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="..\..\imgui_widgets.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="..\..\backends\imgui_impl_sdl3.cpp">
<Filter>sources</Filter>
</ClCompile>
<ClCompile Include="..\..\backends\imgui_impl_sdlsurface3.cpp">
<Filter>sources</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\imconfig.h">
<Filter>imgui</Filter>
</ClInclude>
<ClInclude Include="..\..\imgui.h">
<Filter>imgui</Filter>
</ClInclude>
<ClInclude Include="..\..\imgui_internal.h">
<Filter>imgui</Filter>
</ClInclude>
<ClInclude Include="..\..\backends\imgui_impl_sdl3.h">
<Filter>sources</Filter>
</ClInclude>
<ClInclude Include="..\..\backends\imgui_impl_sdlsurface3.h">
<Filter>sources</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\README.txt" />
<None Include="..\..\misc\debuggers\imgui.natvis">
<Filter>imgui</Filter>
</None>
<None Include="..\..\misc\debuggers\imgui.natstepfilter">
<Filter>imgui</Filter>
</None>
</ItemGroup>
</Project>
+187
View File
@@ -0,0 +1,187 @@
#include "imgui.h"
#include "imgui_impl_sdl3.h"
#include "imgui_impl_sdlsurface3.h"
#include <SDL3/SDL.h>
#include <stdio.h>
#ifdef __EMSCRIPTEN__
#include "../libs/emscripten/emscripten_mainloop_stub.h"
#endif
int main(int, char**)
{
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD))
{
printf("Error: SDL_Init(): %s\n", SDL_GetError());
return 1;
}
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+Surface Example", (int)(1280 * main_scale), (int)(800 * main_scale), window_flags);
if (window == nullptr)
{
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return 1;
}
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
SDL_ShowWindow(window);
SDL_Surface* window_surface = SDL_GetWindowSurface(window);
if (window_surface == nullptr)
{
printf("Error: SDL_GetWindowSurface(): %s\n", SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
int framebuffer_w = window_surface->w;
int framebuffer_h = window_surface->h;
SDL_Surface* framebuffer = SDL_CreateSurface(framebuffer_w, framebuffer_h, SDL_PIXELFORMAT_RGBA32);
if (framebuffer == nullptr)
{
printf("Error: SDL_CreateSurface(): %s\n", SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
#ifdef __EMSCRIPTEN__
io.IniFilename = nullptr;
#endif
ImGui::StyleColorsDark();
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale);
style.FontScaleDpi = main_scale;
ImGui_ImplSDL3_InitForOther(window);
ImGui_ImplSDLSurface3_Init(framebuffer);
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
bool done = false;
#ifdef __EMSCRIPTEN__
EMSCRIPTEN_MAINLOOP_BEGIN
#else
while (!done)
#endif
{
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.type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED) && event.window.windowID == SDL_GetWindowID(window))
{
window_surface = SDL_GetWindowSurface(window);
if (window_surface != nullptr)
{
int new_w = window_surface->w;
int new_h = window_surface->h;
if (new_w != framebuffer_w || new_h != framebuffer_h)
{
SDL_DestroySurface(framebuffer);
framebuffer = SDL_CreateSurface(new_w, new_h, SDL_PIXELFORMAT_RGBA32);
if (framebuffer == nullptr)
{
printf("Error: SDL_CreateSurface(): %s\n", SDL_GetError());
done = true;
break;
}
framebuffer_w = new_w;
framebuffer_h = new_h;
ImGui_ImplSDLSurface3_Shutdown();
ImGui_ImplSDLSurface3_Init(framebuffer);
}
}
}
}
if (done)
break;
if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED)
{
SDL_Delay(10);
continue;
}
ImGui_ImplSDLSurface3_NewFrame();
ImGui_ImplSDL3_NewFrame();
ImGui::NewFrame();
if (show_demo_window)
ImGui::ShowDemoWindow(&show_demo_window);
{
static float f = 0.0f;
static int counter = 0;
ImGui::Begin("Hello, world!");
ImGui::Text("This is some useful text.");
ImGui::Checkbox("Demo Window", &show_demo_window);
ImGui::Checkbox("Another Window", &show_another_window);
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
ImGui::ColorEdit3("clear color", (float*)&clear_color);
if (ImGui::Button("Button"))
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();
}
if (show_another_window)
{
ImGui::Begin("Another Window", &show_another_window);
ImGui::Text("Hello from another window!");
if (ImGui::Button("Close Me"))
show_another_window = false;
ImGui::End();
}
ImGui::Render();
SDL_FillSurfaceRect(framebuffer, nullptr, SDL_MapSurfaceRGBA(framebuffer,
(Uint8)(clear_color.x * 255.0f),
(Uint8)(clear_color.y * 255.0f),
(Uint8)(clear_color.z * 255.0f),
(Uint8)(clear_color.w * 255.0f)));
ImGui_ImplSDLSurface3_RenderDrawData(ImGui::GetDrawData());
window_surface = SDL_GetWindowSurface(window);
if (window_surface != nullptr)
{
SDL_BlitSurface(framebuffer, nullptr, window_surface, nullptr);
SDL_UpdateWindowSurface(window);
}
}
#ifdef __EMSCRIPTEN__
EMSCRIPTEN_MAINLOOP_END;
#endif
ImGui_ImplSDLSurface3_Shutdown();
ImGui_ImplSDL3_Shutdown();
ImGui::DestroyContext();
SDL_DestroySurface(framebuffer);
SDL_DestroyWindowSurface(window);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
@@ -28,27 +28,27 @@
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
+2 -1
View File
@@ -186,7 +186,8 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
{
VkDescriptorPoolSize pool_sizes[] =
{
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE },
{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE },
{ VK_DESCRIPTOR_TYPE_SAMPLER, IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE },
};
VkDescriptorPoolCreateInfo pool_info = {};
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+58 -14
View File
@@ -1,19 +1,24 @@
# Building for desktop (WebGPU-native) with Dawn:
# Building for desktop with Dawn:
# 1. git clone https://github.com/google/dawn dawn
# 2. cmake -B build -DIMGUI_DAWN_DIR=dawn
# 3. cmake --build build
# The resulting binary will be found at one of the following locations:
# * build/Debug/example_sdl3_wgpu[.exe]
# * build/example_sdl3_wgpu[.exe]
# * build/example_sdl3_wgpu[.exe] or build/Debug/example_sdl3_wgpu[.exe]
# Building for desktop (WGPU-Native) with WGPU-Native:
# Building for desktop with WGPU-Native:
# 1. download WGPU-Native autogenerated binary modules for your platform/compiler from: https://github.com/gfx-rs/wgpu-native/releases
# 2. unzip the downloaded file in your_preferred_folder
# 3. cmake -B build -DIMGUI_WGPU_DIR=your_preferred_folder ("full path" or "relative" starting from current directory)
# 4. cmake --build build
# The resulting binary will be found at one of the following locations:
# * build/Debug/example_sdl3_wgpu[.exe]
# * build/example_sdl3_wgpu[.exe]
# * build/example_sdl3_wgpu[.exe] or build/Debug/example_sdl3_wgpu[.exe]
# Building for desktop with WGVK (MUCH EASIER)
# 1. git clone https://github.com/manuel5975p/WGVK dawn
# 2. cmake -B build -DIMGUI_WGVK_DIR=wgvk
# 3. cmake --build build
# The resulting binary will be found at one of the following locations:
# * build/example_sdl3_wgpu[.exe] or build/Debug/example_sdl3_wgpu[.exe]
# Building for Emscripten:
# 1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html
@@ -60,12 +65,14 @@ if(EMSCRIPTEN)
add_compile_options(-sDISABLE_EXCEPTION_CATCHING=1 -DIMGUI_DISABLE_FILE_FUNCTIONS=1)
else() # Native/Desktop build
if(NOT IMGUI_DAWN_DIR AND NOT IMGUI_WGPU_DIR) # if it's Native/Desktop build, IMGUI_DAWN_DIR or IMGUI_WGPU_DIR must be specified
message(FATAL_ERROR "Please specify the Dawn or WGPU base directory")
endif()
if(IMGUI_DAWN_DIR AND IMGUI_WGPU_DIR) # both IMGUI_DAWN_DIR and IMGUI_WGPU_DIR cannot be set
message(FATAL_ERROR "Please specify only one between Dawn / WGPU base directory")
# Check DAWN/WGPU/WGVK directory
# If it's Native/Desktop build, IMGUI_DAWN_DIR or IMGUI_WGPU_DIR or IMGUI_WGVK_DIR must be specified
if(NOT IMGUI_DAWN_DIR AND NOT IMGUI_WGPU_DIR AND NOT IMGUI_WGVK_DIR)
message(FATAL_ERROR "Please specify one of IMGUI_DAWN_DIR/IMGUI_WGPU_DIR/IMGUI_WGVK_DIR base directory.")
endif()
if((IMGUI_DAWN_DIR AND (IMGUI_WGPU_DIR OR IMGUI_WGVK_DIR)) OR (IMGUI_WGPU_DIR AND IMGUI_WGVK_DIR))
message(FATAL_ERROR "Please specify only one of IMGUI_DAWN_DIR/IMGUI_WGPU_DIR/IMGUI_WGVK_DIR base directory.")
endif()
if(APPLE) # Add SDL3 module to get Surface, with libs and file property for MacOS build
@@ -75,7 +82,7 @@ else() # Native/Desktop build
find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3)
if(IMGUI_DAWN_DIR) # DAWN-Native build options
if(IMGUI_DAWN_DIR)
list(APPEND CMAKE_PREFIX_PATH ${IMGUI_DAWN_DIR})
find_package(Threads) # required from Dawn installation
find_package(Dawn) # Search for a Dawn installation using IMGUI_DAWN_DIR in CMAKE_PREFIX_PATH
@@ -119,7 +126,9 @@ else() # Native/Desktop build
set(LIBRARIES webgpu_dawn ${OS_LIBRARIES})
endif()
else() # WGPU-Native build options
endif()
if(IMGUI_WGPU_DIR)
set(WGPU_NATIVE_LIB_DIR ${IMGUI_WGPU_DIR}/lib)
find_library(WGPU_LIBRARY NAMES libwgpu_native.a wgpu_native.lib wgpu_native HINTS ${WGPU_NATIVE_LIB_DIR} REQUIRED)
if(WIN32)
@@ -130,6 +139,31 @@ else() # Native/Desktop build
set(LIBRARIES ${WGPU_LIBRARY} ${OS_LIBRARIES})
endif()
if(IMGUI_WGVK_DIR)
find_package(Vulkan REQUIRED)
set(WGVK_PLATFORM_LIBS)
set(WGVK_PLATFORM_DEFS)
if(WIN32)
list(APPEND WGVK_PLATFORM_DEFS SUPPORT_WIN32_SURFACE=1)
elseif(APPLE)
list(APPEND WGVK_PLATFORM_DEFS SUPPORT_METAL_SURFACE=1)
elseif(UNIX)
find_package(PkgConfig QUIET)
pkg_check_modules(WAYLAND_CLIENT QUIET wayland-client)
if(WAYLAND_CLIENT_FOUND)
list(APPEND WGVK_PLATFORM_DEFS SUPPORT_WAYLAND_SURFACE=1)
list(APPEND WGVK_PLATFORM_LIBS ${WAYLAND_CLIENT_LIBRARIES})
endif()
find_package(X11 QUIET)
if(X11_FOUND)
list(APPEND WGVK_PLATFORM_DEFS SUPPORT_XLIB_SURFACE=1)
list(APPEND WGVK_PLATFORM_LIBS X11::X11)
endif()
list(APPEND WGVK_PLATFORM_LIBS m dl pthread)
endif()
set(LIBRARIES glfw Vulkan::Vulkan ${WGVK_PLATFORM_LIBS})
endif()
endif()
add_executable(${IMGUI_EXECUTABLE} ${IMGUI_EXAMPLE_SOURCE_FILES})
@@ -162,10 +196,20 @@ if(NOT EMSCRIPTEN) # WegGPU-Native settings
if(NOT Dawn_FOUND)
target_link_libraries(${IMGUI_EXECUTABLE} INTERFACE webgpu_cpp)
endif()
else()
endif()
if(IMGUI_WGPU_DIR)
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGPU_DIR}/include)
endif()
if(IMGUI_WGVK_DIR)
target_sources(${IMGUI_EXECUTABLE} PRIVATE ${IMGUI_WGVK_DIR}/src/wgvk.c)
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGVK")
target_compile_definitions(${IMGUI_EXECUTABLE} PRIVATE ${WGVK_PLATFORM_DEFS})
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGVK_DIR}/include)
if (MSVC)
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC /std:clatest /experimental:c11atomics)
endif()
endif()
target_link_libraries(${IMGUI_EXECUTABLE} PUBLIC ${LIBRARIES} SDL3::SDL3)
else() # Emscripten settings
+9 -3
View File
@@ -61,6 +61,8 @@ int main(int, char**)
// Create SDL window graphics context
float main_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
SDL_WindowFlags window_flags = SDL_WINDOW_RESIZABLE;
wgpu_surface_width = (int)(wgpu_surface_width * main_scale);
wgpu_surface_height = (int)(wgpu_surface_height * main_scale);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+WebGPU example", wgpu_surface_width, wgpu_surface_height, window_flags);
if (window == nullptr)
{
@@ -335,9 +337,10 @@ static WGPUDevice RequestDevice(wgpu::Instance& instance, wgpu::Adapter& adapter
IM_ASSERT(acquired_device != nullptr && waitStatusDevice == wgpu::WaitStatus::Success && "Error on Device request");
return acquired_device.MoveToCHandle();
}
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void* userdata1, void* userdata2)
{
IM_UNUSED(userdata2);
if (status == WGPURequestAdapterStatus_Success)
{
WGPUAdapter* extAdapter = (WGPUAdapter*)userdata1;
@@ -351,6 +354,7 @@ static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter
static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void* userdata1, void* userdata2)
{
IM_UNUSED(userdata2);
if (status == WGPURequestDeviceStatus_Success)
{
WGPUDevice* extDevice = (WGPUDevice*)userdata1;
@@ -435,17 +439,19 @@ static bool InitWGPU(SDL_Window* window)
preferred_fmt = surface_capabilities.formats[0];
// WGPU backend: Adapter and Device acquisition, Surface creation
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
WGPUInstanceDescriptor instanceDesc = {};
WGPUInstanceFeatureName timedWaitAny = WGPUInstanceFeatureName_TimedWaitAny;
instanceDesc.requiredFeatureCount = 1;
instanceDesc.requiredFeatures = &timedWaitAny;
wgpu_instance = wgpuCreateInstance(&instanceDesc);
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
wgpuSetLogCallback(
[](WGPULogLevel level, WGPUStringView msg, void* userdata) { fprintf(stderr, "%s: %.*s\n", ImGui_ImplWGPU_GetLogLevelName(level), (int)msg.length, msg.data); }, nullptr
);
wgpuSetLogLevel(WGPULogLevel_Warn);
#endif
WGPUAdapter adapter = RequestAdapter(wgpu_instance);
ImGui_ImplWGPU_DebugPrintAdapterInfo(adapter);
@@ -526,7 +532,7 @@ WGPUSurface CreateWGPUSurface(const WGPUInstance& instance, SDL_Window* window)
}
#else
#error "Unsupported WebGPU native platform!"
#endif
return nullptr;
#endif
}
#endif // #ifndef __EMSCRIPTEN__
@@ -28,27 +28,27 @@
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -21,33 +21,34 @@
<PropertyGroup Label="Globals">
<ProjectGuid>{9F316E83-5AE5-4939-A723-305A94F48005}</ProjectGuid>
<RootNamespace>example_win32_directx11</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -28,27 +28,27 @@
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -28,27 +28,27 @@
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -21,33 +21,34 @@
<PropertyGroup Label="Globals">
<ProjectGuid>{0A1E32DF-E0F4-4CCE-B3DC-9644C503BD88}</ProjectGuid>
<RootNamespace>example_win32_directx11</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
+2 -1
View File
@@ -182,7 +182,8 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
{
VkDescriptorPoolSize pool_sizes[] =
{
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE },
{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE },
{ VK_DESCRIPTOR_TYPE_SAMPLER, IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE },
};
VkDescriptorPoolCreateInfo pool_info = {};
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+22 -2
View File
@@ -3,12 +3,12 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.2.32616.157
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_win32_directx11", "example_win32_directx11\example_win32_directx11.vcxproj", "{9F316E83-5AE5-4939-A723-305A94F48005}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_win32_directx9", "example_win32_directx9\example_win32_directx9.vcxproj", "{4165A294-21F2-44CA-9B38-E3F935ABADF5}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_win32_directx10", "example_win32_directx10\example_win32_directx10.vcxproj", "{345A953E-A004-4648-B442-DC5F9F11068C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_win32_directx11", "example_win32_directx11\example_win32_directx11.vcxproj", "{9F316E83-5AE5-4939-A723-305A94F48005}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_win32_directx12", "example_win32_directx12\example_win32_directx12.vcxproj", "{B4CF9797-519D-4AFE-A8F4-5141A6B521D3}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_glfw_opengl2", "example_glfw_opengl2\example_glfw_opengl2.vcxproj", "{9CDA7840-B7A5-496D-A527-E95571496D18}"
@@ -31,10 +31,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl2_sdlrenderer2",
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl2_surface", "example_sdl2_surface\example_sdl2_surface.vcxproj", "{47525E56-7D05-474E-A455-64C5BBFFC029}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl2_cpu", "example_sdl2_cpu\example_sdl2_cpu.vcxproj", "{1E9DB182-9BF1-4C7D-8930-85ACAEAC2458}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl3_opengl3", "example_sdl3_opengl3\example_sdl3_opengl3.vcxproj", "{84AAA301-84FE-428B-9E3E-817BC8123C0C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl3_sdlrenderer3", "example_sdl3_sdlrenderer3\example_sdl3_sdlrenderer3.vcxproj", "{C0290D21-3AD2-4A35-ABBC-A2F5F48326DA}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl3_surface", "example_sdl3_surface\example_sdl3_surface.vcxproj", "{08DD87C0-C734-45D6-9B44-D23F19F2D4B6}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl3_vulkan", "example_sdl3_vulkan\example_sdl3_vulkan.vcxproj", "{663A7E89-1E42-4222-921C-177F5B5910DF}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_win32_vulkan", "example_win32_vulkan\example_win32_vulkan.vcxproj", "{0A1E32DF-E0F4-4CCE-B3DC-9644C503BD88}"
@@ -165,6 +169,14 @@ Global
{47525E56-7D05-474E-A455-64C5BBFFC029}.Release|Win32.Build.0 = Release|Win32
{47525E56-7D05-474E-A455-64C5BBFFC029}.Release|x64.ActiveCfg = Release|x64
{47525E56-7D05-474E-A455-64C5BBFFC029}.Release|x64.Build.0 = Release|x64
{1E9DB182-9BF1-4C7D-8930-85ACAEAC2458}.Debug|Win32.ActiveCfg = Debug|Win32
{1E9DB182-9BF1-4C7D-8930-85ACAEAC2458}.Debug|Win32.Build.0 = Debug|Win32
{1E9DB182-9BF1-4C7D-8930-85ACAEAC2458}.Debug|x64.ActiveCfg = Debug|x64
{1E9DB182-9BF1-4C7D-8930-85ACAEAC2458}.Debug|x64.Build.0 = Debug|x64
{1E9DB182-9BF1-4C7D-8930-85ACAEAC2458}.Release|Win32.ActiveCfg = Release|Win32
{1E9DB182-9BF1-4C7D-8930-85ACAEAC2458}.Release|Win32.Build.0 = Release|Win32
{1E9DB182-9BF1-4C7D-8930-85ACAEAC2458}.Release|x64.ActiveCfg = Release|x64
{1E9DB182-9BF1-4C7D-8930-85ACAEAC2458}.Release|x64.Build.0 = Release|x64
{84AAA301-84FE-428B-9E3E-817BC8123C0C}.Debug|Win32.ActiveCfg = Debug|Win32
{84AAA301-84FE-428B-9E3E-817BC8123C0C}.Debug|Win32.Build.0 = Debug|Win32
{84AAA301-84FE-428B-9E3E-817BC8123C0C}.Debug|x64.ActiveCfg = Debug|x64
@@ -181,6 +193,14 @@ Global
{C0290D21-3AD2-4A35-ABBC-A2F5F48326DA}.Release|Win32.Build.0 = Release|Win32
{C0290D21-3AD2-4A35-ABBC-A2F5F48326DA}.Release|x64.ActiveCfg = Release|x64
{C0290D21-3AD2-4A35-ABBC-A2F5F48326DA}.Release|x64.Build.0 = Release|x64
{08DD87C0-C734-45D6-9B44-D23F19F2D4B6}.Debug|Win32.ActiveCfg = Debug|Win32
{08DD87C0-C734-45D6-9B44-D23F19F2D4B6}.Debug|Win32.Build.0 = Debug|Win32
{08DD87C0-C734-45D6-9B44-D23F19F2D4B6}.Debug|x64.ActiveCfg = Debug|x64
{08DD87C0-C734-45D6-9B44-D23F19F2D4B6}.Debug|x64.Build.0 = Debug|x64
{08DD87C0-C734-45D6-9B44-D23F19F2D4B6}.Release|Win32.ActiveCfg = Release|Win32
{08DD87C0-C734-45D6-9B44-D23F19F2D4B6}.Release|Win32.Build.0 = Release|Win32
{08DD87C0-C734-45D6-9B44-D23F19F2D4B6}.Release|x64.ActiveCfg = Release|x64
{08DD87C0-C734-45D6-9B44-D23F19F2D4B6}.Release|x64.Build.0 = Release|x64
{663A7E89-1E42-4222-921C-177F5B5910DF}.Debug|Win32.ActiveCfg = Debug|Win32
{663A7E89-1E42-4222-921C-177F5B5910DF}.Debug|Win32.Build.0 = Debug|Win32
{663A7E89-1E42-4222-921C-177F5B5910DF}.Debug|x64.ActiveCfg = Debug|x64
+3 -1
View File
@@ -49,7 +49,9 @@
//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
//#define IMGUI_DISABLE_DEFAULT_FONT // Disable default embedded fonts (ProggyClean/ProggyForever), remove ~9 KB + ~14 KB from output binary. AddFontDefaultXXX() functions will assert.
//#define IMGUI_DISABLE_DEFAULT_FONT // Disable default embedded fonts (ProggyClean + ProggyForever). Remove ~9 KB + ~14 KB from output binary. AddFontDefaultXXX() functions will assert.
//#define IMGUI_DISABLE_DEFAULT_FONT_BITMAP // Disable default embedded bitmap font (ProggyClean). Remove ~9 KB from output binary. AddFontDefaultBitmap() will assert.
//#define IMGUI_DISABLE_DEFAULT_FONT_VECTOR // Disable default embedded vector font (ProggyForever), Remove ~14 KB from output binary. AddFontDefaultVector() will assert.
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
//---- Enable Test Engine / Automation features.
+314 -138
View File
File diff suppressed because it is too large Load Diff
+111 -63
View File
@@ -1,4 +1,4 @@
// dear imgui, v1.92.7 WIP
// dear imgui, v1.92.9 WIP
// (headers)
// Help:
@@ -20,7 +20,7 @@
// - Software using Dear ImGui https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui
// - Issues & support ........... https://github.com/ocornut/imgui/issues
// - Test Engine & Automation ... https://github.com/ocornut/imgui_test_engine (test suite, test engine to automate your apps)
// - Web version of the Demo .... https://pthom.github.io/imgui_manual (w/ source code browser)
// - Web version of the Demo .... https://pthom.github.io/imgui_explorer (w/ source code browser)
// For FIRST-TIME users having issues compiling/linking/running:
// please post in https://github.com/ocornut/imgui/discussions if you cannot find a solution in resources above.
@@ -29,8 +29,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.7 WIP"
#define IMGUI_VERSION_NUM 19264
#define IMGUI_VERSION "1.92.9 WIP"
#define IMGUI_VERSION_NUM 19282
#define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000
#define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198
@@ -340,7 +340,9 @@ IM_MSVC_RUNTIME_CHECKS_RESTORE
typedef ImU64 ImTextureID; // Default: store up to 64-bits (any pointer or integer). A majority of backends are ok with that.
#endif
// Define this if you need 0 to be a valid ImTextureID for your backend.
// Define this if you need to change the invalid value for your backend.
// - If your backend is using ImTextureID to store an index/offset and you need 0 to be valid, You can add '#define ImTextureID_Invalid ((ImTextureID)-1)' in your imconfig.h file.
// - From 2026/03/12 to 2026/03/19 we experimented with changing to default to -1, but I worried it would cause too many issues in third-party code so it was reverted.
#ifndef ImTextureID_Invalid
#define ImTextureID_Invalid ((ImTextureID)0)
#endif
@@ -611,7 +613,8 @@ namespace ImGui
IMGUI_API ImGuiID GetID(int int_id);
// Widgets: Text
IMGUI_API void TextUnformatted(const char* text, const char* text_end = NULL); // raw text without formatting. Roughly equivalent to Text("%s", text) but: A) doesn't require null terminated string if 'text_end' is specified, B) it's faster, no memory copy is done, no buffer size limits, recommended for long chunks of text.
// - Note that all functions taking format strings in the API may be passed ("%s", text) or ("%.*s", text_len, text): which will automatically bypass the formatter.
IMGUI_API void TextUnformatted(const char* text, const char* text_end = NULL); // raw text without formatting. Practically equivalent to 'Text("%s", text)' but doesn't require null terminated string if 'text_end' is specified.
IMGUI_API void Text(const char* fmt, ...) IM_FMTARGS(1); // formatted text
IMGUI_API void TextV(const char* fmt, va_list args) IM_FMTLIST(1);
IMGUI_API void TextColored(const ImVec4& col, const char* fmt, ...) IM_FMTARGS(2); // shortcut for PushStyleColor(ImGuiCol_Text, col); Text(fmt, ...); PopStyleColor();
@@ -835,7 +838,7 @@ namespace ImGui
// Popups, Modals
// - They block normal mouse hovering detection (and therefore most mouse interactions) behind them.
// - If not modal: they can be closed by clicking anywhere outside them, or by pressing ESCAPE.
// - If not modal: they can be closed by clicking anywhere outside them, or by pressing Escape (call 'Shortcut(ImGuiKey_Escape)' to claim a higher-priority shortcut).
// - Their visibility state (~bool) is held internally instead of being held by the programmer as we are used to with regular Begin*() calls.
// - The 3 properties above are related: we need to retain popup visibility state in the library because popups may be closed as any time.
// - You can bypass the hovering restriction by using ImGuiHoveredFlags_AllowWhenBlockedByPopup when calling IsItemHovered() or IsWindowHovered().
@@ -912,7 +915,7 @@ namespace ImGui
// The context menu can also be made available in columns body using ImGuiTableFlags_ContextMenuInBody.
// - You may manually submit headers using TableNextRow() + TableHeader() calls, but this is only useful in
// some advanced use cases (e.g. adding custom widgets in header row).
// - Use TableSetupScrollFreeze() to lock columns/rows so they stay visible when scrolled.
// - Use TableSetupScrollFreeze() to lock columns/rows so they stay visible when scrolled. When freezing columns you would usually also use ImGuiTableColumnFlags_NoHide on them.
IMGUI_API void TableSetupColumn(const char* label, ImGuiTableColumnFlags flags = 0, float init_width_or_weight = 0.0f, ImGuiID user_id = 0);
IMGUI_API void TableSetupScrollFreeze(int cols, int rows); // lock columns/rows so they stay visible when scrolled.
IMGUI_API void TableHeader(const char* label); // submit one header cell manually (rarely used)
@@ -999,7 +1002,7 @@ namespace ImGui
IMGUI_API void SetNavCursorVisible(bool visible); // alter visibility of keyboard/gamepad cursor. by default: show when using an arrow key, hide when clicking with mouse.
// Overlapping mode
IMGUI_API void SetNextItemAllowOverlap(); // allow next item to be overlapped by a subsequent item. Useful with invisible buttons, selectable, treenode covering an area where subsequent items may need to be added. Note that both Selectable() and TreeNode() have dedicated flags doing this.
IMGUI_API void SetNextItemAllowOverlap(); // allow next item to be overlapped by a subsequent item. Typically useful with InvisibleButton(), Selectable(), TreeNode() covering an area where subsequent items may need to be added. Note that both Selectable() and TreeNode() have dedicated flags doing this.
// Item/Widgets Utilities and Query Functions
// - Most of the functions are referring to the previous Item that has been submitted.
@@ -1090,10 +1093,11 @@ namespace ImGui
// Inputs Utilities: Key/Input Ownership [BETA]
// - One common use case would be to allow your items to disable standard inputs behaviors such
// as Tab or Alt key handling, Mouse Wheel scrolling, etc.
// e.g. Button(...); SetItemKeyOwner(ImGuiKey_MouseWheelY); to make hovering/activating a button disable wheel for scrolling.
// e.g. `Button(...); if (SetItemKeyOwner(ImGuiKey_MouseWheelY)) { ... }` to make hovering/activating a button disable wheel for scrolling.
// - Reminder ImGuiKey enum include access to mouse buttons and gamepad, so key ownership can apply to them.
// - The return value of SetItemKeyOwner() says if ownership has been requested for the item, which is a shortcut to calling yet non-public TestKeyOwner() function.
// - Many related features are still in imgui_internal.h. For instance, most IsKeyXXX()/IsMouseXXX() functions have an owner-id-aware version.
IMGUI_API void SetItemKeyOwner(ImGuiKey key); // Set key owner to last item ID if it is hovered or active. Equivalent to 'if (IsItemHovered() || IsItemActive()) { SetKeyOwner(key, GetItemID());'.
IMGUI_API bool SetItemKeyOwner(ImGuiKey key); // Set key owner to last item ID if it is hovered or active. Return true when ownership has been set. Roughly equivalent to 'if (TestKeyOwner(key, GetItemID()) && (IsItemHovered() || IsItemActive())) { SetKeyOwner(key, GetItemID());'.
// Inputs Utilities: Mouse
// - To refer to a mouse button, you may use named enums in your code e.g. ImGuiMouseButton_Left, ImGuiMouseButton_Right.
@@ -1301,7 +1305,7 @@ enum ImGuiTreeNodeFlags_
ImGuiTreeNodeFlags_None = 0,
ImGuiTreeNodeFlags_Selected = 1 << 0, // Draw as selected
ImGuiTreeNodeFlags_Framed = 1 << 1, // Draw frame with background (e.g. for CollapsingHeader)
ImGuiTreeNodeFlags_AllowOverlap = 1 << 2, // Hit testing to allow subsequent widgets to overlap this one
ImGuiTreeNodeFlags_AllowOverlap = 1 << 2, // Hit testing will allow subsequent widgets to overlap this one. Require previous frame HoveredId to match before being usable. Shortcut to calling SetNextItemAllowOverlap().
ImGuiTreeNodeFlags_NoTreePushOnOpen = 1 << 3, // Don't do a TreePush() when open (e.g. for CollapsingHeader) = no extra indent nor pushing on ID stack
ImGuiTreeNodeFlags_NoAutoOpenOnLog = 1 << 4, // Don't automatically and temporarily open node when Logging is active (by default logging will automatically open tree nodes)
ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, // Default node to be open
@@ -1327,7 +1331,7 @@ enum ImGuiTreeNodeFlags_
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
ImGuiTreeNodeFlags_NavLeftJumpsBackHere = ImGuiTreeNodeFlags_NavLeftJumpsToParent, // Renamed in 1.92.0
ImGuiTreeNodeFlags_SpanTextWidth = ImGuiTreeNodeFlags_SpanLabelWidth, // Renamed in 1.90.7
//ImGuiTreeNodeFlags_SpanTextWidth = ImGuiTreeNodeFlags_SpanLabelWidth, // Renamed in 1.90.7
//ImGuiTreeNodeFlags_AllowItemOverlap = ImGuiTreeNodeFlags_AllowOverlap, // Renamed in 1.89.7
#endif
};
@@ -1361,7 +1365,7 @@ enum ImGuiSelectableFlags_
ImGuiSelectableFlags_SpanAllColumns = 1 << 1, // Frame will span all columns of its container table (text will still fit in current column)
ImGuiSelectableFlags_AllowDoubleClick = 1 << 2, // Generate press events on double clicks too
ImGuiSelectableFlags_Disabled = 1 << 3, // Cannot be selected, display grayed out text
ImGuiSelectableFlags_AllowOverlap = 1 << 4, // (WIP) Hit testing to allow subsequent widgets to overlap this one
ImGuiSelectableFlags_AllowOverlap = 1 << 4, // Hit testing will allow subsequent widgets to overlap this one. Require previous frame HoveredId to match before being usable. Shortcut to calling SetNextItemAllowOverlap().
ImGuiSelectableFlags_Highlight = 1 << 5, // Make the item be displayed as if it is hovered
ImGuiSelectableFlags_SelectOnNav = 1 << 6, // Auto-select when moved into, unless Ctrl is held. Automatic when in a BeginMultiSelect() block.
@@ -1399,7 +1403,7 @@ enum ImGuiTabBarFlags_
ImGuiTabBarFlags_DrawSelectedOverline = 1 << 6, // Draw selected overline markers over selected tab
// Fitting/Resize policy
ImGuiTabBarFlags_FittingPolicyMixed = 1 << 7, // Shrink down tabs when they don't fit, until width is style.TabMinWidthShrink, then enable scrolling buttons.
ImGuiTabBarFlags_FittingPolicyMixed = 1 << 7, // Shrink down tabs when they don't fit, until width is style.TabMinWidthShrink, then enable scrolling. Setting TabMinWidthShrink to FLT_MAX makes this behave like ImGuiTabBarFlags_FittingPolicyScroll.
ImGuiTabBarFlags_FittingPolicyShrink = 1 << 8, // Shrink down tabs when they don't fit
ImGuiTabBarFlags_FittingPolicyScroll = 1 << 9, // Enable scrolling buttons when tabs don't fit
ImGuiTabBarFlags_FittingPolicyMask_ = ImGuiTabBarFlags_FittingPolicyMixed | ImGuiTabBarFlags_FittingPolicyShrink | ImGuiTabBarFlags_FittingPolicyScroll,
@@ -1616,10 +1620,10 @@ enum ImGuiKey : int
// // XBOX | SWITCH | PLAYSTA. | -> ACTION
ImGuiKey_GamepadStart, // Menu | + | Options |
ImGuiKey_GamepadBack, // View | - | Share |
ImGuiKey_GamepadFaceLeft, // X | Y | Square | Tap: Toggle Menu. Hold: Windowing mode (Focus/Move/Resize windows)
ImGuiKey_GamepadFaceLeft, // X | Y | Square | Toggle Menu. Hold for Windowing mode (Focus/Move/Resize windows)
ImGuiKey_GamepadFaceRight, // B | A | Circle | Cancel / Close / Exit
ImGuiKey_GamepadFaceUp, // Y | X | Triangle | Text Input / On-screen Keyboard
ImGuiKey_GamepadFaceDown, // A | B | Cross | Activate / Open / Toggle / Tweak
ImGuiKey_GamepadFaceUp, // Y | X | Triangle | Open Context Menu
ImGuiKey_GamepadFaceDown, // A | B | Cross | Activate / Open / Toggle. Hold for 0.60f to Activate in Text Input mode (e.g. wired to an on-screen keyboard).
ImGuiKey_GamepadDpadLeft, // D-pad Left | " | " | Move / Tweak / Resize Window (in Windowing mode)
ImGuiKey_GamepadDpadRight, // D-pad Right | " | " | Move / Tweak / Resize Window (in Windowing mode)
ImGuiKey_GamepadDpadUp, // D-pad Up | " | " | Move / Tweak / Resize Window (in Windowing mode)
@@ -1701,6 +1705,7 @@ enum ImGuiInputFlags_
};
// Configuration flags stored in io.ConfigFlags. Set by user/application.
// Note that nowadays most of our configuration options are in other ImGuiIO fields, e.g. io.ConfigWindowsMoveFromTitleBarOnly.
enum ImGuiConfigFlags_
{
ImGuiConfigFlags_None = 0,
@@ -1710,10 +1715,9 @@ enum ImGuiConfigFlags_
ImGuiConfigFlags_NoMouseCursorChange = 1 << 5, // Instruct backend to not alter mouse cursor shape and visibility. Use if the backend cursor changes are interfering with yours and you don't want to use SetMouseCursor() to change mouse cursor. You may want to honor requests from imgui by reading GetMouseCursor() yourself instead.
ImGuiConfigFlags_NoKeyboard = 1 << 6, // Instruct dear imgui to disable keyboard inputs and interactions. This is done by ignoring keyboard events and clearing existing states.
// User storage (to allow your backend/engine to communicate to code that may be shared between multiple projects. Those flags are NOT used by core Dear ImGui)
// [Unused] User storage (to allow your backend/engine to communicate to code that may be shared between multiple projects. Those flags are NOT used by core Dear ImGui)
ImGuiConfigFlags_IsSRGB = 1 << 20, // Application is SRGB-aware.
ImGuiConfigFlags_IsTouchScreen = 1 << 21, // Application is using a touch screen instead of a mouse.
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
ImGuiConfigFlags_NavEnableSetMousePos = 1 << 2, // [moved/renamed in 1.91.4] -> use bool io.ConfigNavMoveSetMousePos
ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3, // [moved/renamed in 1.91.4] -> use bool io.ConfigNavCaptureKeyboard
@@ -1753,6 +1757,7 @@ enum ImGuiCol_
ImGuiCol_ScrollbarGrabHovered,
ImGuiCol_ScrollbarGrabActive,
ImGuiCol_CheckMark, // Checkbox tick and RadioButton circle
ImGuiCol_CheckboxSelectedBg, // Checkbox background when Selected, otherwise use FrameBg
ImGuiCol_SliderGrab,
ImGuiCol_SliderGrabActive,
ImGuiCol_Button,
@@ -1850,6 +1855,7 @@ enum ImGuiStyleVar_
ImGuiStyleVar_TableAngledHeadersTextAlign,// ImVec2 TableAngledHeadersTextAlign
ImGuiStyleVar_TreeLinesSize, // float TreeLinesSize
ImGuiStyleVar_TreeLinesRounding, // float TreeLinesRounding
ImGuiStyleVar_DragDropTargetRounding, // float DragDropTargetRounding
ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign
ImGuiStyleVar_SelectableTextAlign, // ImVec2 SelectableTextAlign
ImGuiStyleVar_SeparatorSize, // float SeparatorSize
@@ -1868,6 +1874,7 @@ enum ImGuiButtonFlags_
ImGuiButtonFlags_MouseButtonMiddle = 1 << 2, // React on center mouse button
ImGuiButtonFlags_MouseButtonMask_ = ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight | ImGuiButtonFlags_MouseButtonMiddle, // [Internal]
ImGuiButtonFlags_EnableNav = 1 << 3, // InvisibleButton(): do not disable navigation/tabbing. Otherwise disabled by default.
ImGuiButtonFlags_AllowOverlap = 1 << 12, // Hit testing will allow subsequent widgets to overlap this one. Require previous frame HoveredId to match before being usable. Shortcut to calling SetNextItemAllowOverlap().
};
// Flags for ColorEdit3() / ColorEdit4() / ColorPicker3() / ColorPicker4() / ColorButton()
@@ -2027,11 +2034,11 @@ enum ImGuiTableFlags_
// Features
ImGuiTableFlags_None = 0,
ImGuiTableFlags_Resizable = 1 << 0, // Enable resizing columns.
ImGuiTableFlags_Reorderable = 1 << 1, // Enable reordering columns in header row (need calling TableSetupColumn() + TableHeadersRow() to display headers)
ImGuiTableFlags_Reorderable = 1 << 1, // Enable reordering columns in header row. (Need calling TableSetupColumn() + TableHeadersRow() to display headers, or using ImGuiTableFlags_ContextMenuInBody to access context-menu without headers).
ImGuiTableFlags_Hideable = 1 << 2, // Enable hiding/disabling columns in context menu.
ImGuiTableFlags_Sortable = 1 << 3, // Enable sorting. Call TableGetSortSpecs() to obtain sort specs. Also see ImGuiTableFlags_SortMulti and ImGuiTableFlags_SortTristate.
ImGuiTableFlags_NoSavedSettings = 1 << 4, // Disable persisting columns order, width, visibility and sort settings in the .ini file.
ImGuiTableFlags_ContextMenuInBody = 1 << 5, // Right-click on columns body/contents will display table context menu. By default it is available in TableHeadersRow().
ImGuiTableFlags_ContextMenuInBody = 1 << 5, // Right-click on columns body/contents will also display table context menu. By default it is available in TableHeadersRow().
// Decorations
ImGuiTableFlags_RowBg = 1 << 6, // Set each RowBg color with ImGuiCol_TableRowBg or ImGuiCol_TableRowBgAlt (equivalent of calling TableSetBgColor with ImGuiTableBgFlags_RowBg0 on each row manually)
ImGuiTableFlags_BordersInnerH = 1 << 7, // Draw horizontal borders between rows.
@@ -2316,7 +2323,7 @@ struct ImGuiStyle
float TabBorderSize; // Thickness of border around tabs.
float TabMinWidthBase; // Minimum tab width, to make tabs larger than their contents. TabBar buttons are not affected.
float TabMinWidthShrink; // Minimum tab width after shrinking, when using ImGuiTabBarFlags_FittingPolicyMixed policy.
float TabCloseButtonMinWidthSelected; // -1: always visible. 0.0f: visible when hovered. >0.0f: visible when hovered if minimum width.
float TabCloseButtonMinWidthSelected; // -1: always visible. 0.0f: visible when hovered. >0.0f: visible when hovered if minimum width. FLT_MAX: never shrink, will behave like ImGuiTabBarFlags_FittingPolicyScroll.
float TabCloseButtonMinWidthUnselected; // -1: always visible. 0.0f: visible when hovered. >0.0f: visible when hovered if minimum width. FLT_MAX: never show close button when unselected.
float TabBarBorderSize; // Thickness of tab-bar separator, which takes on the tab active color to denote focus.
float TabBarOverlineSize; // Thickness of tab-bar overline, which highlights the selected tab-bar.
@@ -2325,14 +2332,15 @@ struct ImGuiStyle
ImGuiTreeNodeFlags TreeLinesFlags; // Default way to draw lines connecting TreeNode hierarchy. ImGuiTreeNodeFlags_DrawLinesNone or ImGuiTreeNodeFlags_DrawLinesFull or ImGuiTreeNodeFlags_DrawLinesToNodes.
float TreeLinesSize; // Thickness of outlines when using ImGuiTreeNodeFlags_DrawLines.
float TreeLinesRounding; // Radius of lines connecting child nodes to the vertical line.
float DragDropTargetRounding; // Radius of the drag and drop target frame.
float DragDropTargetRounding; // Radius of the drag and drop target frame. When <0.0f: use FrameRounding.
float DragDropTargetBorderSize; // Thickness of the drag and drop target border.
float DragDropTargetPadding; // Size to expand the drag and drop target from actual target item size.
float ColorMarkerSize; // Size of R/G/B/A color markers for ColorEdit4() and for Drags/Sliders when using ImGuiSliderFlags_ColorMarkers.
ImGuiDir ColorButtonPosition; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f, 0.5f) (centered).
ImVec2 SelectableTextAlign; // Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
float SeparatorSize; // Thickness of border in Separator()
float InputTextCursorSize; // Thickness of cursor/caret in InputText().
float SeparatorSize; // Thickness of border in Separator(). Must be >= 1.0f.
float SeparatorTextBorderSize; // Thickness of border in SeparatorText()
ImVec2 SeparatorTextAlign; // Alignment of text within the separator. Defaults to (0.0f, 0.5f) (left aligned, center).
ImVec2 SeparatorTextPadding; // Horizontal offset of text from each edge of the separator + spacing on other axis. Generally small values. .y is recommended to be == FramePadding.y.
@@ -2362,7 +2370,7 @@ struct ImGuiStyle
// Functions
IMGUI_API ImGuiStyle();
IMGUI_API void ScaleAllSizes(float scale_factor); // Scale all spacing/padding/thickness values. Do not scale fonts.
IMGUI_API void ScaleAllSizes(float scale_factor); // Scale all spacing/padding/thickness values. Do not scale fonts. See comments in definition. Consider not calling this if your initial scale factor if <1.0.
// Obsolete names
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
@@ -2428,7 +2436,7 @@ struct ImGuiIO
bool ConfigMacOSXBehaviors; // = defined(__APPLE__) // Swap Cmd<>Ctrl keys + OS X style text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl.
bool ConfigInputTrickleEventQueue; // = true // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.
bool ConfigInputTextCursorBlink; // = true // Enable blinking cursor (optional as some users consider it to be distracting).
bool ConfigInputTextEnterKeepActive; // = false // [BETA] Pressing Enter will keep item active and select contents (single-line only).
bool ConfigInputTextEnterKeepActive; // = false // [BETA] Pressing Enter will reactivate item and select all text (single-line only).
bool ConfigDragClickToInputText; // = false // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard.
bool ConfigWindowsResizeFromEdges; // = true // Enable resizing of windows from their edges and from the lower-left corner. This requires ImGuiBackendFlags_HasMouseCursors for better mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag)
bool ConfigWindowsMoveFromTitleBarOnly; // = false // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar.
@@ -2606,7 +2614,7 @@ struct ImGuiIO
//void* ImeWindowHandle; // [Obsoleted in 1.87] Set ImGuiViewport::PlatformHandleRaw instead. Set this to your HWND to get automatic IME cursor positioning.
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
float FontGlobalScale; // Moved io.FontGlobalScale to style.FontScaleMain in 1.92 (June 2025)
float FontGlobalScale; // Moved io.FontGlobalScale to style.FontScaleMain in 1.92.0 (June 2025)
// Legacy: before 1.91.1, clipboard functions were stored in ImGuiIO instead of ImGuiPlatformIO.
// As this is will affect all users of custom engines/backends, we are providing proper legacy redirection (will obsolete).
@@ -2639,7 +2647,7 @@ struct ImGuiInputTextCallbackData
ImGuiInputTextFlags EventFlag; // One ImGuiInputTextFlags_Callback* // Read-only
ImGuiInputTextFlags Flags; // What user passed to InputText() // Read-only
void* UserData; // What user passed to InputText() // Read-only
ImGuiID ID; // Widget ID // Read-only
ImGuiID ID; // Widget ID // Read-only
// Arguments for the different callback events
// - During Resize callback, Buf will be same as your input buffer.
@@ -2653,9 +2661,9 @@ struct ImGuiInputTextCallbackData
char* Buf; // Text buffer // Read-write // [Resize] Can replace pointer / [Completion,History,Always] Only write to pointed data, don't replace the actual pointer!
int BufTextLen; // Text length (in bytes) // Read-write // [Resize,Completion,History,Always] Exclude zero-terminator storage. In C land: == strlen(some_text), in C++ land: string.length()
int BufSize; // Buffer size (in bytes) = capacity+1 // Read-only // [Resize,Completion,History,Always] Include zero-terminator storage. In C land: == ARRAYSIZE(my_char_array), in C++ land: string.capacity()+1
int CursorPos; // // Read-write // [Completion,History,Always]
int SelectionStart; // // Read-write // [Completion,History,Always] == to SelectionEnd when no selection
int SelectionEnd; // // Read-write // [Completion,History,Always]
int CursorPos; // // Read-write // [Completion,History,Always,CharFilter]
int SelectionStart; // // Read-write // [Completion,History,Always,CharFilter] == to SelectionEnd when no selection
int SelectionEnd; // // Read-write // [Completion,History,Always,CharFilter]
// Helper functions for text manipulation.
// Use those function to benefit from the CallbackResize behaviors. Calling those function reset the selection.
@@ -2853,16 +2861,16 @@ enum ImGuiListClipperFlags_
// - The clipper also handles various subtleties related to keyboard/gamepad navigation, wrapping etc.
struct ImGuiListClipper
{
ImGuiContext* Ctx; // Parent UI context
int DisplayStart; // First item to display, updated by each call to Step()
int DisplayEnd; // End of items to display (exclusive)
int UserIndex; // Helper storage for user convenience/code. Optional, and otherwise unused if you don't use it.
int ItemsCount; // [Internal] Number of items
float ItemsHeight; // [Internal] Height of item after a first step and item submission can calculate it
ImGuiListClipperFlags Flags; // [Internal] Flags, currently not yet well exposed.
double StartPosY; // [Internal] Cursor position at the time of Begin() or after table frozen rows are all processed
double StartSeekOffsetY; // [Internal] Account for frozen rows in a table and initial loss of precision in very large windows.
ImGuiContext* Ctx; // [Internal] Parent UI context
void* TempData; // [Internal] Internal data
ImGuiListClipperFlags Flags; // [Internal] Flags, currently not yet well exposed.
// items_count: Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step, and you can call SeekCursorForItem() manually if you need)
// items_height: Use -1.0f to be calculated automatically on first step. Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or GetFrameHeightWithSpacing().
@@ -2893,17 +2901,18 @@ struct ImGuiListClipper
// - It is important that we are keeping those disabled by default so they don't leak in user space.
// - This is in order to allow user enabling implicit cast operators between ImVec2/ImVec4 and their own types (using IM_VEC2_CLASS_EXTRA in imconfig.h)
// - Add '#define IMGUI_DEFINE_MATH_OPERATORS' before including this file (or in imconfig.h) to access courtesy maths operators for ImVec2 and ImVec4.
// - We intentionally provide ImVec2*float but not float*ImVec2: this is rare enough and we want to reduce the surface for possible user mistake.
#ifdef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS_IMPLEMENTED
IM_MSVC_RUNTIME_CHECKS_OFF
// ImVec2 operators
inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x * rhs, lhs.y * rhs); }
inline ImVec2 operator*(const float lhs, const ImVec2& rhs) { return ImVec2(lhs * rhs.x, lhs * rhs.y); }
inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x / rhs, lhs.y / rhs); }
inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x + rhs.x, lhs.y + rhs.y); }
inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x - rhs.x, lhs.y - rhs.y); }
inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); }
inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x / rhs.x, lhs.y / rhs.y); }
inline ImVec2 operator+(const ImVec2& lhs) { return lhs; }
inline ImVec2 operator-(const ImVec2& lhs) { return ImVec2(-lhs.x, -lhs.y); }
inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; }
inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; }
@@ -2915,12 +2924,20 @@ inline bool operator==(const ImVec2& lhs, const ImVec2& rhs) { return lhs.x =
inline bool operator!=(const ImVec2& lhs, const ImVec2& rhs) { return lhs.x != rhs.x || lhs.y != rhs.y; }
// ImVec4 operators
inline ImVec4 operator*(const ImVec4& lhs, const float rhs) { return ImVec4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); }
inline ImVec4 operator*(const float lhs, const ImVec4& rhs) { return ImVec4(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z, lhs * rhs.w); }
inline ImVec4 operator/(const ImVec4& lhs, const float rhs) { return ImVec4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); }
inline ImVec4 operator+(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); }
inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); }
inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); }
inline ImVec4 operator/(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z, lhs.w / rhs.w); }
inline ImVec4 operator+(const ImVec4& lhs) { return lhs; }
inline ImVec4 operator-(const ImVec4& lhs) { return ImVec4(-lhs.x, -lhs.y, -lhs.z, -lhs.w); }
inline ImVec4& operator*=(ImVec4& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; lhs.z *= rhs; lhs.w *= rhs; return lhs; }
inline ImVec4& operator/=(ImVec4& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; lhs.z /= rhs; lhs.w /= rhs; return lhs; }
inline ImVec4& operator+=(ImVec4& lhs, const ImVec4& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; lhs.z += rhs.z; lhs.w += rhs.w; return lhs; }
inline ImVec4& operator-=(ImVec4& lhs, const ImVec4& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; lhs.z -= rhs.z; lhs.w -= rhs.w; return lhs; }
inline ImVec4& operator*=(ImVec4& lhs, const ImVec4& rhs) { lhs.x *= rhs.x; lhs.y *= rhs.y; lhs.z *= rhs.z; lhs.w *= rhs.w; return lhs; }
inline ImVec4& operator/=(ImVec4& lhs, const ImVec4& rhs) { lhs.x /= rhs.x; lhs.y /= rhs.y; lhs.z /= rhs.z; lhs.w /= rhs.w; return lhs; }
inline bool operator==(const ImVec4& lhs, const ImVec4& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.w == rhs.w; }
inline bool operator!=(const ImVec4& lhs, const ImVec4& rhs) { return lhs.x != rhs.x || lhs.y != rhs.y || lhs.z != rhs.z || lhs.w != rhs.w; }
IM_MSVC_RUNTIME_CHECKS_RESTORE
@@ -3022,16 +3039,23 @@ enum ImGuiMultiSelectFlags_
ImGuiMultiSelectFlags_NoAutoClearOnReselect = 1 << 5, // Disable clearing selection when clicking/selecting an already selected item.
ImGuiMultiSelectFlags_BoxSelect1d = 1 << 6, // Enable box-selection with same width and same x pos items (e.g. full row Selectable()). Box-selection works better with little bit of spacing between items hit-box in order to be able to aim at empty space.
ImGuiMultiSelectFlags_BoxSelect2d = 1 << 7, // Enable box-selection with varying width or varying x pos items support (e.g. different width labels, or 2D layout/grid). This is slower: alters clipping logic so that e.g. horizontal movements will update selection of normally clipped items.
ImGuiMultiSelectFlags_BoxSelectNoScroll = 1 << 8, // Disable scrolling when box-selecting near edges of scope.
ImGuiMultiSelectFlags_BoxSelectNoScroll = 1 << 8, // Disable scrolling when box-selecting and moving mouse near edges of scope.
ImGuiMultiSelectFlags_ClearOnEscape = 1 << 9, // Clear selection when pressing Escape while scope is focused.
ImGuiMultiSelectFlags_ClearOnClickVoid = 1 << 10, // Clear selection when clicking on empty location within scope.
ImGuiMultiSelectFlags_ScopeWindow = 1 << 11, // Scope for _BoxSelect and _ClearOnClickVoid is whole window (Default). Use if BeginMultiSelect() covers a whole window or used a single time in same window.
ImGuiMultiSelectFlags_ScopeRect = 1 << 12, // Scope for _BoxSelect and _ClearOnClickVoid is rectangle encompassing BeginMultiSelect()/EndMultiSelect(). Use if BeginMultiSelect() is called multiple times in same window.
ImGuiMultiSelectFlags_SelectOnClick = 1 << 13, // Apply selection on mouse down when clicking on unselected item. (Default)
ImGuiMultiSelectFlags_SelectOnClickRelease = 1 << 14, // Apply selection on mouse release when clicking an unselected item. Allow dragging an unselected item without altering selection.
ImGuiMultiSelectFlags_SelectOnAuto = 1 << 13, // Apply selection on mouse down when clicking on unselected item, on mouse up when clicking on selected item. (Default)
ImGuiMultiSelectFlags_SelectOnClickAlways = 1 << 14, // Apply selection on mouse down when clicking on any items. Prevents Drag and Drop from being used on multiple-selection, but allows e.g. BoxSelect to always reselect even when clicking inside an existing selection. (Excel style behavior)
ImGuiMultiSelectFlags_SelectOnClickRelease = 1 << 15, // Apply selection on mouse release when clicking an unselected item. Allow dragging an unselected item without altering selection.
//ImGuiMultiSelectFlags_RangeSelect2d = 1 << 15, // Shift+Selection uses 2d geometry instead of linear sequence, so possible to use Shift+up/down to select vertically in grid. Analogous to what BoxSelect does.
ImGuiMultiSelectFlags_NavWrapX = 1 << 16, // [Temporary] Enable navigation wrapping on X axis. Provided as a convenience because we don't have a design for the general Nav API for this yet. When the more general feature be public we may obsolete this flag in favor of new one.
ImGuiMultiSelectFlags_NoSelectOnRightClick = 1 << 17, // Disable default right-click processing, which selects item on mouse down, and is designed for context-menus.
ImGuiMultiSelectFlags_SelectOnMask_ = ImGuiMultiSelectFlags_SelectOnAuto | ImGuiMultiSelectFlags_SelectOnClickAlways | ImGuiMultiSelectFlags_SelectOnClickRelease,
// Obsolete names
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
ImGuiMultiSelectFlags_SelectOnClick = ImGuiMultiSelectFlags_SelectOnAuto, // RENAMED in 1.92.6
#endif
};
// Main IO structure returned by BeginMultiSelect()/EndMultiSelect().
@@ -3147,12 +3171,6 @@ typedef unsigned short ImDrawIdx; // Default: 16-bit (for maximum compatibilit
typedef void (*ImDrawCallback)(const ImDrawList* parent_list, const ImDrawCmd* cmd);
#endif
// Special Draw callback value to request renderer backend to reset the graphics/render state.
// The renderer backend needs to handle this special value, otherwise it will crash trying to call a function at this address.
// This is useful, for example, if you submitted callbacks which you know have altered the render state and you want it to be restored.
// Render state is not reset by default because they are many perfectly useful way of altering render state (e.g. changing shader/blending settings before an Image call).
#define ImDrawCallback_ResetRenderState (ImDrawCallback)(-8)
// Typically, 1 command = 1 GPU draw call (unless command is a callback)
// - VtxOffset: When 'io.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset' is enabled,
// this fields allow us to render meshes larger than 64K vertices while keeping 16-bit indices.
@@ -3226,23 +3244,30 @@ struct ImDrawListSplitter
};
// Flags for ImDrawList functions
// (Legacy: bit 0 must always correspond to ImDrawFlags_Closed to be backward compatible with old API using a bool. Bits 1..3 must be unused)
enum ImDrawFlags_
{
ImDrawFlags_None = 0,
ImDrawFlags_Closed = 1 << 0, // PathStroke(), AddPolyline(): specify that shape should be closed (Important: this is always == 1 for legacy reason)
ImDrawFlags_RoundCornersTopLeft = 1 << 4, // AddRect(), AddRectFilled(), PathRect(): enable rounding top-left corner only (when rounding > 0.0f, we default to all corners). Was 0x01.
ImDrawFlags_RoundCornersTopRight = 1 << 5, // AddRect(), AddRectFilled(), PathRect(): enable rounding top-right corner only (when rounding > 0.0f, we default to all corners). Was 0x02.
ImDrawFlags_RoundCornersBottomLeft = 1 << 6, // AddRect(), AddRectFilled(), PathRect(): enable rounding bottom-left corner only (when rounding > 0.0f, we default to all corners). Was 0x04.
ImDrawFlags_RoundCornersBottomRight = 1 << 7, // AddRect(), AddRectFilled(), PathRect(): enable rounding bottom-right corner only (when rounding > 0.0f, we default to all corners). Wax 0x08.
ImDrawFlags_RoundCornersNone = 1 << 8, // AddRect(), AddRectFilled(), PathRect(): disable rounding on all corners (when rounding > 0.0f). This is NOT zero, NOT an implicit flag!
// Rounding for AddRect(), AddRectFilled(), PathRect()
// - When not specified, we defaults to ImDrawFlags_RoundCornersAll! So you only need to use those flags if you want another configuration.
ImDrawFlags_RoundCornersTopLeft = 1 << 4, // Round top-left corner only (when rounding > 0.0f, we default to all corners).
ImDrawFlags_RoundCornersTopRight = 1 << 5, // Round top-right corner only (when rounding > 0.0f, we default to all corners).
ImDrawFlags_RoundCornersBottomLeft = 1 << 6, // Round bottom-left corner only (when rounding > 0.0f, we default to all corners).
ImDrawFlags_RoundCornersBottomRight = 1 << 7, // Round bottom-right corner only (when rounding > 0.0f, we default to all corners).
ImDrawFlags_RoundCornersNone = 1 << 8, // Disable rounding even if `float rounding > 0.0f`. This is NOT zero, NOT an implicit flag!
ImDrawFlags_RoundCornersAll = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight | ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight, // (Default!!)
ImDrawFlags_RoundCornersDefault_ = ImDrawFlags_RoundCornersAll, // Default to ALL corners if none of the _RoundCornersXX flags are specified!
ImDrawFlags_RoundCornersTop = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight,
ImDrawFlags_RoundCornersBottom = ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight,
ImDrawFlags_RoundCornersLeft = ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersTopLeft,
ImDrawFlags_RoundCornersRight = ImDrawFlags_RoundCornersBottomRight | ImDrawFlags_RoundCornersTopRight,
ImDrawFlags_RoundCornersAll = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight | ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight,
ImDrawFlags_RoundCornersDefault_ = ImDrawFlags_RoundCornersAll, // Default to ALL corners if none of the _RoundCornersXX flags are specified.
ImDrawFlags_RoundCornersMask_ = ImDrawFlags_RoundCornersAll | ImDrawFlags_RoundCornersNone,
// Stroke options
ImDrawFlags_Closed = 1 << 9, // PathStroke(), AddPolyline(): specify that shape should be closed.
//ImDrawFlags_Closed = 1 << 0, // Prior to 1.92.8 (May 2026), ImDrawFlags_Closed was guaranteed to be == 1<<0 == 1 for legacy compatibility reason. Hardcoded use of 1 or true should be replaced.
ImDrawFlags_InvalidMask_ = ~0x7FFFFFF0, // == 0x8000000F,
};
// Flags for ImDrawList instance. Those are set automatically by ImGui:: functions from ImGuiIO settings, and generally not manipulated directly.
@@ -3254,6 +3279,7 @@ enum ImDrawListFlags_
ImDrawListFlags_AntiAliasedLinesUseTex = 1 << 1, // Enable anti-aliased lines/borders using textures when possible. Require backend to render with bilinear filtering (NOT point/nearest filtering).
ImDrawListFlags_AntiAliasedFill = 1 << 2, // Enable anti-aliased edge around filled shapes (rounded rectangles, circles).
ImDrawListFlags_AllowVtxOffset = 1 << 3, // Can emit 'VtxOffset > 0' to allow large meshes. Set when 'ImGuiBackendFlags_RendererHasVtxOffset' is enabled.
ImDrawListFlags_TextNoPixelSnap = 1 << 4, // Disable automatically snapping AddText() calls to pixel boundaries.
};
// Draw command list
@@ -3308,7 +3334,9 @@ struct ImDrawList
// In future versions we will use textures to provide cheaper and higher-quality circles.
// Use AddNgon() and AddNgonFilled() functions if you need to guarantee a specific number of sides.
IMGUI_API void AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float thickness = 1.0f);
IMGUI_API void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, ImDrawFlags flags = 0, float thickness = 1.0f); // a: upper-left, b: lower-right (== upper-left + size)
IMGUI_API void AddLineH(float min_x, float max_x, float y, ImU32 col, float thickness = 1.0f);
IMGUI_API void AddLineV(float x, float min_y, float max_y, ImU32 col, float thickness = 1.0f);
IMGUI_API void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, float thickness = 1.0f, ImDrawFlags flags = 0); // a: upper-left, b: lower-right (== upper-left + size)
IMGUI_API void AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, ImDrawFlags flags = 0); // a: upper-left, b: lower-right (== upper-left + size)
IMGUI_API void AddRectFilledMultiColor(const ImVec2& p_min, const ImVec2& p_max, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left);
IMGUI_API void AddQuad(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness = 1.0f);
@@ -3329,7 +3357,7 @@ struct ImDrawList
// General polygon
// - Only simple polygons are supported by filling functions (no self-intersections, no holes).
// - Concave polygon fill is more expensive than convex one: it has O(N^2) complexity. Provided as a convenience for the user but not used by the main library.
IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness);
IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, float thickness, ImDrawFlags flags = 0);
IMGUI_API void AddConvexPolyFilled(const ImVec2* points, int num_points, ImU32 col);
IMGUI_API void AddConcavePolyFilled(const ImVec2* points, int num_points, ImU32 col);
@@ -3349,7 +3377,7 @@ struct ImDrawList
inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path.Data[_Path.Size - 1], &pos, 8) != 0) _Path.push_back(pos); }
inline void PathFillConvex(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col); _Path.Size = 0; }
inline void PathFillConcave(ImU32 col) { AddConcavePolyFilled(_Path.Data, _Path.Size, col); _Path.Size = 0; }
inline void PathStroke(ImU32 col, ImDrawFlags flags = 0, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, flags, thickness); _Path.Size = 0; }
inline void PathStroke(ImU32 col, float thickness = 1.0f, ImDrawFlags flags = 0) { AddPolyline(_Path.Data, _Path.Size, col, thickness, flags); _Path.Size = 0; }
IMGUI_API void PathArcTo(const ImVec2& center, float radius, float a_min, float a_max, int num_segments = 0);
IMGUI_API void PathArcToFast(const ImVec2& center, float radius, int a_min_of_12, int a_max_of_12); // Use precomputed angles for a 12 steps circle
IMGUI_API void PathEllipticalArcTo(const ImVec2& center, const ImVec2& radius, float rot, float a_min, float a_max, int num_segments = 0); // Ellipse
@@ -3359,14 +3387,15 @@ struct ImDrawList
// Advanced: Draw Callbacks
// - May be used to alter render state (change sampler, blending, current shader). May be used to emit custom rendering commands (difficult to do correctly, but possible).
// - Use special ImDrawCallback_ResetRenderState callback to instruct backend to reset its render state to the default.
// - Use special GetPlatformIO().DrawCallback_ResetRenderState callback to instruct backend to reset its render state to the default.
// - See other standard callbacks in GetPlatformIO(), which may or not be supported by your backend.
// - Your rendering loop must check for 'UserCallback' in ImDrawCmd and call the function instead of rendering triangles. All standard backends are honoring this.
// - For some backends, the callback may access selected render-states exposed by the backend in a ImGui_ImplXXXX_RenderState structure pointed to by platform_io.Renderer_RenderState.
// - IMPORTANT: please be mindful of the different level of indirection between using size==0 (copying argument) and using size>0 (copying pointed data into a buffer).
// - If userdata_size == 0: we copy/store the 'userdata' argument as-is. It will be available unmodified in ImDrawCmd::UserCallbackData during render.
// - If userdata_size > 0, we copy/store 'userdata_size' bytes pointed to by 'userdata'. We store them in a buffer stored inside the drawlist. ImDrawCmd::UserCallbackData will point inside that buffer so you have to retrieve data from there. Your callback may need to use ImDrawCmd::UserCallbackDataSize if you expect dynamically-sized data.
// - Support for userdata_size > 0 was added in v1.91.4, October 2024. So earlier code always only allowed to copy/store a simple void*.
IMGUI_API void AddCallback(ImDrawCallback callback, void* userdata, size_t userdata_size = 0);
IMGUI_API void AddCallback(ImDrawCallback callback, void* userdata = NULL, size_t userdata_size = 0);
// Advanced: Miscellaneous
IMGUI_API void AddDrawCmd(); // This is useful if you need to forcefully create a new draw call (to allow for dependent rendering / blending). Otherwise primitives are merged into the same draw-call as much as possible
@@ -3396,8 +3425,15 @@ struct ImDrawList
// Obsolete names
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
inline void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawFlags flags, float thickness) { AddRect(p_min, p_max, col, rounding, thickness, flags); } // OBSOLETED in 1.92.8: NEW FUNCTION SIGNATURE HAS 'thickness' AND 'flags' SWAPPED.
inline void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness) { AddPolyline(points, num_points, col, thickness, flags); } // OBSOLETED in 1.92.8: NEW FUNCTION SIGNATURE HAS 'thickness' AND 'flags' SWAPPED.
inline void PathStroke(ImU32 col, ImDrawFlags flags, float thickness) { PathStroke(col, thickness, flags); } // OBSOLETED in 1.92.8: NEW FUNCTION SIGNATURE HAS 'thickness' AND 'flags' SWAPPED.
inline void PushTextureID(ImTextureRef tex_ref) { PushTexture(tex_ref); } // RENAMED in 1.92.0
inline void PopTextureID() { PopTexture(); } // RENAMED in 1.92.0
#else
void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding /*= 0.0f*/, ImDrawFlags flags /*= 0*/, float thickness /*= 1.0f*/) = delete;
void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness) = delete;
inline void PathStroke(ImU32 col, ImDrawFlags flags /*= 0*/, float thickness /*= 1.0f*/) = delete;
#endif
//inline void AddEllipse(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0, float thickness = 1.0f) { AddEllipse(center, ImVec2(radius_x, radius_y), col, rot, num_segments, thickness); } // OBSOLETED in 1.90.5 (Mar 2024)
//inline void AddEllipseFilled(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0) { AddEllipseFilled(center, ImVec2(radius_x, radius_y), col, rot, num_segments); } // OBSOLETED in 1.90.5 (Mar 2024)
@@ -3509,6 +3545,7 @@ struct ImTextureData
bool WantDestroyNextFrame; // rw - // [Internal] Queued to set ImTextureStatus_WantDestroy next frame. May still be used in the current frame.
// Functions
// - If GetPixels() functions asserts while being called by your render loop, it could be caused by calling ImFontAtlas::Clear() instead of ClearFonts()?
ImTextureData() { memset((void*)this, 0, sizeof(*this)); Status = ImTextureStatus_Destroyed; TexID = ImTextureID_Invalid; }
~ImTextureData() { DestroyPixels(); }
IMGUI_API void Create(ImTextureFormat format, int w, int h);
@@ -3664,13 +3701,13 @@ struct ImFontAtlas
IMGUI_API ImFont* AddFontFromMemoryCompressedBase85TTF(const char* compressed_font_data_base85, float size_pixels = 0.0f, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 parameter.
IMGUI_API void RemoveFont(ImFont* font);
IMGUI_API void Clear(); // Clear everything (input fonts, output glyphs/textures).
IMGUI_API void Clear(); // Clear everything (fonts + textures). Don't call mid-frame!
IMGUI_API void ClearFonts(); // Clear input+output font data/glyphs. You can call this mid-frame if you load new fonts afterwards!
IMGUI_API void CompactCache(); // Compact cached glyphs and texture.
IMGUI_API void SetFontLoader(const ImFontLoader* font_loader); // Change font loader at runtime.
// As we are transitioning toward a new font system, we expect to obsolete those soon:
IMGUI_API void ClearInputData(); // [OBSOLETE] Clear input data (all ImFontConfig structures including sizes, TTF data, glyph ranges, etc.) = all the data used to build the texture and fonts.
IMGUI_API void ClearFonts(); // [OBSOLETE] Clear input+output font data (same as ClearInputData() + glyphs storage, UV coordinates).
IMGUI_API void ClearTexData(); // [OBSOLETE] Clear CPU-side copy of the texture data. Saves RAM once the texture has been copied to graphics memory.
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
@@ -3842,6 +3879,7 @@ enum ImFontFlags_
ImFontFlags_NoLoadError = 1 << 1, // Disable throwing an error/assert when calling AddFontXXX() with missing file/data. Calling code is expected to check AddFontXXX() return value.
ImFontFlags_NoLoadGlyphs = 1 << 2, // [Internal] Disable loading new glyphs.
ImFontFlags_LockBakedSizes = 1 << 3, // [Internal] Disable loading new baked sizes, disable garbage collecting current ones. e.g. if you want to lock a font to a single size. Important: if you use this to preload given sizes, consider the possibility of multiple font density used on Retina display.
ImFontFlags_ImplicitRefSize = 1 << 4, // [Internal] Reference size was not set explicitly.
};
// Font runtime data and rendering
@@ -3887,7 +3925,7 @@ struct ImFont
IMGUI_API void RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, ImWchar c, const ImVec4* cpu_fine_clip = NULL);
IMGUI_API void 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 = 0.0f, ImDrawTextFlags flags = 0);
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
inline const char* CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) { return CalcWordWrapPosition(LegacySize * scale, text, text_end, wrap_width); }
inline const char* CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) { return CalcWordWrapPosition(LegacySize * scale, text, text_end, wrap_width); } // Obsoleted old name in 1.92.0. Note how `scale` was to `size`.
#endif
// [Internal] Don't use!
@@ -3906,8 +3944,10 @@ inline ImTextureID ImTextureRef::GetTexID() const
// Using an indirection to avoid patching ImDrawCmd after a SetTexID() call (but this could be an alternative solution too)
inline ImTextureID ImDrawCmd::GetTexID() const
{
// If you are getting this assert: A renderer backend with support for ImGuiBackendFlags_RendererHasTextures (1.92)
// must iterate and handle ImTextureData requests stored in ImDrawData::Textures[].
// If you are getting this assert with ImTextureID_Invalid == 0 and your ImTextureID is used to store an index or an offset:
// - You can add '#define ImTextureID_Invalid ((ImTextureID)-1)' in your imconfig.h file.
// If you are getting this assert with a renderer backend with support for ImGuiBackendFlags_RendererHasTextures (1.92+):
// - You must correctly iterate and handle ImTextureData requests stored in ImDrawData::Textures[]. See docs/BACKENDS.md.
ImTextureID tex_id = TexRef._TexData ? TexRef._TexData->TexID : TexRef._TexID; // == TexRef.GetTexID() above.
if (TexRef._TexData != NULL)
IM_ASSERT(tex_id != ImTextureID_Invalid && "ImDrawCmd is referring to ImTextureData that wasn't uploaded to graphics system. Backend must call ImTextureData::SetTexID() after handling ImTextureStatus_WantCreate request!");
@@ -4000,6 +4040,12 @@ struct ImGuiPlatformIO
// Written by some backends during ImGui_ImplXXXX_RenderDrawData() call to point backend_specific ImGui_ImplXXXX_RenderState* structure.
void* Renderer_RenderState;
// Standard draw callbacks provided by renderer backend.
ImDrawCallback DrawCallback_ResetRenderState; // Request to reset the graphics/render state.
ImDrawCallback DrawCallback_SetSamplerLinear; // Request backend to set texture sampling to Linear.
ImDrawCallback DrawCallback_SetSamplerNearest; // Request backend to set texture sampling to Nearest/Point.
//ImDrawCallback DrawCallback_SetSamplerCustom; // Request backend to set texture sampling using Backend Specific data.
//------------------------------------------------------------------
// Output
//------------------------------------------------------------------
@@ -4128,6 +4174,8 @@ namespace ImGui
//static inline void SetScrollPosHere() { SetScrollHere(); } // OBSOLETED in 1.42
}
#define ImDrawCallback_ResetRenderState (ImDrawCallback)(-8) // OBSOLETED in 1.92.8: Use ImGui::GetPlatformIO().DrawCallback_ResetRenderState
//-- OBSOLETED in 1.92.0: ImFontAtlasCustomRect becomes ImTextureRect
// - ImFontAtlasCustomRect::X,Y --> ImTextureRect::x,y
// - ImFontAtlasCustomRect::Width,Height --> ImTextureRect::w,h

Some files were not shown because too many files have changed in this diff Show More