Compare commits

...

499 Commits

Author SHA1 Message Date
ocornut
6ded5230d0 Changelog formatting amends 2026-02-17 18:32:57 +01:00
ocornut
e118ea06e0 Version 1.92.6 2026-02-17 17:45:07 +01:00
ocornut
f921abe7e7 InputTextMultiline(): fixed a minor bug where Shift+Wheel would allow a small horizontal scroll offset. (#9249) 2026-02-17 17:44:42 +01:00
ocornut
7609963448 Demo: fixes for Emscripten 5.0+ 2026-02-17 17:25:12 +01:00
ocornut
ff673d31df Backends: WebGPU: minor build fix for Emscripten 5.0.0 (note: our examples currently don't build with 5.0.1).
Getting 'warning: unused function 'CreateWGPUSurface' [-Wunused-function]' in some build paths.
cc #9246
2026-02-16 18:04:20 +01:00
ocornut
acdaaef625 Backends: further zealous warning fixes. (#9247) 2026-02-16 16:45:08 +01:00
Laurenz Altenmüller
fbe973a8d0 Cast this to (void*) in zero-clearing memset calls to fix -Wnontrivial-memcall (#9247, #8295, #8129, #8135)
Clang 20+ warns on memset(this, ...) for non-trivially copyable types via -Wnontrivial-memcall.
Should separately investigate -Wnonontrivial-memaccess vs -Wnonontrivial-memcall.
2026-02-16 16:29:00 +01:00
Naveen Regulla
eaa32bb787 Avoid using SSE intrinsic on ARM64/ARM64EC targets. (#9209, #5943, #4091) 2026-02-13 17:24:34 +01:00
ocornut
9f2b3bcf7a Backends: SDL2, SDL3: systems other than X11 are back to starting mouse capture on mouse down. Only X11 requires waiting for a drag by defaultadded ImGui_ImplSDL2_SetMouseCaptureMode(), ImGui_ImplSDL3_SetMouseCaptureMode(). (#9235, #3650, #6410, #3956, #3835)
Amend aa83d5d455
2026-02-13 16:01:08 +01:00
ocornut
041cdddf35 Fonts: add new ProggyForever font!
Amend f006400
2026-02-12 20:06:33 +01:00
ocornut
a8bf659143 Fonts: AddFontDefaultBitmap() doesn't need to explicitely set OversampleH/OversampleV to 1 as this is automatic. 2026-02-12 19:35:41 +01:00
ocornut
9c33672e5c Examples: reword a comment to not mention AddFontDefault() explicitly. 2026-02-12 18:37:31 +01:00
ocornut
42f28ba305 Fonts: avoid baking ExtraSizeScale twice into Ascent/Descent. (re)
Reapply 1bcc23e + offset for our current internal font using it.
2026-02-11 20:26:14 +01:00
ocornut
291787bcac Fonts: comment about swapping EllipsisChar value. (#9228) 2026-02-11 19:09:51 +01:00
ocornut
d67c66c437 Changed RenderTextEllipsis() logic to not trim trailing blanks before the ellipsis. (#9229) 2026-02-11 13:24:38 +01:00
ocornut
7b365fa6b4 Nav: fixed another occurence of nav cursor briefly appearing when Tabbing with ImGuiConfigFlags_NavEnableKeyboard disabled. (#9214, #9218)
Amend 1566c96cc + ea83628.
2026-02-10 22:04:15 +01:00
ocornut
87262dd07a Nav, IO: added undocumented ConfigNavEnableTabbing flag. (#9218) 2026-02-10 21:51:54 +01:00
Ryan Jensen
8ed10d538e Docs: update comment on ImGuiConfigFlags_NavEnableKeyboard. (#9218)
Reworked comment of original PR + trim trailing blanks.
2026-02-10 21:12:35 +01:00
ocornut
9f30044333 Backends: GLFW: try to set IMGUI_IMPL_GLFW_DISABLE_X11 / IMGUI_IMPL_GLFW_DISABLE_WAYLAND automatically if headers are not available. (#9225)
Amend/fix 10d0162378 for system without X11/Wayland headers. (#8921, #8920, #8969)
2026-02-10 20:50:46 +01:00
ocornut
fd9873a5c2 Tables: internals: extract TableSetColumnDisplayOrder() out of TableBeginApplyRequests() and clarify API limitations. 2026-02-10 18:12:53 +01:00
ocornut
c71b2a1fe6 Revert "Fonts: avoid baking ExtraSizeScale twice into Ascent/Descent."
This reverts commit 1bcc23ef12.
2026-02-10 17:56:37 +01:00
tanksdude
5fe48b6a0e Docs: fixed some typos (#9217) 2026-02-10 16:40:52 +01:00
ocornut
1bcc23ef12 Fonts: avoid baking ExtraSizeScale twice into Ascent/Descent.
Amend 55ad3b4
With extreme values of ExtraSizeScale offset would be noticeable in Descent - TextLink() function - or Ascent - TableAngledHeadersRow() function.
2026-02-05 16:52:04 +01:00
ocornut
524f01d248 Metrics: browsing font baked data persist tree state when e.g. using LoadAll. 2026-02-05 16:29:26 +01:00
ocornut
226f62fa8f Demo: amend Shortcuts demo to clarify that ImGuiInputFlags_RouteOverActive may be used with focused route. (#9004) 2026-02-05 15:27:01 +01:00
ocornut
ea83628438 Nav: fixed navigation cursor briefly appearing when using API to focus an InputText() in a window with _NoNavInputs flag. (#9214)
Amend 1566c96cc
2026-02-03 17:33:45 +01:00
ocornut
76860017d5 Clipper, Nav: fixed an UBSan warning when using in a ListClipper region . (#9160) 2026-02-02 17:24:32 +01:00
ocornut
4b8e41cffb TabBar: expose NextScrollToTabId to internal API. 2026-02-02 17:08:38 +01:00
ocornut
a9ca61a7ce Fonts: fixed an issue where using PushFont() from the implicit/fallback "Debug" window when its recorded state is collapsed would incorrectly early out. (#9210, #8865)
Amend 0e769c5, ca31693, d8da97f, 1bf41a0.
2026-02-02 16:00:33 +01:00
ocornut
5166bec5d8 Scrollbar: rounding corners selected based on a generic helper.
CalcRoundingFlagsForRectInRect() is backported and used multiple times by docking.
2026-01-29 17:23:28 +01:00
ocornut
6cc7787c77 Windows: shallow tweaks in window bg rendering to simplify diff w/ docking. 2026-01-29 14:14:15 +01:00
Ahmed Samy
960aff24fc Backends: Win32: use XInput Packet to avoid resubmitting gamepad data. (#9202, #8556) 2026-01-28 15:30:49 +01:00
ocornut
8306e32495 Nav: fixed speed scale for resizing/moving with keyboard/gamepad. (#323)
Fix 04157da29.
2026-01-28 15:14:15 +01:00
ocornut
814c6a194b Log/Capture: fixed erroneously injecting extra carriage returns in output. 2026-01-26 12:29:42 +01:00
Tom Seddon
ab6c9d9b12 Ignore -Wsign-conversion warnings when building with gcc. (#9192)
Co-authored-by: Tom Seddon <tom@trlinux>
2026-01-26 11:51:22 +01:00
ocornut
d12b1a938e Demo: improved Selectable() demos. (#9193) 2026-01-26 11:45:32 +01:00
ocornut
c91bcea7a8 Backends: SDLGPU3: fixed missing release of TexSamplerNearest. (#9196)
Amend/fix 8b86c939c7
2026-01-25 13:30:28 +01:00
ocornut
c6e54c7ab5 Comments about input queue being close to be supporting multi-thread. (#5772) 2026-01-25 13:29:21 +01:00
ocornut
d1cf58e590 Nav: fixed WrapX/LoopX handling in menu layer. (#9178)
Amend 3050f653cb
2026-01-23 16:00:28 +01:00
RegimantasSimkus
e1217227b2 Tooltips, Disabled: fixed EndDisabledOverrideReenable() assertion when nesting a tooltip in a disabled block. (#9180, #7640)
Amend f953ebf9ca
2026-01-23 15:29:27 +01:00
ocornut
7250fbde2e Fixed warning compiling stb_truetype with MSVC, C++20 with /w15262 (#9189) 2026-01-23 14:29:20 +01:00
ocornut
a117055b6b Internals: move field for locality. 2026-01-22 20:13:35 +01:00
ocornut
b015acc464 Viewports: added GetWindowViewport() in imgui_internal.h to increase consistency with code using this public API in docking branch. (#9140) 2026-01-22 17:50:25 +01:00
ocornut
3050f653cb Menus, Nav: made navigation into menu-bar auto wrap on X axis. (#9178) 2026-01-22 17:33:35 +01:00
ocornut
66bb8add73 Docs: better document Shortcut() related stuff. (#9188) Better document io.ConfigDpiScaleFonts. (#9179) 2026-01-22 14:35:16 +01:00
ocornut
3aba95060e Fonts: adding new fonts after removing all fonts mid-frame properly updates current state. 2026-01-21 19:53:55 +01:00
ocornut
cb3b7ff4fb InputText: added mGuiInputTextCallbackData::EventActive helpers. (#9174) 2026-01-21 18:46:38 +01:00
ocornut
d448045669 InputText: Added ImGuiInputTextCallbackData::ID field. 2026-01-21 18:34:28 +01:00
ocornut
f21307e5c9 InputText: ImGuiInputTextCallbackData::SelectAll() sets CursorPos. Added SetSelection() helper.
Context was for #9174 but not specific to it.
2026-01-21 18:25:38 +01:00
ocornut
42b7704b70 InputText: add ImGuiInputTextState::SetSelection() helper + make TextSrc valid outside scope for non-read only fields. (#9174) 2026-01-21 18:19:03 +01:00
Pádraic Slattery
3803203d47 CI: update outdated GitHub Actions versions (#9186) 2026-01-21 17:34:30 +01:00
ocornut
8c0b410371 Docs: tweaks. 2026-01-20 18:25:18 +01:00
ocornut
8b86c939c7 Backends: DirectX10, DirectX11, SDLGPU3: added nearest sampler in ImGui_ImplDX10_RenderState/ImGui_ImplDX11_RenderState/ImGui_ImplSDLGPU3_RenderState struct.
(#6969, #5834, #7468, #3590, #9173, #8926, #7230, #5118, #3590, #2973, #6969)
2026-01-19 13:02:25 +01:00
thedmd
b933599f00 Backends: DirectX12: added helpers to switch to Linear sampler (yet not made public, but intended to be forward declared). (#9173) 2026-01-19 12:32:45 +01:00
ocornut
12223cc3e9 Error handling: rework macros, add IM_ASSERT_USER_ERROR_RET(), IM_ASSERT_USER_ERROR_RETV() to simplify code. 2026-01-19 12:16:10 +01:00
ocornut
ea122de913 Error handling: Improve error handling and recovery for TableSetupColumn(). 2026-01-19 11:49:11 +01:00
ocornut
14dfd5bf6b Examples: DX12: update to VS2019 so it supports WIndows SDK 10.0 simplified versioning. 2026-01-19 11:42:08 +01:00
E
5dde06b327 Docs: fixed 'Tearaway' link in credits section (#9176) 2026-01-18 23:45:38 +01:00
ocornut
21d3299e58 Backends: fixed reappearing uses to NULL to favor nullptr. 2026-01-15 16:09:01 +01:00
ocornut
d7598aa84f Backends: SDL2, SDL3: changed GetClipboardText() handler to return NULL on error aka clipboard contents is not text. (#9168)
Consistent with other backends.
2026-01-15 16:08:18 +01:00
ocornut
9a6eb0ab25 Backends: Vulkan: ImGui_ImplVulkanH_DestroyWindow() oes not call vkDestroySurfaceKHR(): because surface is created by caller. (#9163)
# Conflicts:
#	backends/imgui_impl_vulkan.cpp
2026-01-14 19:37:05 +01:00
ocornut
a1dfaf4869 ImageButton() doesn't use a clamped style.FrameRounding value but instead adjust inner image rounding when FramePadding > FrameRounding. (#2942, #845) 2026-01-14 15:55:07 +01:00
ocornut
7143d711bf Images, Style: added style.ImageRounding, ImGuiStyleVar_ImageRounding to configure rounding of Image() widgets. (#2942, #845)
Moving border drawing above AddImage() call, should not make a difference for square images.
2026-01-14 15:55:03 +01:00
ocornut
0d08927dae Error handling: Improve error handling and recovery for EndMenu()/EndCombo(). (#1651, #9165, #8499) 2026-01-14 14:59:39 +01:00
ocornut
791ad9b82d InvisibleButton: allow calling with size (0,0) to fit to available content size. (#9166, #7623) 2026-01-13 16:15:48 +01:00
ocornut
f64c7c37ef Fonts: fixed a crash when trying to use AddFont() with MergeMode=true on a font that has already been rendered. (#9162) 2026-01-12 18:17:38 +01:00
ocornut
d1c5a66557 Backends: WebGPU: rework unsupported path into an assert. (#9155, #9156) 2026-01-12 12:11:10 +01:00
ocornut
f5384544cb (Breaking) Commented out legacy names obsoleted in 1.90 (Sept 2023): BeginChildFrame(), EndChildFrame(), ShowStackToolWindow(), IM_OFFSETOF(), IM_FLOOR(). 2026-01-08 17:33:09 +01:00
ocornut
fedf227ea4 Amend 7a02f4b. 2026-01-08 17:17:06 +01:00
ocornut
7a02f4b545 Nav, Shortcuts, Tooltips: tooltip reference position not affected by remote shortcut activation. (#9138, #456)
NavCalcPreferredRefPos() has different path for popups vs tooltip.
Amend 197f8904fe
2026-01-08 17:14:38 +01:00
ocornut
ca9b7b4071 InputText, Nav: amend 1566c96. (incorrectly commited old chunk) 2026-01-08 17:11:23 +01:00
ocornut
1566c96ccd InputText, Nav: fixed remote/shortcut InputText() not teleporting mouse cursor when nav cursor is active and io.ConfigNavMoveSetMousePos is enabled.
Motivated by this, also made SetFocusID() immediately set g.NavIdIsAlive, which is more correct and might be other (positive) subtle side effects.
2026-01-08 17:04:52 +01:00
ocornut
3389dfd9dd IsItemHovered() doesn't filter out the signal when activated item is a shortcut remote activation. (#9138, #456)
Amend a201af7354
2026-01-08 15:58:12 +01:00
ocornut
9ce41a92c3 Misc/shallow merges from docking branch to reduce small drift. 2026-01-08 14:31:25 +01:00
maf
43a90adc61 Docs: Fix spelling errors (#9158) 2026-01-08 09:17:44 +01:00
ocornut
7b3ad4a282 (Breaking) Popups: changed 'ImGuiPopupFlags popup_flags = 1' default value to be '= 0' for BeginPopupContextItem(), BeginPopupContextWindow(), BeginPopupContextVoid(), OpenPopupOnItemClick(). (#9157, #9146) 2026-01-07 18:15:15 +01:00
JD31
4ce188def8 Backends: WebGPU: clarify build failure when attempting to build with Dawn for iOS. (#9155, #9156) 2026-01-07 17:25:41 +01:00
ocornut
b467a0466c Docs: amends comments about fonts. 2026-01-06 19:07:46 +01:00
ocornut
69a501df6e Backends: OpenGL3: call ImGui_ImplOpenGL3_InitLoader() in ImGui_ImplOpenGL3_CreateDeviceObjects() / ImGui_ImplOpenGL3_DestroyDeviceObjects(). (#9112) 2026-01-05 16:46:56 +01:00
ocornut
1dc1964d5b Backends: Vulkan: change ImGui_ImplVulkanH_Window::ClearEnable to fuller featured AttachmentDesc. (#9152) 2026-01-05 16:39:49 +01:00
ocornut
f106ccd5fa Backends: Vulkan: clarify ImGui_ImplVulkanH_Window members. 2026-01-05 16:38:01 +01:00
Sammy Fatnassi
25158fe33b Textures: prevent assert/crash of having a destroyed texture recreated without the pixels data available (#9150, #8811)
Amend 8c22b8aef
2026-01-03 20:26:29 +01:00
ocornut
960921f03a Happy new year! 2026-01-03 01:07:58 +01:00
ocornut
922a11f084 Docs: update links, refs. 2025-12-23 19:33:37 +01:00
ocornut
b7b8f52437 Examples: Android: update for consistency (untested). 2025-12-23 18:16:33 +01:00
ocornut
05581da183 AddFontDefault() now automatically selects an embedded font between AddFontDefaultVector() and AddFontDefaultBitmap). 2025-12-23 18:16:33 +01:00
ocornut
f006400f05 Fonts: added AddFontDefaultVector() with embedded ProggyVector data. 2025-12-23 18:16:33 +01:00
ocornut
cde6ad3967 Removed unused ImRect::Floor(). Clarified IM_TRUNC(), IM_ROUND(), ImRound64().
Better to remove since it uses IM_TRUNC which has unusual specs.
Note: 87a6443c5 always use positive value in ImRound64(). (#3609, #8215)
2025-12-23 18:16:33 +01:00
ocornut
73dd0e869d (Breaking) Fonts: remove ImFontConfig::PixelSnapV. Post-rescale GlyphOffset is always rounded.
Amend 99f6b305c, 99bca397d8.
2025-12-23 18:16:33 +01:00
ocornut
55ad3b4abd Fonts: added ExtraSizeScale feature (undocumented). 2025-12-23 18:16:32 +01:00
ocornut
d1de937c31 Fonts: ImFontAtlasFontRebuildOutput() helper. 2025-12-23 18:16:32 +01:00
ocornut
d365417e8b CI: reduce macOS runs since they are expensive. 2025-12-23 16:47:44 +01:00
ocornut
0ff810038d Added GetItemFlags() in public API. (#9127) 2025-12-22 18:33:12 +01:00
ocornut
9055c9ed22 imgui_freetype: fixed overwriting ImFontConfig::PixelSnapH when hinting is enabled.
Fix/amend 99f6b305c1.
2025-12-22 17:52:32 +01:00
ocornut
d87650dffb Text: fixed unused variable warning on builds without asserts. 2025-12-21 18:22:48 +01:00
ocornut
a5dffbec38 Text: word-wrapping use a small lookup table. (#8990, #3237, #8503, #8139, #8439, #9094, #3002, #9066, #8838) 2025-12-21 18:04:01 +01:00
ocornut
22ffa3d6d3 Text: rewrite word-wrapping logic. (#8990, #3237, #8503, #8139, #8439, #9094, #3002, #9066, #8838) 2025-12-21 18:04:00 +01:00
ocornut
683f9160b9 Internals: ImBitArray: rename storage. 2025-12-18 23:38:34 +01:00
ocornut
4e7c05504a Renamed IM_ARRAYSIZE() -> IM_COUNTOF(). Kept legacy name for now. 2025-12-17 14:30:01 +01:00
ocornut
99bca397d8 Docs: clarify PixelSnapH / PixelSnapV + comment on PushTextWrapPos(). 2025-12-17 12:02:07 +01:00
ocornut
dc48a7c88e Docs: amend fc89c61 2025-12-15 16:59:22 +01:00
ocornut
4dac00ca0c Windows: fixed always updating internal buffer for ### window titles even when Ctrl+Tab window is hidden. Instead forcing an update on mismatching when appearing.
3997e8b555 was already doing that. (Relates to 8e67fe1: code assume pointer used to be nulled when ctrl+tab window is disabled. not the case).
2025-12-11 23:24:43 +01:00
omar
fc89c61089 Hashing: handling of "###" operator to reset to seed within a string identifier doesn't include the "###" characters in the output hash anymore.
This has various simplifying properties.
Need a test engine update too.
+ Demo: removed misleading/unnecessary usage of ###.
2025-12-11 23:02:20 +01:00
ocornut
1e7d2adc29 Fixed Clang cast-align warning + Added missing Changelog entry in 1.92.4. (#8893) 2025-12-11 21:37:42 +01:00
ocornut
bd6f48fe20 Backends: OpenGL3: Fixed embedded loader multiple init/shutdown cycles broken on some platforms. (#8792, #9112) 2025-12-11 18:28:23 +01:00
ocornut
0d2dd30ee9 Tabs: minor tweaks to facilitate mods altering spacing. 2025-12-11 17:17:57 +01:00
ocornut
9971251574 Fonts: amend/comment on FontDataOwnedByAtlas=false fix being a breaking change. (#9086, #8465) 2025-12-10 21:42:07 +01:00
ocornut
a07b2828ce Backends: GLFW: add IMGUI_IMPL_GLFW_DISABLE_X11 / IMGUI_IMPL_GLFW_DISABLE_WAYLAND. (#9109, #9116)
cc #8884, #8474, #8289
2025-12-10 18:57:02 +01:00
ocornut
9a4fd69f6d Backends: GLFW: avoid repeated glfwSetCursor()/glfwSetInputMode() calls when unnecessary. 2025-12-10 18:35:22 +01:00
ocornut
cf64b7fa72 Tables: Fixed losing stored display order when reducing column count. (#9108, #4046)
Amend f2df804fcc
2025-12-08 19:29:41 +01:00
ocornut
a726bded11 Fonts: ClearOutputData() doesn't need to clear FallbackChar, EllipsisChar. Fixed crash changing font loader. 2025-12-05 19:12:50 +01:00
ocornut
7f78f52243 Demo: removed some hardcoded widths. 2025-12-05 18:46:13 +01:00
ocornut
60f8b0733c Rework color marker internals to facilitate arbitrary override using SetNextItemColorMarker().
Amend fa4b47c
2025-12-05 18:28:55 +01:00
ocornut
fa4b47c5e2 Added RGBA color markers to ColorEdit3/ColorEdit4 + opt-in ImGuiSliderFlags_ColorMarkers for Drags/Sliders.
+ Added ImGuiColorEditFlags_NoColorMarkers
+ Added style.ColorMarkerSize.
2025-12-05 16:32:48 +01:00
ocornut
a7ecbcdeba Shuffle ImGuiColorEditFlags flag values.
ImGuiColorEditFlags_AlphaOpaque, ImGuiColorEditFlags_AlphaNoBg, ImGuiColorEditFlags_AlphaPreviewHalf, ImGuiColorEditFlags_AlphaBar.
2025-12-05 16:32:45 +01:00
ocornut
ded52c71d9 Debug Log: can output to debugger. Added ImGuiDebugLogFlags_OutputToDebugger. 2025-12-05 15:07:44 +01:00
ocornut
9d4fafa671 Nav: removed an unnecessary FindWindowByName() call.
Amend c7016c25e8. It's not clear to me why it was committed like that, maybe a leftover of wip code which used the pointer before Begin().
2025-12-05 14:16:14 +01:00
ocornut
e2c49530cb ImDrawList: harden/clarify static asserts about ImDrawCmd / ImDrawCmdHeader layout. 2025-12-05 13:42:15 +01:00
achabense
fee06a92ea Text: fixed word-wrapping function reading from *text_end when passed a string range. (#9107)
Likely caused by 4d4889bf1b (#5720)
2025-12-05 13:23:26 +01:00
ocornut
d71091a957 Internals: amend RenderRectFilledRangeH() to avoid shadowed variables. 2025-12-04 16:27:54 +01:00
ocornut
d1e262ad55 Internals: refactor RenderRectFilledRangeH() into RenderRectFilledInRangeH() to take absolute coordinates instead of normalized ones.
Amend 01d4bf299a (#1296)
2025-12-04 16:13:12 +01:00
ocornut
6e0ee6ff03 Fonts: removed misleading SizePixels >= 0.0f test and stbtt_ScaleForMappingEmToPixels() call in ImGui_ImplStbTrueType_FontSrcInit(). (#8857)
Logic was picked in 9a9712807e while extracting code from stbtt_PackFontRangesGatherRects(), but ScaleForMappingEmToPixels() was actually never called: we assert against negative SizePixels since 2015.
2025-12-03 20:15:58 +01:00
ulhc
d27dce58cd Backends: Win32: handle WM_IME_CHAR/WM_IME_COMPOSITION messages to support Unicode inputs on MBCS Windows. (#9099, #3653, #5961) 2025-12-03 13:34:57 +01:00
ocornut
87b193399e Backends: Win32: change param to MultiByteToWideChar() to be consistent (should be no-op?).
Amend 0a7054c7e4 (#5725, #1807, #471, #2815, #1060 + #9099, #3653, #5961)
2025-12-03 13:30:59 +01:00
ocornut
bfe137893a Debug Log: fixed incorrectly printing characters in IO log when submitting non-ASCII values to io.AddInputCharacter(). (#9099) 2025-12-01 17:03:04 +01:00
ocornut
620a33dd85 TreeNode: fixed highlight position when used inside a line with a large text baseline offset.
Most old logic e.g. df749e3f13, ec0e953cca. Never quite worked for this situation.
2025-11-27 23:49:17 +01:00
ocornut
47766ca403 Demo: fix in 'Demo->Selection->Multi-Select in a Table' section. 2025-11-27 23:45:50 +01:00
ocornut
7c6febed66 Tables: fixed an issue where submitting non-integer row heights would eventually advance table parent layout by +0/+1 depending on its visibility. 2025-11-27 22:54:51 +01:00
ocornut
1a62292ac0 Tables: fixed an issue where a very thin scrolling table would advance parent layout slightly differently depending on its visibility. 2025-11-27 22:37:00 +01:00
ocornut
2026e3db88 Menus: fixed BeginMenu() child popup position when used inside a line with a baseline offset. 2025-11-27 21:51:04 +01:00
ocornut
3ff8c466bf Menus: fixed BeginMenuEx() icon/arrow baseline when using inside a line with an offset.
Amend 1f54665.
2025-11-27 20:05:18 +01:00
ocornut
1f54665799 Menus: fixed MenuItem() label baseline when using inside a line with an offset.
Amend f8fae02270
2025-11-27 19:54:06 +01:00
ocornut
ae873b1e0d Misc: rename extraneous parenthesizes from return statements. 2025-11-27 15:01:24 +01:00
ocornut
9c75ef5a61 Tables: clarify TableNextRow() row_height and adjust demo to make this clearer (demo height were arbitrary and therefore misleading). 2025-11-26 18:25:30 +01:00
ocornut
c36162fc6c Internals: add SetContextName() helper. (#9097)
Amend 37c243b.
2025-11-26 17:29:37 +01:00
Rémy Tassoux
f0699effed Examples: Win32+DirectX12: Disable breaking on the D3D12_MESSAGE_ID_FENCE_ZERO_WAIT warning. (#9093, #9084) 2025-11-26 15:39:37 +01:00
ocornut
75db81cf08 Backends: SDL_GPU3: select between metallib and MSL shaders based on availability. (#9076)
Amend fd887f5
2025-11-26 15:05:05 +01:00
Leon Lysak
fd887f5241 Backends: SDL_GPU3: use MSL on macOS and MetalLib on iOS to fix shader compatibility. (#9076)
Edit original PR to keep metallib shader binary since next commit is going to use them.
2025-11-26 15:01:03 +01:00
ocornut
285e3042ba Docs: tweaks. Add reference to imgui-module from main README. (#9092, #8868) 2025-11-26 14:49:11 +01:00
ocornut
d981b33dd0 Textures: amend to please static analyzer. 2025-11-26 14:24:55 +01:00
ocornut
e768f91dc2 Textures: fixed displaying texture # in metrics/debugger. 2025-11-26 14:21:48 +01:00
ocornut
3fef0d553d Textures: fixed a building issue when ImTextureID is defined as a struct.
+ Added CI for this case.
2025-11-26 14:21:48 +01:00
ocornut
3a45bae9dc Backends: Vulkan: helper for creating a swapchain selects VkSwapchainCreateInfoKHR's compositeAlpha based on cap.supportedCompositeAlpha. (#8784) 2025-11-24 18:11:23 +01:00
ocornut
98636f4a23 Fonts: fixed handling of ImFontConfig::FontDataOwnedByAtlas = false which did erroneously make a copy of the font data. (#9086)
Amend 815168c7e
+ Added explicit casts for intent/clarity when passing to stb_truetype/freetype.
2025-11-24 15:58:01 +01:00
ocornut
5f82275ba1 Docs: updated 1.91.5 logs for missing info that GetKeyIndex() was removed at this date.
Amend 6f287dd16
2025-11-24 14:49:16 +01:00
ocornut
136d067eed Scrollbar: fixed a codepath leading to a divide-by-zero. (#9089) 2025-11-24 14:27:03 +01:00
ocornut
324cea1f41 Version 1.92.6 WIP 2025-11-24 13:35:41 +01:00
ocornut
ee48fad09d Internals: rename ImStableVector's BLOCK_SIZE to avoid conflict with Linux header defines. (#9088) 2025-11-21 19:47:03 +01:00
ocornut
6d910d5487 Version 1.92.5 2025-11-20 17:49:52 +01:00
ocornut
26ff93dadc Examples: NULL: fixed msvc project. 2025-11-20 14:51:25 +01:00
ocornut
a484fd2b56 Examples: Win32+OpenGL3: enable DPI awareness. (#9083) 2025-11-20 14:50:08 +01:00
Rokas Kupstys
8ff7f35eec CI: run imgui_test_suite as part of CI build. 2025-11-20 14:35:48 +01:00
Rokas Kupstys
e8448d0494 CI: general update + rename steps. 2025-11-20 14:33:23 +01:00
ocornut
4ab86e1d61 Nav: fixed scoring when using PageUp/PageDown from a focused item which is outside of visible boundaries. (#9079)
We only use ImGuiNavMoveFlags_AlsoScoreVisibleSet when starting point is visible.
2025-11-19 19:01:22 +01:00
ocornut
0faa0dba15 Drag and Drop: rework cancel drag and drop logic to be overridable. (#9071) 2025-11-19 18:26:44 +01:00
ocornut
db6b8e0fb3 Drag and Drop: handling of Escape after UpdateKeyboardInputs(). (#9071) 2025-11-19 18:26:43 +01:00
ocornut
1f16ca5e5c Docs: update ShowUserGuide() + PR guidelines. (#9071) 2025-11-19 18:26:43 +01:00
ocornut
b4a3d423e0 Docs: amend BeginDisabled() comments. (#9082) 2025-11-19 17:06:44 +01:00
achabense
68894d4149 Docs: fixed outdated comment. (#9082) 2025-11-19 17:03:14 +01:00
ocornut
23bd697f05 Drag and Drop: Pressing Escape while carrying a payload automatically cancel the active drag and drop. (#9071) 2025-11-18 19:18:10 +01:00
ocornut
37f9153105 Nav: improved/clarified behavior when requesting PageUp/PageDown from a focused item which is outside of visible boundaries. (#9079) 2025-11-18 18:59:06 +01:00
ocornut
81e01ddebe Nav: reworked PageUp/PageDown to pick same-page top/bottom page based on inner rectangle rather than clipping rectangle. 2025-11-18 18:57:32 +01:00
ocornut
405c802607 Nav: shallow tweaks. 2025-11-18 18:22:36 +01:00
ocornut
91b5256c57 Clipper: fixed an issue when using up/down from an item outside of visible bound and using the clipper. (#9079) 2025-11-18 17:00:01 +01:00
ocornut
6ae32c696a Backends: fixed misc zealous Clang warnings. 2025-11-18 16:34:35 +01:00
ocornut
9afc62d087 InputText: Fixed an assert when using ImGuiInputTextFlags_ReadOnly and making underlying contents shorter while text is selected. (#9069) 2025-11-18 16:20:51 +01:00
ocornut
c3835de38a CI: fixes warning building example_null w/ msvc as DLL 2025-11-17 18:01:51 +01:00
ocornut
52caa2f38a CI: fixes warning building example_null w/ msvc as DLL 2025-11-17 17:50:37 +01:00
ocornut
04af1a3917 CI: fixes warning building example_null w/ mingw 64-bit, as DLL 2025-11-17 17:43:09 +01:00
ocornut
e1f9b8b3a7 CI: fixes warning building example_null w/ mingw 64-bit, as DLL 2025-11-17 16:49:34 +01:00
ocornut
cfb48969af Examples: CI: backtrack and make example_null embed backend: simpler for all sorts of quick build scripts. 2025-11-17 16:38:07 +01:00
ocornut
0cf5b93a0a CI, Backends: fixes for example_null building. Add consistent IMGUI_IMPL_API in backend. 2025-11-17 16:18:12 +01:00
ocornut
d99baf332c CI: fixes for example_null building. 2025-11-17 16:11:05 +01:00
ocornut
7e919a543c Examples: fix example_null Makefile.
Amend b885382,eb19a77
2025-11-17 15:58:12 +01:00
ocornut
eb19a77848 Examples: fix example_null Makefile.
Amend b885382
2025-11-17 15:52:32 +01:00
ocornut
b885382a63 Backends: Null: added imgui_impl_null platform/renderer backend. 2025-11-17 15:28:03 +01:00
ocornut
9e15ebb402 Backends: GLFW: fixed last ImGui_ImplGlfw_Shutdown() call not immediately clearing the context map. (#9075, #8676, #8239, #8069)
Amend/fix f633a6058
2025-11-17 13:38:17 +01:00
ocornut
f145b0cffd Debug Tools: ID Stack Tool: refactor, extract data/code into ImGuiDebugItemPathQuery for reuse. 2025-11-13 18:32:43 +01:00
ocornut
c254db7637 Debug Tools: ID Stack Tool: store ResultsComplete and don't display incomplete paths. 2025-11-13 16:19:27 +01:00
ocornut
5a0c67c4b8 Debug Tools: ID Stack Tool: extracted code into a StackToolGetResultAsPath() function. 2025-11-13 16:15:00 +01:00
ocornut
ec6219752d Fonts: calling ImFontAtlas::Clear() mid-frame without re-adding a font will lead to a more explicit crash. (#9067)
+ reformat Changelog.
2025-11-13 15:54:50 +01:00
ocornut
d246850787 Fonts: added comment about the classic AddFontFromMemoryTTF() issue. (#9067, #6916, #6781, #5330, #4307, #2042, #2029, #1734, #1259, #220) 2025-11-13 15:42:19 +01:00
ocornut
e60e5bff63 Misc: standardized casing of keyboard mods in comments and demo ("CTRL" -> "Ctrl"). 2025-11-13 15:24:03 +01:00
ocornut
873fe34b31 Debug Tools: ID Stack Tool: preserve first data type, so user of PushOverrideID() e.g. TreeNode() elements don't get demoted from _String to _ID. 2025-11-13 15:05:16 +01:00
ocornut
e3979c2098 Demo: removing absolute __FILE_ from being emitted by default. (#9033) 2025-11-13 14:23:25 +01:00
ocornut
68a44776bd Misc: tweak conflicting id error tooltip to use a link.
Now that nested tooltips are not hiding each others.
2025-11-13 13:47:45 +01:00
ocornut
613cfaf0b4 Tooltips: made BeginTooltipEx() not hide nested tooltips.
It's not typically possible to nest tooltips since BeginTooltipEx() imply ImGuiWindowFlags_NoInputs + following mouse pos + most tooltips would be triggered on hover. But BeginErrorTooltip() bypass that.
2025-11-13 13:47:45 +01:00
ocornut
de917ebb95 Windows: move auto-fit block into braces for clarify. (no-op) 2025-11-11 21:48:17 +01:00
ocornut
501e0adcdb Windows: CalcWindowAutoFitSize() remove child-specific hack added by 29439bdd27 and made obsolete by 7537ba2b4. (#9060, #1710) 2025-11-11 21:47:15 +01:00
ocornut
a2544f9496 Windows: programmatic auto-sizing on a single axis also apply proper logic. (#9060) 2025-11-11 21:37:21 +01:00
ocornut
b51f6e073c Windows: reorganize auto-fitting code blocks in Begin(), step 2.
Toward #9060
2025-11-11 21:15:43 +01:00
ocornut
52e9d94f93 Windows: reorganize auto-fitting code blocks in Begin(), aimed to have no side-effect, but..
..outer ImGuiWindowFlags_AlwaysAutoResize previously took priority for both axis. New logic per-axis.
Toward #9060
2025-11-11 20:03:31 +01:00
ocornut
fc262355ca Windows: Fixed an issue where repeated calls to SetNextWindowSize() using 0.0f to auto-size would keep marking ini settings as dirty.
+ marking dirty on old io.FontAllowUserScaling Ctrl+Wheel
2025-11-11 19:47:48 +01:00
ocornut
7537ba2b44 Windows: fixed single-axis auto-sizing (via double-clicking a border) to take account of remaining scrollbar on the other axis. (#9060)
Potentially now should apply same logic to the other resizing path also described in #9060
2025-11-10 19:36:16 +01:00
ocornut
86daa8930e Backends, Examples: WebGPU: simplified ifndef (#8381) 2025-11-07 13:24:16 +01:00
ocornut
635eb1d8e9 Added .tmp files. 2025-11-06 18:07:18 +01:00
ocornut
bd0e2036e0 Drag and Drop: added ImGuiDragDropFlags_AcceptDrawAsHovered. (#8632)
Not calling SetHoveredId() in that path, does not seem necessary.
2025-11-06 18:07:18 +01:00
ocornut
b0d3c3a674 Drag and Drop: prev/curr storage for DragDropAcceptFlags. ImGuiDragDropFlags_AcceptNoPreviewTooltip test uses DragDropAcceptFlagsPrev for consistency. (#143)
I don't think this would have materialized as a visible bug.
2025-11-06 17:59:01 +01:00
ocornut
dacd080639 Docs: added link to imgui-module. (#8868( 2025-11-06 17:30:00 +01:00
ocornut
8e2e87d638 (Breaking) Commented out legacy SetItemAllowOverlap() obsoleted in 1.89.7: this never worked right. Use SetNextItemAllowOverlap() _before_ item instead. 2025-11-06 16:29:19 +01:00
ocornut
e389502ffb Amends comments referring to 1.92.X to refer to 1.92.0. FontAllowUserScaling not marked obsolete anymore. 2025-11-06 16:28:59 +01:00
ocornut
1c3a60047c (Breaking) IO: commented out legacy io.ClearInputCharacters() obsoleted in 1.89.8. 2025-11-06 16:28:58 +01:00
ocornut
62162747e7 (Breaking) Keys: commented out legacy names which were obsoleted in 1.89.
ImGuiKey_ModCtrl --> ImGuiMod_Ctrl, ImGuiKey_ModShift --> ImGuiMod_Shift, ImGuiKey_ModAlt --> ImGuiMod_Alt, ImGuiKey_ModSuper --> ImGuiMod_Super.
2025-11-06 16:28:25 +01:00
ocornut
189d8c9d9c (Breaking) Commented out legacy ImGuiChildFlags_Border (#462), ImGuiWindowFlags_NavFlattened (#7687), ImGuiWindowFlags_AlwaysUseWindowPadding. 2025-11-06 16:11:07 +01:00
ocornut
f45adb995c Drag and Drop, Style: added basic styling options to DragDrop target rect. Amends. (#9056) 2025-11-06 15:38:20 +01:00
aaronkirkham
7954d6782e Drag and Drop, Style: added basic styling options to DragDrop target rect. (#9056) 2025-11-06 15:34:40 +01:00
Clownacy
59db6ceeb1 Backends: GLFW: lower minimum requirement from GLFW 3.1 to GLFW 3.0. (#9055) 2025-11-06 15:25:11 +01:00
ocornut
a0bfbe4d8f Windows: BgClickFlags inherited by default + missing info in Changelog. Amend 40f9e4e. (#899, #3071, #5044, #3379) 2025-11-05 20:16:45 +01:00
ocornut
e674f57bb6 Backends: SDL3: Fixed an issue with missing characters events when an already active text field changes viewports. (#9054)
Always use SDL_GetKeyboardFocus().
(tried to defer ImGui_ImplSDL3_PlatformSetImeData() processing for when OS-window is available but it didn't actually work because we don't systemetically OS-focus new viewports and SDL3 only sent characters to keyboard focused window.)
2025-11-05 19:15:47 +01:00
ocornut
1897248bda Misc: added assert to detect ~ImGuiContext() called without DestroyContext(). (#9051) 2025-11-04 17:55:18 +01:00
ocornut
051a31594f Metrics: fixed table and columns rect highlight from display when metrics window is not in the same viewport as the table. 2025-11-03 19:48:57 +01:00
ocornut
dc6e0f4b9e Tables: Angled headers: fixed an auto-resize feedback loop that could affect tables with empty non-resizing columns using angled headers. 2025-11-03 19:35:19 +01:00
BrutPitt
df3f2fff88 Examples: WebGPU: moved CreateWGPUSurface to the bottom of the file due to interference with X.h. (#8381) 2025-11-03 19:15:41 +01:00
ocornut
8e5e79054e Examples: WGPU: tweak headers and standardize other things so examples have less differences. (#8381) 2025-11-03 19:05:28 +01:00
BrutPitt
3cc8b470a6 Backends, Examples: WebGPU: header optimization. Added the code for using Dawn “pre-built” library. (#8381) 2025-11-03 19:05:28 +01:00
ocornut
f1becf7e4b Amend 149587b config/build infos change to be resilient to IM_ASSERT() macros using stringification inside a list. 2025-11-03 14:31:14 +01:00
Brenton Bostick
a3546b52f8 Various typo fixes (#9042) 2025-11-03 13:26:12 +01:00
ocornut
823ccc274e Examples: update docs. (#8381) 2025-10-31 19:34:12 +01:00
BrutPitt
ff672b2db3 Examples: SDL2+WebGPU, SDL3+WebGPU: add new examples. (#8381) 2025-10-31 19:10:23 +01:00
BrutPitt
778aed9966 Examples: GLFW+WebGPU: update to latest specs and to work on Emscripten 4.0.10+ and latest Dawn-Native, WGPU-Native. (#8381, #8567, #8191, #7435) 2025-10-31 19:10:23 +01:00
BrutPitt
c5b2a848fa Backends: WebGPU: added smaller and debug helpers. (#8381, #8831, #8567, #8191, #7435) 2025-10-31 19:10:23 +01:00
BrutPitt
d0e3b1d4e2 Backends: WebGPU: added ImGui_ImplWGPU_CreateWGPUSurfaceHelper(). (#8381, #8831, #8567, #8191, #7435) 2025-10-31 19:10:23 +01:00
ocornut
505ff536f9 Textures: fixed an issue preventing multi-contexts from using each others' fonts if context 2 runs after context 1's Render() function. (#9039) 2025-10-31 16:38:27 +01:00
ocornut
db577cd445 Fonts: rename internal fields for consistency. 2025-10-31 16:38:23 +01:00
ocornut
149587b85b Config/build infos emit infos to convey when IM_ASSERT() macro is disabled. 2025-10-30 18:03:36 +01:00
ocornut
670a92723a Move IM_STRINGIFY() to imgui.h 2025-10-30 17:47:06 +01:00
ocornut
130c3e6b75 Backends: Vulkan: tweak comments. (#9041) 2025-10-30 16:04:21 +01:00
ocornut
3c578fa87e InputText: restore truncating, now between UTF-8 codepoint. (#9029)
Amend e612536, 2a194e2.
2025-10-29 18:40:40 +01:00
ocornut
8df962a6ed Debug Tools: fixed DebugTextEncoding() potentially reading out of bounds if provided a trailing truncated UTF-8 sequence. 2025-10-29 17:58:52 +01:00
ocornut
2a194e21a0 InputText: revert truncation behavior from e612536 as it can truncate mid-UTF8. (#9029) 2025-10-29 17:24:23 +01:00
ocornut
9753c741b9 Disabled, ButtonBehavior: fixed a bug when a previously enabled item that got nav focus and then turns disabled could still be activated using keyboard. (#9036)
ButtonBehavior() was relying on lack of nav focus for keyboard handling
2025-10-29 16:43:27 +01:00
ocornut
7c483a0eba Add indentation to ButtonBehavior() - no logic change. 2025-10-29 16:39:37 +01:00
ocornut
0ba9fedf1a Win32: Revert 1.92.4 change of comparing dwPacketNumber. (#8556) 2025-10-29 16:29:47 +01:00
ocornut
2c54b15a5f Update ignore list. 2025-10-29 15:03:55 +01:00
ocornut
2a229c8cb8 Examples: SDL3+OpenGL3: fixed Emscripten makefile + ignore list.
Can't get this to run however.
2025-10-29 14:21:43 +01:00
ocornut
40f9e4e8e2 Windows: store BgClickFlags which allows the equivalent of io.ConfigWindowsMoveFromTitleBarOnly to be overridden on a per window basis. (#899, #3071, #5044, + #3379)
io.ConfigWindowsMoveFromTitleBarOnly now sets initial value for BgClickFlags. Using e.g. ImGui::GetCurrentWindow()->BgClickFlags &= ~ImGuiWindowBgClickFlags_Move; allow per-window override.
This will be extended for supporting scrolling options for #3379.
As a minor side effect: the effect of enabling io.ConfigWindowsMoveFromTitleBarOnly now happens one frame later ('window_modal_bounds_exceeding_work_area" test accidentally broke in some situations because of that)
2025-10-28 19:13:11 +01:00
ocornut
245e12cca7 Internals: tweak UpdateMouseMovingWindowEndFrame(). 2025-10-28 19:06:37 +01:00
ocornut
8019d39545 Shuffle a few internal context fields to reduce padding. 2025-10-28 19:06:36 +01:00
ocornut
a1632c6116 InputText, Demo: amend comments to direct more users to the std::string version.
https://www.youtube.com/watch?v=pLwvNdpTpjs wasted a solid hour before finding this.
Crazy that people are using AI instead of actually _reading_ comments, demo and headers. (The information appeared multiple times on their screen)
2025-10-24 17:10:57 +02:00
ocornut
c72d0b2cbb Backends: Vulkan: SwapChainImageUsage assume VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT which is added automatically. (#8946, #8110, #8111, #8686)
Merge bad3c14 which was accidentally only pushed to docking. No important side effect.
2025-10-23 21:04:48 +02:00
ocornut
e6125361f9 InputText: paste does a truncate when not fitting instead of ignoring it. (#9029) 2025-10-23 20:53:29 +02:00
ocornut
b7e45b3a48 InputText: rework STB_TEXTEDIT_INSERTCHARS() signature to allow partial insertion (unused). (#9029)
To be submitted as a PR to nothings/stb.
2025-10-23 20:19:16 +02:00
ocornut
6add99f8d2 Examples: SDL3+Vulkan: Fixed call to ImGui_ImplVulkanH_CreateOrResizeWindow() during resize. (#9030)
Surprisingly it still worked because ImGui_ImplVulkanH_CreateWindowSwapChain() pulls from `cap.currentExtent` when available.
2025-10-23 20:00:57 +02:00
ocornut
750c5d2a61 InputText: do not require anymore that CursorPos be clamped by user code. (#9029)
Add clamping outside of callback code + simplify logic. The previous logic checking for difference was because old code e.g. 21d03edcb0 required a ImTextCountCharsFromUtf8() which is not required since #7925.
2025-10-23 18:54:32 +02:00
ocornut
e571ccf3f4 InputText: removed unnecessary variables. 2025-10-23 18:43:20 +02:00
ocornut
b8573a7e33 Groups: fixed an issue reporting IsItemEdited() signal after EndGroup() for some widgets e.g. Checkbox(), Selectable(). (#9028) 2025-10-23 13:54:14 +02:00
ocornut
bc5da9b367 Examples: DirectX10: Amends. (#8979) 2025-10-22 13:58:51 +02:00
ocornut
b3dab0a406 Examples: DirectX10, DirectX11, DirectX12: comments about fullscreen mode and swapchain setup. (#8979) 2025-10-22 13:57:27 +02:00
ocornut
2a022d997b Examples: GLFW+WebGPU: removed unnecessary ImGui_ImplWGPU_InvalidateDeviceObjects() call during surface resize. (#8381)
+ Relayout changelog.
2025-10-22 13:42:23 +02:00
ocornut
5870b979a8 Examples: GLFW+WebGPU: fixed cmakefile for example to use legacy path. (#8381)
Amend 71447b94f
2025-10-22 13:39:00 +02:00
ocornut
bdb8243602 Backends: SDl3: Fixed Platform_OpenInShellFn() return value. (#9027) 2025-10-22 13:33:36 +02:00
ocornut
b46f099a3f Backends: GLFW: fixed building on Linux platforms where Wayland headers are not available. (#9024, #8969, #8921, #8920) 2025-10-20 23:57:09 +02:00
ocornut
63bfad401f MultiSelect: added ImGuiMultiSelectFlags_NoSelectOnRightClick. (#8200, #9015) 2025-10-20 18:58:45 +02:00
Ingmar Rieger
e11b7a0414 Make ClearPlatformHandlers and ClearRendererHandlers API public (#9016) 2025-10-18 17:34:40 +02:00
mwlasiuk
065f9e0269 Backends: Vulkan: added IMGUI_IMPL_VULKAN_VOLK_FILENAME. (#9008, #7722, #6582, #4854) 2025-10-16 20:36:30 +02:00
ocornut
4b1f5aba80 Examples: GLFW+WebGPU: moving blocks to simplify upcoming diff. (#8381) 2025-10-16 19:42:28 +02:00
ocornut
71447b94fb Examples: GLFW+WebGPU: default build to legacy for now. (#8381) 2025-10-16 18:23:02 +02:00
BrutPitt
3dc511c71d Backends: WebGPU: update to compile with Dawn and Emscripten's 4.0.10+ '--use-port=emdawnwebgpu' ports. (#8381, #8898) 2025-10-16 18:16:28 +02:00
ocornut
36de604a5b InputText: avoid continuously overwriting ownership of ImGuiKey_Enter / ImGuiKey_KeypadEnter in order to allow e.g. external Shortcut to override behavior. (#9004) 2025-10-16 16:12:40 +02:00
ocornut
2a5e9a15e4 InputTextMultiline: fixed a crash when using ImGuiInputTextFlags_WordWrap and resizing the parent window while keeping the multi-line field active. (#9007, #3237) 2025-10-15 19:12:40 +02:00
ocornut
d7fec5e1d3 Tables: fixed a bug where nesting BeginTable()->Begin()->BeginTable(). (#9005) 2025-10-15 16:50:11 +02:00
ocornut
7d8d587bc0 Version 1.92.5 WIP 2025-10-15 16:46:18 +02:00
ocornut
9a5d5c45f5 Version 1.92.4 2025-10-14 19:26:56 +02:00
ocornut
25e5baf5f0 (Breaking) Clipper: commented out legacy IncludeRangeByIndices name obsoleted in 1.89.9. (#6424, #3841) 2025-10-14 19:00:50 +02:00
ocornut
c8db91b7b4 (Breaking) TreeNode, Selectable: commented out legacy ImGuiTreeNodeFlags_AllowItemOverlap, ImGuiSelectableFlags_AllowItemOverlap names obsoleted in 1.89.7.
Amend 51f564e
2025-10-14 19:00:49 +02:00
ocornut
702cc9993a Relaxed internal assert in MarkItemEdited() some more. (#8997)
Amend e7a734f78d, 5a2b1e8482
2025-10-14 16:31:38 +02:00
ocornut
bad5ee167b Shortcuts: added support for combining ImGuiInputFlags_RouteFocused with ImGuiInputFlags_RouteOverActive,. (#9004) 2025-10-13 15:06:34 +02:00
ocornut
b6e277980f Shortcuts: reorganize route scoring so values are easier to read. (#9004)
Score now require 16-bits but ImGuiKeyRoutingData doesn't grow size.
2025-10-13 15:06:32 +02:00
ocornut
878c863af4 Docs: reformat changlog entries. 2025-10-13 13:25:02 +02:00
Rémy Tassoux
9be4f150ef Backends: DirectX12: Reuse texture upload buffer and grow it only when necessary. (#9002) 2025-10-13 13:19:37 +02:00
ocornut
00251c8921 CI: disable PVS-Studio's --disableLicenseExpirationCheck 2025-10-13 12:01:10 +02:00
ocornut
5af650fc6d Examples: GLFW+WGPU: various tweaks to reduce diff with #8381 2025-10-09 19:24:17 +02:00
ocornut
2b770a029b InputText: fixed an infinite loop error happening if a custom input text callback modifies/clear BufTextLen before calling InsertChars(). (#8994, #3237)
+ misc comments.
2025-10-08 19:06:12 +02:00
ocornut
bee2720faa Docs: clarify meaning/purpose of IMGUI_ENABLE_FREETYPE. (#8993) 2025-10-08 18:44:07 +02:00
ocornut
fd0873c61f Test Engine: fixed mismatched macro signature when disabled.
The macro was actually unused in our code if IMGUI_ENABLE_TEST_ENGINE is not defined, but can affect third-party code.
2025-10-07 15:59:45 +02:00
ocornut
ee3d16f150 Demo: fixed layout issue in "Layout & Scrolling -> Scrolling" section. 2025-10-06 18:39:10 +02:00
ocornut
4b858cf5d1 Made tooltip windows inherit parent. (#8982, #1345)
Intent here was for a manually focused tooltip to not steal title bar highlight.
2025-10-06 17:06:40 +02:00
ocornut
09e15e8c9d Nav: fixed typo. 2025-10-06 13:56:34 +02:00
ocornut
2128e2f44b Style: added ImGuiCol_UnsavedMarker. (#8983) 2025-10-06 12:16:48 +02:00
ocornut
27a9374ef3 Drag and Drop: added BeginDragDropTargetViewport(), still in imgui_internal.h for now. (#5204) 2025-10-03 19:06:23 +02:00
ocornut
1cdec11e24 Drag and Drop: rework RenderDragDropTargetRect() into RenderDragDropTargetRectForItem() and add RenderDragDropTargetRectEx(). (#1603, #5204) 2025-10-03 18:54:15 +02:00
ocornut
3ac624b795 Update FAQ.md typos. (#8862) 2025-10-03 18:26:06 +02:00
omar
a97b0c32ab Update FAQ.md 2025-10-02 20:31:14 +02:00
ocornut
bcf722e637 Docs: updated FAQ "What is the difference between Dear ImGui and traditional UI toolkits?". (#8862) 2025-10-02 20:14:43 +02:00
ocornut
8c22b8aef6 Textures: allowed backend to destroy texture while inside the NewFrame/EndFrame scope. (#8811) 2025-10-01 18:39:40 +02:00
ocornut
fc4105c8a8 Backends: DX9,DX10,DX11,DX12,Metal,Vulkan,WGPU,SDLRenderer2,SDLRenderer3: ensure that a texture in _WantDestroy state always turn to _Destroyed. (#8977)
Amend 9809b0b. Strictly speaking this is not necessary anymore but it seems generally sane to promote this.
2025-10-01 17:49:22 +02:00
ocornut
ea564a6a5e Textures: fixed a crash if a texture marked as _WantDestroy by a backend after it had already been destroyed. (#8977, #8811) 2025-10-01 17:40:20 +02:00
ocornut
9809b0b061 Textures: Fixed not updating ImTextureData's RefCount when destroying a context using a shared ImFontAtlas. (#8975) 2025-10-01 14:59:53 +02:00
ocornut
b987970870 Textures: fixed an issue preventing multi-contexts sharing a ImFontAtlas from being possible to destroy in any order. 2025-10-01 14:59:40 +02:00
omar
a3d6e82dbd Update README.md 2025-09-30 16:26:27 +02:00
ocornut
3dafd9e898 Backends: DirectX12: enable swapchain tearing if available. (#8965) 2025-09-29 18:36:13 +02:00
ocornut
5cd83e689e Backends: DirectX12: amend changelog to clarify fixes. (#3463, #5018) 2025-09-29 16:34:27 +02:00
Rémy Tassoux
5ce903af6e Backends: DX12: Use one fence instead of one by viewport. (master) (#8961) 2025-09-29 16:15:46 +02:00
Rémy Tassoux
bab3ebec14 Backends: DX12: Rework synchronization logic. (master) (#8961) 2025-09-29 16:14:53 +02:00
ocornut
3ff195f702 Backends: DX12: let bd->FrameIndex start at 0 to match docking. (#8961) 2025-09-29 16:12:33 +02:00
ocornut
e459e5bf0a Backends: GLFW: fixed build on platform that are neither Windows, macOS or known Unixes. (#8969, #8920, #8921)
Fix 10d0162.

x
2025-09-29 16:12:33 +02:00
Rémy Tassoux
217bc445ff Backends: DirectX12: reuse a command list and allocator for texture uploads. (#8963, #8465) 2025-09-29 15:45:17 +02:00
ocornut
1c87024840 InputText: fixed single-line InputText() not applying fine character clipping properly (regression in 1.92.3). (#8967) 2025-09-29 13:38:27 +02:00
ocornut
3470e6112b (Breaking) Backends: Vulkan: moved fields in ImGui_ImplVulkan_InitInfo: RenderPass, Subpass, MSAASamples, PipelineRenderingCreateInfo. (#8946, #8110, #8111, #8686) 2025-09-26 18:23:51 +02:00
ocornut
e312b99296 (Breaking) Backends: Vulkan: renamed ImGui_ImplVulkan_MainPipelineCreateInfo to ImGui_ImplVulkan_PipelineInfo. (#8110, #8111) 2025-09-26 18:18:33 +02:00
ocornut
cc0a6690bf Backends: Vulkan: minor internal renames/tweaks to reduce further patches. (#8946, #8110, #8111, #8686) 2025-09-26 18:12:47 +02:00
ocornut
5fe962216a (Breaking) Backends: Vulkan: added 'VkImageUsageFlags image_usage' parameter to ImGui_ImplVulkanH_CreateOrResizeWindow(). (#8946, #8110, #8111, #8686)
Default to VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT.
2025-09-26 18:12:47 +02:00
johan0A
01686c6294 Backends: Vulkan: added a way to specify custom vertex/fragment shaders. (#8585, #8271) 2025-09-26 15:44:02 +02:00
ocornut
bf2e0b2c6f Tables: change ImGuiTableFlags_NoBordersInBody behavior to not draw border in body even when resizing. (#8893) 2025-09-25 19:07:59 +02:00
ocornut
cee40f8af9 Examples: made examples's main.cpp consistent with returning 1 on error. 2025-09-24 17:48:48 +02:00
ocornut
940627d008 Backends: SDL2: Fixed build for Emscripten and SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE=0 platforms.
Amend e06b5df.
2025-09-24 15:29:00 +02:00
ocornut
719ea9c228 Comments 2025-09-24 15:00:24 +02:00
ocornut
f61a7ef222 Backends: SDL2,SDL3: avoid using the SDL_GetGlobalMouseState() path when one of our window is hovered. Fix mouse coordinate issue in fullscreen apps with macOS notch + better X11 perfs. (#7919, #7786) 2025-09-24 14:48:33 +02:00
ocornut
e06b5dfe12 Backends: SDL2,SDL3: Shallow tweaks.
Toward fallback focused mouse handler to be a closer match docking version.
2025-09-24 14:41:10 +02:00
ocornut
e1aea42e45 Windows: add resize grips for child windows with both ResizeX+ResizeY. Amends. (#8501) 2025-09-23 16:55:37 +02:00
Aleksi Juvani
82e9a5e47d Windows: add resize grips for child windows with both ResizeX+ResizeY. (#8501) 2025-09-23 16:48:45 +02:00
ocornut
5f6eaa5278 Backends: Win32: minor optimization not submitting gamepad input if packet number has not changed. (#8556)
To be honest I don't believe this is valuable as an optimization, but it makes debug stepping a little nicer.
2025-09-23 16:30:07 +02:00
ocornut
d701ffb478 Examples: added SDL3+DirectX11 example. Minor amends + fix both SDL2/SDL3+DirectX11 to allow WARP driver. (#8956, #8957) 2025-09-22 21:38:33 +02:00
Tomas Jakobsson
a00e517a81 Examples: added SDL3+DirectX11 example. (#8956, #8957) 2025-09-22 21:25:56 +02:00
Brenton Bostick
8868ad67e4 Fixed typos. (#8955) 2025-09-22 16:09:44 +02:00
ocornut
301e652376 Backends: OpenGL3: fixed GL loader to work on Haiku OS which does not support. (#8952) 2025-09-22 16:04:59 +02:00
ocornut
dc0198a7e4 CI: update Windows Vulkan scripts. Amends. (#8925) 2025-09-22 12:45:18 +02:00
yaz0r
ef6fe2ecee CI: update Windows Vulkan scripts. (#8925) 2025-09-22 12:34:23 +02:00
ocornut
46e6382b69 Added type formatters for the LLDB debuggers (e.g. Xcode, Android Studio) (#8950) 2025-09-22 12:26:53 +02:00
David Mentler
087fbf08f6 Added type formatters for the LLDB debuggers (e.g. Xcode) (#8950) 2025-09-22 12:25:17 +02:00
ocornut
d4f722d5b2 IO: added ImGuiPlatformIO::ClearPlatformHandlers(), ClearRendererHandlers(). Backends: call those on Shutdown(). (#8945, #2769) 2025-09-18 16:58:50 +02:00
ocornut
0e7cd694eb Version 1.92.4 WIP 2025-09-18 15:38:46 +02:00
ocornut
bf75bfec48 Amend f6890ed mostly to please static analyzers. 2025-09-17 19:05:22 +02:00
ocornut
1c544ee941 Version 1.92.3 2025-09-17 18:37:56 +02:00
ocornut
70a43f3088 Fixed build with IMGUI_ENABLE_TEST_ENGINE. 2025-09-17 18:12:32 +02:00
ocornut
9cf9d2be83 Debug Tools: ID Stack Tool: fixed a crash when using PushOverrideID(0) during a query. (#8937, #4631) 2025-09-17 18:06:45 +02:00
ocornut
7e473d38d3 Debug Tools: ID Stack Tool: internal renaming (should be no-op). 2025-09-17 18:06:45 +02:00
ocornut
6d834d325e Debug Tools: ID Stack Tool: fixed misleading/unnecessary run of UpdateDebugToolStackQueries() on first frame. (#4631)
`if (g.FrameCount != tool->LastActiveFrame + 1)` test failing on first frame.
Was not harmful but probably confusing in a debugger.
2025-09-17 18:06:45 +02:00
ocornut
f6890ed007 Nav, Inputs: fixed a crash that could occur when opening a popup following the processing of a global shortcut while no windows were focused.
Regression test: "window_popup_from_shortcut"
2025-09-17 16:41:40 +02:00
ocornut
431f2c5abd InputText: fixed dubious code handling ImGuiInputTextFlags_EscapeClearsAll.
Specifically the missing = 0. Somehow only now got reported by Emscripten CI.
2025-09-15 19:32:24 +02:00
ocornut
6274ca4266 Backends: GLFW: fixed build for Emscripten which doesn't expose glfw3native.h.
Amend 10d0162
2025-09-15 19:28:01 +02:00
ocornut
d92c8c6aff Backends: SDL2: Content Scales are always reported as 1.0 on Wayland. (#8921)
SDL_GetDisplayDPI() seems generally broken on X11/Wayland, but our logs shows that on Wayland we get both a content scale from SDL_GetDisplayDPI() and a framebuffer scale.
2025-09-15 19:20:56 +02:00
ocornut
72c00f39c1 Backends: GLFW: fix ImGui_ImplGlfw_IsWayland() amend broken 10d0162. (#8921, #8920)
Accidentally broke this while shuffling code...
2025-09-15 19:16:05 +02:00
ocornut
2675b7ca26 Backends: GLFW: Content Scales always reported as 1.0 on Wayland, FramebufferScale always reported as 1.0 on X11. (#8920, #8921) 2025-09-15 18:55:09 +02:00
ocornut
10d0162378 Backends: GLFW: added ImGui_ImplGlfw_IsWayland(). (#8921, #8920)
(technically presently untested but we've researched this)
2025-09-15 18:40:22 +02:00
ocornut
3c6c5692b8 Examples: Win32+Vulkan, GLFW+Metal: Fixed not applying content scale. (#8921, #8756)
Somehow it breaks in Win32+OpenGL3 example: when enabled Win32 applies some extra scale.
2025-09-15 16:50:58 +02:00
ocornut
e044d99710 Examples: standardized all examples to have a base window size of 1280x800. 2025-09-15 16:34:36 +02:00
ocornut
22a6a83c54 Backends: SDL3: use SDL_GetWindowDisplayScale() on Mac to output DisplayFrameBufferScale. The function is more reliable during resolution changes e.g. going fullscreen. (#8703, #4414) 2025-09-15 15:16:42 +02:00
ocornut
cd476b27f8 Examples: GLFW+Vulkan: Fixed not applying content scale. (#8921, #8756) 2025-09-12 21:32:46 +02:00
ocornut
9f13684d70 Examples: GLFW+OpenGL2: Fixed not applying content scale. (#8921)
Note that this requires GLFW 3.3.
2025-09-12 20:57:04 +02:00
ocornut
6d25cb844b CI: switch iOS build to macos-14 runner as macos-latest currently fails. 2025-09-12 16:41:05 +02:00
ocornut
36133d8ac4 InputText: Word-Wrap: hide vertical scrollbar but takes its width into account. (#3237, #952, #1062, #7363)
Also increase IMGUI_VERSION_NUM for good measure, forgot to increase it when moving to public api.
2025-09-12 16:03:18 +02:00
ocornut
b6a33f8ce1 InputText: Word-Wrap: amend 7f1e2bb to avoid triggering static analyzer. (#3237, #952, #1062, #7363)
And generally more logical this way anyhow.
2025-09-12 15:05:23 +02:00
ocornut
78c1d4a92c InputText: Word-Wrap: moving ImGuiInputTextFlags_WordWrap to public API. Added in demo. (#3237, #952, #1062, #7363) 2025-09-12 15:03:33 +02:00
ocornut
7f1e2bb8dd InputText: Word-Wrap: avoid word-wrap specific path InputTextLineIndexGetPosOffset() when word-wrap is disabled. (#3237, #952, #1062, #7363) 2025-09-12 15:03:33 +02:00
ocornut
2f3e85bc37 Comments 2025-09-12 15:03:33 +02:00
ocornut
8a94422246 InputText: optimize inactive path by avoiding an early ImStrlen(). 2025-09-11 21:26:10 +02:00
ocornut
ae832ce532 InputText: moved blocks so same text rendering code is now used for active and inactive states.
(ignore whitespace to visualize this change easily)
2025-09-11 21:26:04 +02:00
ocornut
1e52e7b90c InputText: Added a line index. Refactored cursor and selection rendering, now simpler, easier to reason about, and faster. (#3237, #952, #1062, #7363) 2025-09-11 21:26:01 +02:00
ocornut
67085d732a ImGuiTextIndex: rename member. 2025-09-11 21:25:56 +02:00
ocornut
f36c65661c InputText: fixed pressing End (without Shift) in a multi-line selection from mistakenly moving cursor based on selection start. 2025-09-11 18:45:07 +02:00
ocornut
e2b7d84e96 CI: disable pvs-studio 28 days warning (amend). 2025-09-11 15:15:48 +02:00
ocornut
271f476d08 CI: disable pvs-studio 28 days warning. 2025-09-11 15:12:51 +02:00
ocornut
e2f314d613 InputText: fixed misassignment to unused Scroll.y variable when using ImGuiInputTextFlags_NoHorizontalScroll.
Amend d474ed7f7 (#7913, #383)
2025-09-11 15:06:25 +02:00
ocornut
8eb22ea620 Demo: ShowStyleSelector(), ShowFontSelector(): remove ImGuiSelectableFlags_NoAutoClosePopups for now.
In this situation we kinda want keyboard Enter to select and close but ideally not click. We don't have separate options yet.
2025-09-10 22:42:12 +02:00
ocornut
55f590c1d1 Selectable: ImGuiSelectableFlags_SelectOnNav doesn't select when holding Ctrl, to be consistent with multi-select.
Amend e66afbb + remove needless line in CloseCurrentPopup() block
2025-09-10 22:29:42 +02:00
Harry Mander
5e5658e68f Debug Tools: fixed assertion failure when opening a combo box while using io.ConfigDebugBeginReturnValueOnce/ConfigDebugBeginReturnValueLoop. (#8931) 2025-09-10 19:12:03 +02:00
ocornut
013c4ed476 InputText: fixed gross buffer underflow introduced by a82f66a. (#3237, #952, #1062, #7363)
Would typically not crash by detected by sanitinizers.
2025-09-10 19:00:05 +02:00
ocornut
2f1d1c8b2f Focus, InputText: fixed an issue where SetKeyboardFocusHere() did not work on InputTextMultiline() with ImGuiInputTextFlags_AllowTabInput. (#8928) 2025-09-10 18:31:34 +02:00
ocornut
1cd08b883c TabBar: fixed calling TabBarQueueFocus() before submitting tabs. (#8929, #6681) 2025-09-10 18:03:34 +02:00
ocornut
4e98fb20e2 TabBar: Internals: added TabBarFindByID(), TabBarRemove() helpers.
Currently only for the benefit of TestEngine.
2025-09-10 17:59:26 +02:00
ocornut
045645e5f1 Demo: tweaked ShowFontSelector() and ShowStyleSelector() to update selection while navigating and to not close popup automatically. 2025-09-09 17:50:40 +02:00
ocornut
8e4955bb23 Selectable: moved ImGuiSelectableFlags_SelectOnNav to public API. 2025-09-09 17:42:14 +02:00
ocornut
e66afbbbe0 Selectable: ImGuiSelectableFlags_SelectOnNav doesn't close popups. 2025-09-09 17:33:03 +02:00
ocornut
2841c5135d Backends: OpenGL3: add GL_NEAREST and samplers functions in loader. 2025-09-08 17:24:39 +02:00
ocornut
bf52f4a83c Backends: OpenGL3: added HasBindSampler storage for readability and consistency. 2025-09-08 17:23:48 +02:00
ocornut
14e076c5bb Backends: Internal renaming of samplers. 2025-09-08 16:02:23 +02:00
ocornut
ea8a5a9e17 DrawList: made AddCallback() assert when passing a null callback. 2025-09-08 15:20:18 +02:00
ocornut
230418a75d InputText: Word-Wrap: attempt to track cursor while resizing frame/parent. (#3237, #952, #1062, #7363) 2025-09-08 11:56:22 +02:00
ocornut
16415aa39f InputText: Word-Wrap: added custom implementation for Home/End that is word-wrap friendly. (#3237, #952, #1062, #7363) 2025-09-08 11:56:22 +02:00
ocornut
985723ed94 InputText: Word-Wrap: mouse clicks on word-wrapping points set cursor side correctly. (#3237, #952, #1062, #7363) 2025-09-08 11:56:22 +02:00
ocornut
a82f66a9b0 InputText: Word-Wrap: added ImGuiInputTextFlags_WordWrap support. (#3237, #952, #1062, #7363) 2025-09-08 11:56:20 +02:00
ocornut
e422a38e4c InputText: internals: expose LineCount, GetPreferredOffsetX(). 2025-09-08 11:54:34 +02:00
ocornut
11fff1ccf5 ImFont::RenderText() takes ImDrawTextFlags_CpuFineClip instead of bool cpu_fine_clip + forward ImDrawTextFlags to word-wrap code.
(for #3237, #952, #1062, #7363)
2025-09-08 11:54:33 +02:00
ocornut
3cc7d1c81a InputText: InputTextCalcTextSize() uses ImFontCalcTextSizeEx().
(for #3237, #952, #1062, #7363)
2025-09-08 11:54:33 +02:00
ocornut
56189cd814 Internals: added ImDrawTextFlags_StopOnNewLine support to ImFontCalcTextSizeEx(), ImDrawTextFlags_WrapKeepTrailingBlanks to ImTextCalcWordWrapNextLineStart().
(for #3237, #952, #1062, #7363)
2025-09-08 11:54:33 +02:00
ocornut
a9945899c6 stb_textedit: extracted stb_textedit_move_line_start()/stb_textedit_move_line_end(), adding STB_TEXTEDIT_MOVELINESTART,STB_TEXTEDIT_MOVELINEEND support. (#3237, #952, #1062, #7363) 2025-09-08 11:54:33 +02:00
ocornut
bc6478f651 Internals: added ImDrawTextFlags_WrapKeepTrailingBlanks required for text-edit style word-wrapping.
(for #3237, #952, #1062, #7363)
2025-09-08 11:54:33 +02:00
ocornut
34ab6c8a89 Internals: extracted ImFont::CalcTextSizeA() into ImFontCalcTextSizeEx() so we can make change to its signature.
(for #3237, #952, #1062, #7363)
2025-09-08 11:54:33 +02:00
ocornut
c63b5bd8fb Internals: extracted ImFont::CalcWordWrapPosition() into ImFontCalcWordWrapPositionEx() so we can make change to its signature.
(for #3237, #952, #1062, #7363)
2025-09-08 11:54:33 +02:00
ocornut
8a35ce0e98 CalcWordWrapPosition() breaks on \n instead of relying on caller to do it + expose ImTextCalcWordWrapNextLineStart(). (#3237, #952, #1062, #7363)
Should be functional no-op, fingers crossed. Breaking on \n allows caller to count lines reliably.
2025-09-08 11:54:32 +02:00
yaz0r
f77f68a5ed CI: Windows: update to 1.4.326 + pull Vulkan from KhronosGroup's Vulkan-Headers and Vulkan-Loader. (#8925, #8778) 2025-09-08 11:42:28 +02:00
fgungor
bed08daede Backends: SDLGPU3: fixed double assignment. (#8924) 2025-09-08 11:32:38 +02:00
fdsa
09ebcf1779 Docs: fixed mismatched parentheses & other small changes. (#8922) 2025-09-08 11:30:14 +02:00
ocornut
02af06ea5f Backends: Vulkan: rewrite pColorAttachmentFormats deep-copy to avoid issues when calling multiple times. (#8282, #8110) 2025-09-04 18:14:28 +02:00
ocornut
026d47cd35 Backends: Vulkan: store pColorAttachmentFormats deep-copy into an ImVector. (#8282, #8110) 2025-09-04 18:05:58 +02:00
ocornut
c63714822f Backends: Vulkan: reorder InitInfo fields. 2025-09-04 18:05:15 +02:00
ocornut
26aa81a8b1 Backends: Vulkan: misc amends (makes ImGui_ImplVulkan_MainPipelineCreateInfo::PipelineRenderingCreateInfo consistent with InitInfo). (#8110, #8111, #8053) 2025-09-04 18:05:15 +02:00
ocornut
1ecc34a0b1 Backends: Vulkan: misc amends (e.g. changelog, coding style). (8110, 8111, 8053)
# Conflicts:
#	backends/imgui_impl_vulkan.cpp
2025-09-04 18:04:20 +02:00
ocornut
ee03cef14f Backends: Vulkan: revert using a struct for ImGui_ImplVulkan_CreatePipeline() for now. (#8110, #8111, #8053) 2025-09-04 18:00:05 +02:00
Ronan Cailleau
e51d93e2f5 Backends: Vulkan: added ImGui_ImplVulkan_CreateMainPipeline(). (#8110, #8111, #8053)
- Added ImGui_ImplVulkan_CreateMainPipeline(...) to explicitly re-create the main window pipeline (when some of its properties are changed).
- Does not implicitly use ImGui_ImplVulkan_InitInfo::PipelineRenderingCreateInfo, but a function parameter.
- The main window pipeline is created only if possible during ImGui_ImplVulkan_Init(...) (if a render pass or rendering info are given), else it should be created with ImGui_ImplVulkan_ReCreateMainPipeline(...)
- ImGui_ImplVulkan_CreatePipeline now takes a struct rather than (too) many parameters (and returns the created pipeline).
2025-09-04 18:00:05 +02:00
ocornut
7d33524042 InputText: fixed an issue where using Escape with ImGuiInputTextFlags_EscapeClearsAll. (#8915, #8273)
Regression test: "widgets_inputtext_temp_buffer_2"
2025-09-04 13:16:05 +02:00
ocornut
605a751571 InputText, InputInt, InputFloat: fixed an issue where using Escape to revert would not write back the reverted value. (#8915, #8273)
Revealed by 00f12b9a0
Regression test: "widgets_inputtext_temp_buffer_2"
2025-09-04 13:16:04 +02:00
ocornut
b7cb3d93a4 Comments about using MSVC SAL for printf annotation. (#8871) 2025-09-03 19:39:55 +02:00
ocornut
20160ff1d5 Fonts: fixed merging a font and specifying a font target in DstFont that's not the last added font (regression in 1.92). (#8912) 2025-09-03 19:36:02 +02:00
ocornut
3766d40394 Nav: fixed Ctrl+Tab window appearing as empty when the sole active and focused window has the ImGuiWindowFlags_NoNavFocus flag. (#8914) 2025-09-03 17:50:10 +02:00
Ян Ли
0dd3c845eb Docs: add missing anchor in FAQ.md (#8913) 2025-09-03 09:17:23 +02:00
ocornut
8dc457fda2 Internals: added indent, shallow tweaks + unused context pointer to InputTextCalcTextLenAndLineCount() to reduce noise in wip patch.
Visualize this commit with white-space changes disabled.
2025-09-02 15:39:22 +02:00
ocornut
0ef9610e70 InputText, stb_textedit: Revert special handling when pressing Down/PageDown on last line of a buffer without a trailing carriage return.
Revert fbf70070bb.
2025-09-02 15:39:14 +02:00
ocornut
5c92699f5f stb_textedit: trim trailing blanks for simplicity.
In theory your editorconfig has this disabled for this file but MSVC plugin doesn't seem to handle this properly.
2025-08-28 18:43:41 +02:00
ocornut
771fae623d ImRect: added AsVec4() helper. Using ImRect in InputTextEx(). 2025-08-27 21:43:25 +02:00
ocornut
6351f00ff1 Clipper, Tables: removed row_increase >= 0 assert. (#8886)
Seeing cases in my own tests that are not obvious so it seems like too much of a burden for the user to assert/crash, as the row count is not always useful anyhow.
2025-08-27 20:31:05 +02:00
ocornut
55cbc66508 InputText: allow passing an empty string with buf_size==0. (#8907) 2025-08-27 20:21:31 +02:00
ocornut
9f969944d5 stb_textedit: fixed misleading cursor-1 in STB_TEXTEDIT_K_LINESTART handlers. (#7925)
`state->cursor - 1` in STB_TEXTEDIT_K_LINESTART handlers was technically misleadingly not UTF-8 compliant but things would naturally work anyhow.
2025-08-27 19:22:48 +02:00
ocornut
aa2f40c3bb Clipper, Tables: added ImGuiListClipperFlags, ImGuiListClipperFlags_NoSetTableRowCounters. (#8886)
a0cdac48e0 revealed the issue but technically the core issue is that clipper assume 1 item = 1 table row.
2025-08-27 18:54:57 +02:00
Christian Fillion
a309d2dcac Fonts: fixed assertion failure when ImFontAtlasRectEntry::Generation overflows. (#8906) 2025-08-27 14:39:08 +02:00
ocornut
87c1ab7988 Windows: changed how g.CurrentItemFlags is modified before windows' CloseButton() submission to be less misleading. (#8903)
I don't think anyone would have `ImGuiItemFlags_NoFocus` set globally but technically it might.
2025-08-26 18:48:08 +02:00
ocornut
319c481abb AddFontDefault(): shallow simplification. 2025-08-26 17:57:51 +02:00
ocornut
229d56e37a Debug Tools: ID Stack Tool: when ### is used, uncontributing prefix before the ### is now skipped. (#8904, #4631) 2025-08-26 16:30:13 +02:00
ocornut
7d230594de Fixed ImHashSkipUncontributingPrefix() not looping in case of multiple ### elements. 2025-08-26 16:29:14 +02:00
ocornut
75a4a48d1f Internals: extracted ImHashSkipUncontributingPrefix() out of CreateNewWindowSettings() and added note about it. 2025-08-26 16:23:06 +02:00
ocornut
9e864012ae Debug Tools: ID Stack Tool: added option to hex-encode non-ASCII characters in output path. (#8904, #4631) 2025-08-26 15:58:59 +02:00
ocornut
783f1e62cc Debug Tools: ID Stack Tool: fixed using fixed-size buffers preventing long identifiers from being displayed in the tool. (#8905, #4631) 2025-08-26 15:36:56 +02:00
ocornut
e728b96600 Fixed Bullet() fixed tesselation amount which looked out of place in very large sizes. 2025-08-20 20:22:31 +02:00
ocornut
fe03035112 Docs: advertise ProggyVector font as an alternative. 2025-08-20 20:02:49 +02:00
ocornut
515c0b526f Backends: SDL_GPU: typo + changelog. (#8892) 2025-08-20 18:53:25 +02:00
PTSVU
7c6fa8f8f7 Backends: SDL_GPU: add swapchain parameters to ImGui_ImplSDLGPU3_InitInfo. (#8892)
(master branch commit, values are not used)
2025-08-20 18:43:04 +02:00
ocornut
42656b3aa1 Scrollbar, Style: added style.ScrollbarPadding, ImGuiStyleVar_ScrollbarPadding. (#8895) 2025-08-20 18:27:35 +02:00
ocornut
89b7fc906a DrawList: fixed CloneOutput() taking a copy of the ImDrawListSharedData pointer. Missing Changelog. (#8894, #1860) 2025-08-20 17:57:06 +02:00
ocornut
0c4f50090a DrawList: fixed CloneOutput() taking a copy of the ImDrawListSharedData pointer. (#8894, #1860)
Amend b82e99c032
2025-08-20 17:49:18 +02:00
ocornut
720e94f3da Rework FormatTextureIDForDebugDisplay() ImDrawCmd version as FormatTextureRefForDebugDisplay(). 2025-08-19 15:32:38 +02:00
ocornut
321e9eb919 Fixes for printing out ImTextureID value when it is typedef to other types. (#8889) 2025-08-19 15:32:12 +02:00
scribam
655601169b Examples: Android+OpenGL3: update Gradle project, amend. (#8888, #8878) 2025-08-19 15:20:53 +02:00
scribam
361e370fe0 Examples: Android+OpenGL3: update Gradle project (#8888, #8878) 2025-08-19 15:16:15 +02:00
ocornut
86ec5c8342 Version 1.92.3 WIP 2025-08-19 15:15:49 +02:00
ocornut
45acd5e0e8 Version 1.92.2b 2025-08-13 17:31:01 +02:00
ocornut
774ddb58bd Fixed IsItemHovered() failing on disabled items and items that have no identifier. Made holding on disabled items not leak IsItemDisabled() between disabled items when window has _NoMove. (#8877, #8883)
See amends to "widgets_status_common", "widgets_disabled_2" tests.
2025-08-13 17:08:04 +02:00
ocornut
4dee11a089 Make ImGuiInputSource int.
(primarily to avoid "result of comparison 'ImGuiInputSource' < 0 is always false" in GetInputSourceName().
2025-08-13 17:02:23 +02:00
omar
43e3ac0dc6 Docs: fixed unneeded usage of Build(). (#8883) 2025-08-13 15:17:53 +02:00
ocornut
02f654cbce Backends: Allegro5: fixed missing support for ImGuiKey_PrintScreen under Windows. 2025-08-12 20:02:08 +02:00
ocornut
e1baadba84 Backends: Allegro5: Fixed texture format setup. (#8770, #8465)
Amend/fix ee8941e.
2025-08-12 15:02:58 +02:00
ocornut
e2a662eed8 Backends: Allegro5: fixed use of obsolete IM_OFFSETOF(). 2025-08-12 11:41:11 +02:00
ocornut
e1a93805db Backends: Allegro5: Added ImGui_ImplAllegro5_SetDisplay(). 2025-08-12 11:33:10 +02:00
ocornut
af920e1e6f Version 1.92.3 WIP 2025-08-12 11:30:41 +02:00
Wouter Vermaelen
863e989c25 imgui_freetype.cpp: fix gcc -Wmissing-declarations (#8879) 2025-08-11 19:39:26 +02:00
ocornut
2b24f5fa71 Version 1.92.2 2025-08-11 16:47:06 +02:00
ocornut
e10300ed3c Docs: Special thanks. 2025-08-11 16:26:10 +02:00
ocornut
5a6fa33b88 Fixed an inconsistency between IsItemHovered() and internal hovering check, where IsItemHovered() would return true if mouse was first clicked on the background of a non-moveable window. (#8877) 2025-08-11 15:41:38 +02:00
ocornut
8239a0e0c4 Nav, Tables: fix NavIsScrollPushableX logic clamping value stored in NavApplyItemToResult(), which would break scrolling. (#8816, #2221)
Amend 47c4148.
2025-08-11 15:17:02 +02:00
ocornut
50115596dc Demo: About Box: include IMGUI_ENABLE_TEST_ENGINE in Config/Build info. 2025-08-11 12:29:13 +02:00
ocornut
1c57dc21c2 Misc: fixes zealous MSVC static analyzer warnings + make GetInputSourceName(), GetMouseSourceName() a little more tolerant. (#8876) 2025-08-11 11:04:13 +02:00
ocornut
47c41483bd Tables, Nav: fixed navigation within scrolling tables when item boundaries goes beyond columns limits. (#8816, #2221)
Amend 00d3f9295e.
2025-08-11 10:49:20 +02:00
Ian
ea075ed973 ImVector: skip memcpy in operator= if Data isn't initialized to play nice with -fsanitize=undefined. (#8874) 2025-08-11 09:53:01 +02:00
ocornut
b6614f6c7c Backends: SDL_GPU3: removed ImGui_ImplSDLGPU3_Texture struct extraneous indirection now that we only need to store SDL_GPUTexture*. (#8866, #8163, #7998, #7988, #8465) 2025-08-08 15:51:17 +02:00
ocornut
9ee3d731b5 Backends: SDL_GPU3: changed ImTextureID type from SDL_GPUTextureSamplerBinding* to SDL_GPUTexture*. Added ImGui_ImplSDLGPU3_RenderState. (#8866, #8163, #7998, #7988) 2025-08-08 15:51:16 +02:00
LEE KYOUNGHEON
e7d0ad092c Removed static inline usages from free functions. (#8867, #8813)
For C++20 module compatibility. See https://github.com/stripe2933/imgui-module/
2025-08-07 17:01:23 +02:00
ocornut
412daf7362 Tabs: attempt to fix infinite loop in tab-bar ShrinkWidth() by using an epsilon. (#5652, #3421, #8800) 2025-08-07 16:41:21 +02:00
ocornut
c22af8c346 Fonts: fixes comment (amend d8da97f7). 2025-08-07 16:19:07 +02:00
ocornut
1bf41a0762 Fonts, Tables: fixed PushFont() having no effect when called after submitting a hidden column. (#8865)
Amend 0e769c5
2025-08-07 16:16:12 +02:00
ocornut
284283615b InputText: minor tweak to an expression.
Primarily to make PVS Studio static analysis go silent but it is a perfectly valid suggestion.
2025-08-06 10:48:01 +09:00
Adem Budak
d163e20f63 Examples: Win32+OpenGL3: Replace legacy 'GL/GL.h' with 'GL/gl.h' (#8861) 2025-08-06 10:43:57 +09:00
Christian Fillion
f7eae45ae9 Fonts: show ImFontConfig::FontNo in DebugNodeFont(). (#8863)
Thanks!
2025-08-06 10:42:34 +09:00
Elliot Prior
ff2dfc8422 Fonts: fixed a crash when modifying different texture format with a legacy backend. (#8824) 2025-08-04 18:39:30 +09:00
ocornut
7e701c18c8 Fonts: fixed an issue when a font using MergeMode has a reference size specified but the target font doesn't. 2025-08-04 18:21:38 +09:00
Michael Böhme
90025a62c7 Backends: Vulkan: Avoid calling vkCmdBindDescriptorSets() when texture has not changed. (#8666) 2025-08-04 18:10:00 +09:00
ocornut
902b8cc39a Examples: SDL3+SDL_GPU: use SDL_GPU_PRESENTMODE_VSYNC present mode. (#8830) 2025-08-04 15:30:25 +09:00
o:tone
70cfc02811 Examples: SDL3+SDL_GPU: use SDL_WaitAndAcquireGPUSwapchainTexture() instead of SDL_AcquireGPUSwapchainTexture(). (#8830) 2025-08-04 15:28:38 +09:00
ocornut
250bd66b76 Tabs: fixed ImGuiTabBarFlags_FittingPolicyScroll not triggering (regression in 3ef6c84). (#3421, #8800) 2025-08-04 15:19:16 +09:00
ocornut
c14d83d4e0 Tabs: made scrolling buttons never keyboard/gamepad navigation candidates. 2025-08-04 15:12:23 +09:00
ocornut
7d5fef8642 Nav: fixed a bug where GamepadMenu couldn't toggle between main and menu layer while navigating a Modal window. (#8834)
Amend 901d432cb but for Gamepad.
2025-08-04 15:06:14 +09:00
Christian Fillion
22fe9fce4c Textures: fixed assertion in DebugNodeTexture() when ImTextureID_Invalid is non-zero. (#8860, #8745)
ImFontAtlas's constructor resets ImTextureRef::_TexID to 0 instead of ImTextureID_Invalid.
Amend bc051dc
2025-08-04 14:10:20 +09:00
ocornut
320c94bfaa Tabs: when scrolling is enabled, track selected tabs when resizing down parent container. (#3421, #8800) 2025-07-31 23:42:30 +09:00
ocornut
3ef6c8410a Tabs: added new fitting policy ImGuiTabBarFlags_FittingPolicyMixed, new default. (#3421, #8800) 2025-07-31 23:42:25 +09:00
ocornut
cc1fbcc9a9 Fonts: undo change done in b884533 since 19d1ad0 made them unnecessary. (#8794, #8850) 2025-07-31 23:04:35 +09:00
ocornut
78d11cd781 Tabs: (Breaking) renamed ImGuiTabBarFlags_FittingPolicyResizeDown to ImGuiTabBarFlags_FittingPolicyShrink. (#261, #351)
Amend 54a60aaa40
2025-07-31 22:58:01 +09:00
ocornut
7278cda039 Tabs: added TabMinWidthBase, ImGuiStyleVar_TabMinWidthBase. 2025-07-31 22:57:11 +09:00
ocornut
7bb9db501c Tabs: fixed 046a8ea (commited a modified file). 2025-07-31 22:05:19 +09:00
ocornut
046a8eae0f Tabs: fixed tab bar underline not drawing below scroll buttons. (#6820, #4859, #5022, #5239)
Fix ef8ff1b5d8 which accidentally meant we are using BarRect after it may have been modified by TabBarScrollingButtons().
2025-07-31 22:04:01 +09:00
ocornut
a0cdac48e0 Tables: fixed TableGetHoveredRow() (#7350, #6588, #6250) + TableGetRowIndex() which never correctly worked when using a clipper.
Amend e09454aec. Can't understand the comment nor why code was commented. Code looks alright. Compared TableEndRow() between 1.80 and current as well.
2025-07-31 13:21:26 +09:00
ocornut
2ab3946ecb Windows: add StopMouseMovingWindow(), partial merge 80d78fa from docking. 2025-07-30 18:46:49 +09:00
ocornut
87d7f7744e Fonts: (Internal) Added undocumented ImFontBaked::LoadNoRenderOnLayout. (#8758, #8465)
Amend fd75bdccb0.
2025-07-27 20:33:57 +09:00
ocornut
10dc1882c8 Fonts: (Internal) rename ImFontBaked::LockLoadingFallback to ImFontBaked::LoadNoFallback. 2025-07-27 20:31:37 +09:00
ocornut
c6c0c3be08 Docs: amend 1.92.0 logs on the fact that font->CalcTextSizeA() used to be thread-safe. 2025-07-27 20:15:21 +09:00
ocornut
da6c97203e Fixed comments for io.KeyCtrl / io.KeySuper to match the one for ImGuiMod_Ctrl, ImGuiMod_Super. (#8839) 2025-07-27 19:37:30 +09:00
Miolith
853a46e021 Backends: Vulkan: fixed texture update corruption introduced in 1.92.0. (#8801, #8755, #8840, #8465)
Fix abe294bfd0
2025-07-27 19:33:30 +09:00
Ori Avtalion
075ad676aa Demo: Fix '= =' typo in text (#8836) 2025-07-25 17:36:23 +09:00
ocornut
19d1ad04f4 Fonts: stop using stb_truetype.h implementation functions. Fix using IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION. (#8794) 2025-07-23 16:42:00 +09:00
ocornut
b884533957 Document/workaround an issue using IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION since 1.92.0. (#8794) 2025-07-23 16:30:30 +09:00
ocornut
174f37bdaf Fixed building with IMGUI_DISABLE_DEBUG_TOOLS only. (#8796) 2025-07-23 16:17:35 +09:00
ocornut
4f00774006 Examples: SDL3+Metal: Amend example. (#8827, #8825)
Amend 8403c49
2025-07-23 16:11:47 +09:00
Shi Yan
8403c49484 Examples: SDL3+Metal: Added example. (#8827, #8825) 2025-07-23 15:58:13 +09:00
ocornut
06ab541e2f CI: Adjust policies to more frequently build Win64 SDL3+SDL_Renderer, SDL3+SDL_GPU, and tweak others. 2025-07-22 17:01:26 +09:00
scribam
7babc24ad4 CI: Add SDL3 builds to MacOS and Windows. (#8819, #8778) 2025-07-22 16:52:20 +09:00
scribam
c96e9c8273 CI: Update Windows CI to use a more recent SDL2. (#8819, #8778) 2025-07-22 16:51:20 +09:00
Tim-Rex
4a51295c9e Backends: OpenGL3: add and call embedded loader shutdown in ImGui_ImplOpenGL3_Shutdown(). (#8792)
Include update of imgui_impl_opengl3_loader.h as submitted to gl3w_stripped repository, which adds imgl3wShutdown().
2025-07-22 16:46:35 +09:00
gomkyung2
9c392896b7 Misc: removed more redundant inline static linkage from imgui_internal.h. (#8813, #8682, #8358) 2025-07-22 16:31:10 +09:00
ocornut
ea613e181c Windows: fixed an issue where resizable child windows would emit border logic when hidden/non-visible. (#8815)
This makes more sense in docking branch but may be merged in master right away.
2025-07-22 16:22:53 +09:00
ocornut
ed5bd1f9ef Changed ImTextCharToUtf8() to return bytes count rather than original pointer. (#8820)
Amend c2bf4abfa1
2025-07-22 14:17:11 +09:00
Rhys Pounder
3401dbde92 Docs: Fixed typo. (#8817) 2025-07-21 15:42:16 +09:00
ocornut
c9e0208de4 Textures: moved UpdateTexturesNewFrame(), UpdateTexturesEndFrame() to a more suitable location in the file. 2025-07-21 15:35:53 +09:00
ocornut
57a816ae60 Texutres: minor comments, tweaks. 2025-07-21 15:27:17 +09:00
ocornut
643f0e3abf Backends: OpenGL3: restore update path on non-WebGL non-ES targets that doesn't require a CPU copy. (#8802, #8465)
Amend/fix dbb91a5
2025-07-15 14:34:40 +02:00
ocornut
8744d10235 Backends: OpenGL2, OpenGL3: set GL_UNPACK_ALIGNMENT to 1 before updating textures. (#8802) 2025-07-15 14:30:50 +02:00
ocornut
336d9212fc Backends: using range-for to iterate draw_data->CmdLists[]. 2025-07-11 17:41:52 +02:00
ocornut
79d88e2d0b Error Handling, Tables: TableGetSortSpecs() silently return NULL when no table (matching most other table getters). TableSetBgColor() uses IM_ASSERT_USER_ERROR. 2025-07-11 16:57:43 +02:00
ocornut
a0d3e405a3 Textures: ImTextureData::Create() sets status. RegisterUserTexture() increases RefCount. Added comments about ImTextureData::GetTexRef(). (#8789) 2025-07-11 16:49:28 +02:00
ocornut
0e6e876f23 Docs: update docs/comments about ImTextureRef, ImTextureID. (#8783) 2025-07-10 19:07:28 +02:00
ocornut
c680f54e6c FIxed IsWindowFocused() using wrong flag types (harmless as values were identical). (#8786) 2025-07-10 18:42:39 +02:00
ocornut
4d745bc602 Version 1.92.2 WIP 2025-07-10 18:41:05 +02:00
128 changed files with 10891 additions and 3610 deletions

View File

@@ -2,7 +2,9 @@
1. PLEASE CAREFULLY READ: [Contributing Guidelines](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md)
2. Make sure you're using a special branch just for this pull request. (Sometimes people unknowingly use a default branch, then later update that branch, which updates the pull request with the other changes if it hasn't been merged yet.)
2. **Make sure you're using a special branch just for this pull request**. (In git, 1 PR = 1 branch. If you update the branch the PR will be updated.)
3. Clear this template before submitting your PR.
3. Consider running the [imgui_test_suite](https://github.com/ocornut/imgui_test_engine) or adding new tests to test for expected behaviors.
4. Clear this template before submitting your PR.

View File

@@ -16,24 +16,38 @@ on:
- requested
jobs:
Windows:
Build-Windows:
runs-on: windows-2025
name: Build - Windows
defaults:
run:
working-directory: ${{ github.workspace }}/imgui
env:
VS_PATH: C:\Program Files\Microsoft Visual Studio\2022\Enterprise\
MSBUILD_PATH: C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
path: ${{ github.workspace }}/imgui
# The VulkanSDK libs for Windows is manually generated using build_windows_vulkan_libs.ps1 + attached to issue #8925.
# (we have a .yml workflow in commit history if it becomes ever useful to create this on CI too)
- name: Install Dependencies
shell: powershell
run: |
Invoke-WebRequest -Uri "https://www.libsdl.org/release/SDL2-devel-2.26.3-VC.zip" -OutFile "SDL2-devel-2.26.3-VC.zip"
Expand-Archive -Path SDL2-devel-2.26.3-VC.zip
echo "SDL2_DIR=$(pwd)\SDL2-devel-2.26.3-VC\SDL2-2.26.3\" >>${env:GITHUB_ENV}
Invoke-WebRequest -Uri "https://www.libsdl.org/release/SDL2-devel-2.32.8-VC.zip" -OutFile "SDL2-devel-2.32.8-VC.zip"
Expand-Archive -Path SDL2-devel-2.32.8-VC.zip
echo "SDL2_DIR=$(pwd)\SDL2-devel-2.32.8-VC\SDL2-2.32.8\" >>${env:GITHUB_ENV}
Invoke-WebRequest -Uri "https://github.com/ocornut/imgui/files/3789205/vulkan-sdk-1.1.121.2.zip" -OutFile vulkan-sdk-1.1.121.2.zip
Expand-Archive -Path vulkan-sdk-1.1.121.2.zip
echo "VULKAN_SDK=$(pwd)\vulkan-sdk-1.1.121.2\" >>${env:GITHUB_ENV}
Invoke-WebRequest -Uri "https://www.libsdl.org/release/SDL3-devel-3.2.18-VC.zip" -OutFile "SDL3-devel-3.2.18-VC.zip"
Expand-Archive -Path SDL3-devel-3.2.18-VC.zip
echo "SDL3_DIR=$(pwd)\SDL3-devel-3.2.18-VC\SDL3-3.2.18\" >>${env:GITHUB_ENV}
Invoke-WebRequest -Uri "https://github.com/user-attachments/files/22464296/vulkan_windows_libs_1.4.326.zip" -OutFile vulkan_windows_libs_1.4.326.zip
Expand-Archive -Path vulkan_windows_libs_1.4.326.zip
echo "VULKAN_SDK=$(pwd)\vulkan_windows_libs_1.4.326\" >>${env:GITHUB_ENV}
- name: Fix Projects
shell: powershell
@@ -55,7 +69,7 @@ jobs:
echo '#define IMGUI_IMPLEMENTATION' >> example_single_file.cpp
echo '#include "misc/single_file/imgui_single_file.h"' >> example_single_file.cpp
g++ -I. -Wall -Wformat -shared -o libimgui.dll -Wl,--out-implib,libimgui.a example_single_file.cpp -limm32
g++ -I. -Wall -Wformat -DIMGUI_API='__declspec(dllimport)' -o example_null.exe examples/example_null/main.cpp -L. -limgui
g++ -I. -Wall -Wformat -DIMGUI_API='__declspec(dllimport)' -DIMGUI_IMPL_API= -o example_null.exe examples/example_null/main.cpp -L. -limgui
rm -f example_null.exe libimgui.* example_single_file.*
- name: Build example_null (extra warnings, msvc 64-bit)
@@ -100,11 +114,14 @@ jobs:
echo #include "misc/single_file/imgui_single_file.h" >> example_single_file.cpp
cl.exe /D_USRDLL /D_WINDLL /I. example_single_file.cpp /LD /FeImGui.dll /link
cl.exe /DIMGUI_API=__declspec(dllimport) /I. ImGui.lib /Feexample_null.exe examples/example_null/main.cpp
cl.exe /DIMGUI_API=__declspec(dllimport) -DIMGUI_IMPL_API= /I. ImGui.lib /Feexample_null.exe examples/example_null/main.cpp
# Win64 examples are more frequently compilted than the Win32 examples.
# More of the Win32 examples requires 'workflow_run' to reduce waste.
- name: Build Win32 example_glfw_opengl2
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_opengl2/example_glfw_opengl2.vcxproj /p:Platform=Win32 /p:Configuration=Release'
if: github.event_name == 'workflow_run'
- name: Build Win32 example_glfw_opengl3
shell: cmd
@@ -140,79 +157,126 @@ jobs:
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_directx11/example_sdl2_directx11.vcxproj /p:Platform=Win32 /p:Configuration=Release'
if: github.event_name == 'workflow_run'
- name: Build Win32 example_sdl3_opengl3
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl3_opengl3/example_sdl3_opengl3.vcxproj /p:Platform=Win32 /p:Configuration=Release'
- name: Build Win32 example_sdl3_sdlgpu3
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl3_sdlgpu3/example_sdl3_sdlgpu3.vcxproj /p:Platform=Win32 /p:Configuration=Release'
if: github.event_name == 'workflow_run'
- name: Build Win32 example_sdl3_sdlrenderer3
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl3_sdlrenderer3/example_sdl3_sdlrenderer3.vcxproj /p:Platform=Win32 /p:Configuration=Release'
if: github.event_name == 'workflow_run'
- name: Build Win32 example_sdl3_vulkan
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl3_vulkan/example_sdl3_vulkan.vcxproj /p:Platform=Win32 /p:Configuration=Release'
if: github.event_name == 'workflow_run'
- name: Build Win32 example_win32_directx9
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx9/example_win32_directx9.vcxproj /p:Platform=Win32 /p:Configuration=Release'
if: github.event_name == 'workflow_run'
- name: Build Win32 example_win32_directx10
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx10/example_win32_directx10.vcxproj /p:Platform=Win32 /p:Configuration=Release'
if: github.event_name == 'workflow_run'
- name: Build Win32 example_win32_directx11
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx11/example_win32_directx11.vcxproj /p:Platform=Win32 /p:Configuration=Release'
if: github.event_name == 'workflow_run'
- name: Build x64 example_glfw_opengl2
# Windows 64-bits
- name: Build Win64 example_glfw_opengl2
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_opengl2/example_glfw_opengl2.vcxproj /p:Platform=x64 /p:Configuration=Release'
if: github.event_name == 'workflow_run'
- name: Build x64 example_glfw_opengl3
- name: Build Win64 example_glfw_opengl3
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj /p:Platform=x64 /p:Configuration=Release'
- name: Build x64 example_glfw_vulkan
- name: Build Win64 example_glfw_vulkan
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj /p:Platform=x64 /p:Configuration=Release'
- name: Build x64 example_sdl2_sdlrenderer2
- name: Build Win64 example_sdl2_sdlrenderer2
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_sdlrenderer2/example_sdl2_sdlrenderer2.vcxproj /p:Platform=x64 /p:Configuration=Release'
if: github.event_name == 'workflow_run'
- name: Build x64 example_sdl2_vulkan
- name: Build Win64 example_sdl2_vulkan
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_vulkan/example_sdl2_vulkan.vcxproj /p:Platform=x64 /p:Configuration=Release'
if: github.event_name == 'workflow_run'
- name: Build x64 example_sdl2_opengl2
- name: Build Win64 example_sdl2_opengl2
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_opengl2/example_sdl2_opengl2.vcxproj /p:Platform=x64 /p:Configuration=Release'
if: github.event_name == 'workflow_run'
- name: Build x64 example_sdl2_opengl3
- name: Build Win64 example_sdl2_opengl3
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_opengl3/example_sdl2_opengl3.vcxproj /p:Platform=x64 /p:Configuration=Release'
if: github.event_name == 'workflow_run'
- name: Build x64 example_sdl2_directx11
- name: Build Win64 example_sdl2_directx11
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_directx11/example_sdl2_directx11.vcxproj /p:Platform=x64 /p:Configuration=Release'
- name: Build x64 example_win32_directx9
- name: Build Win64 example_sdl3_opengl3
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl3_opengl3/example_sdl3_opengl3.vcxproj /p:Platform=x64 /p:Configuration=Release'
if: github.event_name == 'workflow_run'
- name: Build Win64 example_sdl3_sdlgpu3
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl3_sdlgpu3/example_sdl3_sdlgpu3.vcxproj /p:Platform=x64 /p:Configuration=Release'
- name: Build Win64 example_sdl3_sdlrenderer3
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl3_sdlrenderer3/example_sdl3_sdlrenderer3.vcxproj /p:Platform=x64 /p:Configuration=Release'
- name: Build Win64 example_sdl3_vulkan
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl3_vulkan/example_sdl3_vulkan.vcxproj /p:Platform=x64 /p:Configuration=Release'
if: github.event_name == 'workflow_run'
- name: Build Win64 example_win32_directx9
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx9/example_win32_directx9.vcxproj /p:Platform=x64 /p:Configuration=Release'
if: github.event_name == 'workflow_run'
- name: Build x64 example_win32_directx10
- name: Build Win64 example_win32_directx10
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx10/example_win32_directx10.vcxproj /p:Platform=x64 /p:Configuration=Release'
if: github.event_name == 'workflow_run'
- name: Build x64 example_win32_directx11
- name: Build Win64 example_win32_directx11
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx11/example_win32_directx11.vcxproj /p:Platform=x64 /p:Configuration=Release'
if: github.event_name == 'workflow_run'
- name: Build x64 example_win32_directx12
- name: Build Win64 example_win32_directx12
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx12/example_win32_directx12.vcxproj /p:Platform=x64 /p:Configuration=Release'
Linux:
Build-Linux:
runs-on: ubuntu-latest
name: Build - Linux
defaults:
run:
working-directory: ${{ github.workspace }}/imgui
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
path: ${{ github.workspace }}/imgui
- name: Install Dependencies
run: |
@@ -279,7 +343,7 @@ jobs:
EOF
g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
- name: Build example_null (with large ImDrawIdx + pointer ImTextureID)
- name: Build example_null (with large ImDrawIdx + custom ImTextureID)
run: |
cat > example_single_file.cpp <<'EOF'
@@ -292,6 +356,21 @@ jobs:
EOF
g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
cat > example_single_file.cpp <<'EOF'
// Test build ImTextureID defined as a struct
struct SomeType { int a = 0; int b = 0; };
#define ImTextureID SomeType
#define ImTextureID_Invalid SomeType()
inline bool operator==(const SomeType& lhs, const SomeType& rhs) { return lhs.a == rhs.a && lhs.b == rhs.b; }
inline bool operator!=(const SomeType& lhs, const SomeType& rhs) { return lhs.a != rhs.a || lhs.b != rhs.b; }
#define IMGUI_IMPLEMENTATION
#include "misc/single_file/imgui_single_file.h"
#include "examples/example_null/main.cpp"
EOF
g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
- name: Build example_null (with IMGUI_DISABLE_OBSOLETE_FUNCTIONS)
run: |
cat > example_single_file.cpp <<'EOF'
@@ -426,19 +505,27 @@ jobs:
- name: Build with IMGUI_IMPL_VULKAN_NO_PROTOTYPES
run: g++ -c -I. -std=c++11 -DIMGUI_IMPL_VULKAN_NO_PROTOTYPES=1 backends/imgui_impl_vulkan.cpp
MacOS:
Build-MacOS:
runs-on: macos-latest
name: Build - MacOS
defaults:
run:
working-directory: ${{ github.workspace }}/imgui
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
path: ${{ github.workspace }}/imgui
- name: Install Dependencies
run: |
brew install glfw3 sdl2
brew install glfw3 sdl2 sdl3
- name: Build example_null (extra warnings, clang 64-bit)
run: make -C examples/example_null WITH_EXTRA_WARNINGS=1
- name: Build example_null (single file build)
- name: Build macOS example_null (single file build)
run: |
cat > example_single_file.cpp <<'EOF'
@@ -449,7 +536,7 @@ jobs:
EOF
clang++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
- name: Build example_null (single file build, c++20)
- name: Build macOS example_null (single file build, c++20)
run: |
cat > example_single_file.cpp <<'EOF'
@@ -460,7 +547,7 @@ jobs:
EOF
clang++ -I. -std=c++20 -Wall -Wformat -o example_single_file example_single_file.cpp
- name: Build example_null (without c++ runtime)
- name: Build macOS example_null (without c++ runtime)
run: |
cat > example_single_file.cpp <<'EOF'
@@ -471,46 +558,57 @@ jobs:
EOF
clang++ -I. -std=c++11 -Wall -Wformat -nodefaultlibs -fno-rtti -fno-exceptions -fno-threadsafe-statics -lc -lm -o example_single_file example_single_file.cpp
- name: Build example_glfw_opengl2
- name: Build macOS example_glfw_opengl2
run: make -C examples/example_glfw_opengl2
if: github.event_name == 'workflow_run'
- name: Build example_glfw_opengl3
- name: Build macOS example_glfw_opengl3
run: make -C examples/example_glfw_opengl3
if: github.event_name == 'workflow_run'
- name: Build example_glfw_metal
- name: Build macOS example_glfw_metal
run: make -C examples/example_glfw_metal
- name: Build example_sdl2_metal
- name: Build macOS example_sdl2_metal
run: make -C examples/example_sdl2_metal
- name: Build example_sdl2_opengl2
- name: Build macOS example_sdl2_opengl2
run: make -C examples/example_sdl2_opengl2
if: github.event_name == 'workflow_run'
- name: Build example_sdl2_opengl3
- name: Build macOS example_sdl2_opengl3
run: make -C examples/example_sdl2_opengl3
if: github.event_name == 'workflow_run'
- name: Build example_apple_metal
- name: Build macOS example_sdl3_opengl3
run: make -C examples/example_sdl3_opengl3
- name: Build macOS example_apple_metal
run: xcodebuild -project examples/example_apple_metal/example_apple_metal.xcodeproj -target example_apple_metal_macos
if: github.event_name == 'workflow_run'
- name: Build example_apple_opengl2
- name: Build macOS example_apple_opengl2
run: xcodebuild -project examples/example_apple_opengl2/example_apple_opengl2.xcodeproj -target example_osx_opengl2
if: github.event_name == 'workflow_run'
Build-iOS:
runs-on: macos-14
name: Build - iOS
iOS:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Build example_apple_metal
run: |
# Code signing is required, but we disable it because it is irrelevant for CI builds.
xcodebuild -project examples/example_apple_metal/example_apple_metal.xcodeproj -target example_apple_metal_ios CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO
Emscripten:
Build-Emscripten:
runs-on: ubuntu-latest
name: Build - Emscripten
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Install Dependencies
run: |
@@ -548,12 +646,148 @@ jobs:
emcmake cmake -B build -DCMAKE_BUILD_TYPE=Release examples/example_glfw_wgpu
cmake --build build
Android:
Build-Android:
runs-on: ubuntu-latest
name: Build - Android
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Build example_android_opengl3
run: |
cd examples/example_android_opengl3/android
gradle assembleDebug --stacktrace
Test-Windows:
runs-on: windows-2025
name: Test - Windows
defaults:
run:
working-directory: ${{ github.workspace }}/imgui
env:
MSBUILD_PATH: C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\
steps:
- uses: actions/checkout@v6
with:
path: ${{ github.workspace }}/imgui
- uses: actions/checkout@v6
continue-on-error: true
with:
fetch-depth: 1
repository: ocornut/imgui_test_engine
path: ${{ github.workspace }}/imgui_test_engine
submodules: true
- name: Fix Tests Projects
shell: powershell
working-directory: ${{ github.workspace }}/imgui_test_engine
run: |
# WARNING: This will need updating if toolset/sdk change in project files!
gci -recurse -filter "*.vcxproj" | ForEach-Object {
# Fix SDK and toolset for most samples.
(Get-Content $_.FullName) -Replace "<PlatformToolset>v110</PlatformToolset>","<PlatformToolset>v142</PlatformToolset>" | Set-Content -Path $_.FullName
(Get-Content $_.FullName) -Replace "<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>","<WindowsTargetPlatformVersion>10.0.20348.0</WindowsTargetPlatformVersion>" | Set-Content -Path $_.FullName
# Fix SDK and toolset for samples that require newer SDK/toolset. At the moment it is only dx12.
(Get-Content $_.FullName) -Replace "<PlatformToolset>v140</PlatformToolset>","<PlatformToolset>v142</PlatformToolset>" | Set-Content -Path $_.FullName
(Get-Content $_.FullName) -Replace "<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>","<WindowsTargetPlatformVersion>10.0.20348.0</WindowsTargetPlatformVersion>" | Set-Content -Path $_.FullName
}
- name: Build Tests
shell: cmd
working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
run: '"%MSBUILD_PATH%\MSBuild.exe" imgui_test_suite.vcxproj /p:Platform=x64 /p:Configuration=Release /p:ClFlags=/WX -maxcpucount:%NUMBER_OF_PROCESSORS%'
- name: Run Tests
working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
run: Release/imgui_test_suite.exe -nogui -nopause -v2 -ve4 tests
- name: Check for Docking
id: check_docking
shell: bash
working-directory: ${{ github.workspace }}/imgui
run: echo "has_dock=$(grep -q "#define IMGUI_HAS_DOCK" imgui.h && echo true || echo false)" >> $GITHUB_OUTPUT
- name: Run Viewport Tests
if: steps.check_docking.outputs.has_dock == 'true'
working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
run: Release/imgui_test_suite.exe -nogui -nopause -v2 -ve4 -viewport-mock viewport
Test-Linux:
runs-on: ubuntu-latest
name: Test - Linux
defaults:
run:
working-directory: ${{ github.workspace }}/imgui
steps:
- uses: actions/checkout@v6
with:
path: ${{ github.workspace }}/imgui
- uses: actions/checkout@v6
with:
fetch-depth: 1
repository: ocornut/imgui_test_engine
path: ${{ github.workspace }}/imgui_test_engine
submodules: true
- name: Build Tests
working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
run: make -j$(nproc)
- name: Run Tests
working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
run: ./imgui_test_suite -nogui -nopause -v2 -ve4 tests
- name: Check for Docking
id: check_docking
working-directory: ${{ github.workspace }}/imgui
run: echo "has_dock=$(grep -q "#define IMGUI_HAS_DOCK" imgui.h && echo true || echo false)" >> $GITHUB_OUTPUT
- name: Run Viewport Tests
if: steps.check_docking.outputs.has_dock == 'true'
working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
run: ./imgui_test_suite -nogui -nopause -v2 -ve4 -viewport-mock viewport
# Test-MacOS:
# runs-on: macos-latest
# name: Test - MacOS
#
# defaults:
# run:
# working-directory: ${{ github.workspace }}/imgui
#
# steps:
# - uses: actions/checkout@v6
# with:
# path: ${{ github.workspace }}/imgui
#
# - uses: actions/checkout@v6
# with:
# fetch-depth: 1
# repository: ocornut/imgui_test_engine
# path: ${{ github.workspace }}/imgui_test_engine
# submodules: true
#
# - name: Build Tests
# working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
# run: make -j$(nproc)
#
# - name: Run Tests
# working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
# run: ./imgui_test_suite -nogui -nopause -v2 -ve4 tests
#
# - name: Check for Docking
# id: check_docking
# working-directory: ${{ github.workspace }}/imgui
# run: echo "has_dock=$(grep -q "#define IMGUI_HAS_DOCK" imgui.h && echo true || echo false)" >> $GITHUB_OUTPUT
#
# - name: Run Viewport Tests
# if: steps.check_docking.outputs.has_dock == 'true'
# working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
# run: ./imgui_test_suite -nogui -nopause -v2 -ve4 -viewport-mock viewport

View File

@@ -0,0 +1,38 @@
# This is current meant to be run manually, occasionally:
# - Run then zip the contents of vulkanArtifact/ into e.g. vulkan_windows_libs_1.4.326
# - Upload as an attachment to https://github.com/ocornut/imgui/pull/8925 then change filename in build.yml
# - There is a build_windows_vulkan_libs.yml in commit history that we removed thinking this is run so rarely we don't need to pollute CI UI with it.
# Set default vulkan version if none provided
if (-not $env:VULKAN_TAG) { $env:VULKAN_TAG = "1.4.326" }
# Create output folder
mkdir vulkanArtifact
# Download Vulkan Headers
Invoke-WebRequest -Uri "https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/v$($env:VULKAN_TAG).zip" -OutFile Vulkan-Headers-$($env:VULKAN_TAG).zip
Expand-Archive -Path Vulkan-Headers-$($env:VULKAN_TAG).zip
# Copy Vulkan Headers to artifact folder
cp -R Vulkan-Headers-$($env:VULKAN_TAG)\Vulkan-Headers-$($env:VULKAN_TAG)\include vulkanArtifact\Include
# Download Vulkan Loader
Invoke-WebRequest -Uri "https://github.com/KhronosGroup/Vulkan-Loader/archive/refs/tags/v$($env:VULKAN_TAG).zip" -OutFile Vulkan-Loader-$($env:VULKAN_TAG).zip
Expand-Archive -Path Vulkan-Loader-$($env:VULKAN_TAG).zip
# Build Vulkan Loader x64
cmake -S Vulkan-Loader-$($env:VULKAN_TAG)\Vulkan-Loader-$($env:VULKAN_TAG) -B VulkanLoader-build64 -D UPDATE_DEPS=On -A x64
cmake --build VulkanLoader-build64
mkdir vulkanArtifact\Lib
copy VulkanLoader-build64\loader\Debug\vulkan-1.lib vulkanArtifact\Lib
# Build Vulkan Loader win32
cmake -S Vulkan-Loader-$($env:VULKAN_TAG)\Vulkan-Loader-$($env:VULKAN_TAG) -B VulkanLoader-build32 -D UPDATE_DEPS=On -A Win32
cmake --build VulkanLoader-build32
mkdir vulkanArtifact\Lib32
copy VulkanLoader-build32\loader\Debug\vulkan-1.lib vulkanArtifact\Lib32

View File

@@ -12,7 +12,7 @@ jobs:
PVS-Studio:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 1

5
.gitignore vendored
View File

@@ -12,6 +12,7 @@ imgui*.ini
examples/*/Debug/*
examples/*/Release/*
examples/*/x64/*
examples/*.tmp
## Visual Studio artifacts
.vs
@@ -46,6 +47,9 @@ examples/example_glfw_opengl3/web/*
examples/example_glfw_wgpu/web/*
examples/example_glfw_wgpu/external/*
examples/example_sdl2_opengl3/web/*
examples/example_sdl2_wgpu/web/*
examples/example_sdl3_opengl3/web/*
examples/example_sdl3_wgpu/web/*
## JetBrains IDE artifacts
.idea
@@ -68,6 +72,7 @@ examples/example_sdl2_opengl2/example_sdl2_opengl2
examples/example_sdl2_opengl3/example_sdl2_opengl3
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_sdlgpu3/example_sdl3_sdlgpu3
examples/example_sdl3_sdlrenderer3/example_sdl3_sdlrenderer3

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2014-2025 Omar Cornut
Copyright (c) 2014-2026 Omar Cornut
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -8,7 +8,7 @@
// [X] Platform: Clipboard support (from Allegro 5.1.12).
// [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 convert vertices manually.
// [ ] Renderer: The renderer is suboptimal as we need to unindex our buffers and convert vertices manually.
// [ ] Platform: Missing gamepad support.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
@@ -21,6 +21,9 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2025-09-18: Call platform_io.ClearRendererHandlers() and platform_io.ClearPlatformHandlers() on shutdown.
// 2025-08-12: Inputs: fixed missing support for ImGuiKey_PrintScreen under Windows, as raw Allegro 5 does not receive it.
// 2025-08-12: Added ImGui_ImplAllegro5_SetDisplay() function to change current ALLEGRO_DISPLAY, as Allegro applications often need to do that.
// 2025-07-07: Fixed texture update broken on some platforms where ALLEGRO_LOCK_WRITEONLY needed all texels to be rewritten.
// 2025-06-11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplSDLGPU3_CreateFontsTexture() and ImGui_ImplSDLGPU3_DestroyFontsTexture().
// 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support.
@@ -160,10 +163,8 @@ void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data)
ImGui_ImplAllegro5_SetupRenderState(draw_data);
// Render command lists
for (int n = 0; n < draw_data->CmdListsCount; n++)
for (const ImDrawList* draw_list : draw_data->CmdLists)
{
const ImDrawList* draw_list = draw_data->CmdLists[n];
ImVector<ImDrawVertAllegro>& vertices = bd->BufVertices;
#if ALLEGRO_HAS_DRAW_INDEXED_PRIM
vertices.resize(draw_list->VtxBuffer.Size);
@@ -269,8 +270,6 @@ void ImGui_ImplAllegro5_UpdateTexture(ImTextureData* tex)
al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP | ALLEGRO_MIN_LINEAR | ALLEGRO_MAG_LINEAR);
al_set_new_bitmap_format(ALLEGRO_PIXEL_FORMAT_ABGR_8888_LE);
ALLEGRO_BITMAP* cpu_bitmap = al_create_bitmap(tex->Width, tex->Height);
al_set_new_bitmap_flags(new_bitmap_flags);
al_set_new_bitmap_format(new_bitmap_format);
IM_ASSERT(cpu_bitmap != nullptr && "Backend failed to create texture!");
// Upload pixels
@@ -280,10 +279,15 @@ void ImGui_ImplAllegro5_UpdateTexture(ImTextureData* tex)
al_unlock_bitmap(cpu_bitmap);
// Convert software texture to hardware texture.
al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP);
al_set_new_bitmap_format(ALLEGRO_PIXEL_FORMAT_ANY_32_WITH_ALPHA);
ALLEGRO_BITMAP* gpu_bitmap = al_clone_bitmap(cpu_bitmap);
al_destroy_bitmap(cpu_bitmap);
IM_ASSERT(gpu_bitmap != nullptr && "Backend failed to create texture!");
al_set_new_bitmap_flags(new_bitmap_flags);
al_set_new_bitmap_format(new_bitmap_format);
// Store identifiers
tex->SetTexID((ImTextureID)(intptr_t)gpu_bitmap);
tex->SetStatus(ImTextureStatus_OK);
@@ -478,20 +482,9 @@ bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display)
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
bd->Display = display;
bd->LastCursor = ALLEGRO_SYSTEM_MOUSE_CURSOR_NONE;
// Create custom vertex declaration.
// Unfortunately Allegro doesn't support 32-bit packed colors so we have to convert them to 4 floats.
// We still use a custom declaration to use 'ALLEGRO_PRIM_TEX_COORD' instead of 'ALLEGRO_PRIM_TEX_COORD_PIXEL' else we can't do a reliable conversion.
ALLEGRO_VERTEX_ELEMENT elems[] =
{
{ ALLEGRO_PRIM_POSITION, ALLEGRO_PRIM_FLOAT_2, offsetof(ImDrawVertAllegro, pos) },
{ ALLEGRO_PRIM_TEX_COORD, ALLEGRO_PRIM_FLOAT_2, offsetof(ImDrawVertAllegro, uv) },
{ ALLEGRO_PRIM_COLOR_ATTR, 0, offsetof(ImDrawVertAllegro, col) },
{ 0, 0, 0 }
};
bd->VertexDecl = al_create_vertex_decl(elems, sizeof(ImDrawVertAllegro));
ImGui_ImplAllegro5_SetDisplay(display);
#if ALLEGRO_HAS_CLIPBOARD
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
@@ -507,6 +500,7 @@ void ImGui_ImplAllegro5_Shutdown()
ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
ImGui_ImplAllegro5_InvalidateDeviceObjects();
if (bd->VertexDecl)
@@ -517,9 +511,38 @@ void ImGui_ImplAllegro5_Shutdown()
io.BackendPlatformName = io.BackendRendererName = nullptr;
io.BackendPlatformUserData = nullptr;
io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_RendererHasTextures);
platform_io.ClearRendererHandlers();
platform_io.ClearPlatformHandlers();
IM_DELETE(bd);
}
void ImGui_ImplAllegro5_SetDisplay(ALLEGRO_DISPLAY* display)
{
ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
bd->Display = display;
if (bd->VertexDecl)
{
al_destroy_vertex_decl(bd->VertexDecl);
bd->VertexDecl = nullptr;
}
if (bd->Display && !bd->VertexDecl)
{
// Create custom vertex declaration.
// Unfortunately Allegro doesn't support 32-bits packed colors so we have to convert them to 4 floats.
// We still use a custom declaration to use 'ALLEGRO_PRIM_TEX_COORD' instead of 'ALLEGRO_PRIM_TEX_COORD_PIXEL' else we can't do a reliable conversion.
ALLEGRO_VERTEX_ELEMENT elems[] =
{
{ ALLEGRO_PRIM_POSITION, ALLEGRO_PRIM_FLOAT_2, offsetof(ImDrawVertAllegro, pos) },
{ ALLEGRO_PRIM_TEX_COORD, ALLEGRO_PRIM_FLOAT_2, offsetof(ImDrawVertAllegro, uv) },
{ ALLEGRO_PRIM_COLOR_ATTR, 0, offsetof(ImDrawVertAllegro, col) },
{ 0, 0, 0 }
};
bd->VertexDecl = al_create_vertex_decl(elems, sizeof(ImDrawVertAllegro));
}
}
// ev->keyboard.modifiers seems always zero so using that...
static void ImGui_ImplAllegro5_UpdateKeyModifiers()
{
@@ -661,6 +684,11 @@ void ImGui_ImplAllegro5_NewFrame()
io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f);
bd->Time = current_time;
// Allegro 5 doesn't receive PrintScreen under Windows
#ifdef _WIN32
io.AddKeyEvent(ImGuiKey_PrintScreen, (::GetAsyncKeyState(VK_SNAPSHOT) & 0x8000) != 0);
#endif
// Setup mouse cursor shape
ImGui_ImplAllegro5_UpdateMouseCursor();
}

View File

@@ -32,12 +32,13 @@ IMGUI_IMPL_API void ImGui_ImplAllegro5_Shutdown();
IMGUI_IMPL_API void ImGui_ImplAllegro5_NewFrame();
IMGUI_IMPL_API void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data);
IMGUI_IMPL_API bool ImGui_ImplAllegro5_ProcessEvent(ALLEGRO_EVENT* event);
IMGUI_IMPL_API void ImGui_ImplAllegro5_SetDisplay(ALLEGRO_DISPLAY* display);
// Use if you want to reset your rendering device without losing Dear ImGui state.
IMGUI_IMPL_API bool ImGui_ImplAllegro5_CreateDeviceObjects();
IMGUI_IMPL_API void ImGui_ImplAllegro5_InvalidateDeviceObjects();
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
// (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_ImplAllegro5_UpdateTexture(ImTextureData* tex);
#endif // #ifndef IMGUI_DISABLE

View File

@@ -16,6 +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'.
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
// 2025-06-11: DirectX10: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas.
// 2025-05-07: DirectX10: Honor draw_data->FramebufferScale to allow for custom backends and experiment using it (consistently with other renderer backends, even though in normal condition it is not set under Windows).
// 2025-01-06: DirectX10: Expose selected render state in ImGui_ImplDX10_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
@@ -73,7 +75,8 @@ struct ImGui_ImplDX10_Data
ID3D10InputLayout* pInputLayout;
ID3D10Buffer* pVertexConstantBuffer;
ID3D10PixelShader* pPixelShader;
ID3D10SamplerState* pFontSampler;
ID3D10SamplerState* pTexSamplerLinear;
ID3D10SamplerState* pTexSamplerNearest;
ID3D10RasterizerState* pRasterizerState;
ID3D10BlendState* pBlendState;
ID3D10DepthStencilState* pDepthStencilState;
@@ -140,7 +143,7 @@ static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device*
device->VSSetShader(bd->pVertexShader);
device->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer);
device->PSSetShader(bd->pPixelShader);
device->PSSetSamplers(0, 1, &bd->pFontSampler);
device->PSSetSamplers(0, 1, &bd->pTexSamplerLinear);
device->GSSetShader(nullptr);
// Setup render state
@@ -200,9 +203,8 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
ImDrawIdx* idx_dst = nullptr;
bd->pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst);
bd->pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst);
for (int n = 0; n < draw_data->CmdListsCount; n++)
for (const ImDrawList* draw_list : draw_data->CmdLists)
{
const ImDrawList* draw_list = draw_data->CmdLists[n];
memcpy(vtx_dst, draw_list->VtxBuffer.Data, draw_list->VtxBuffer.Size * sizeof(ImDrawVert));
memcpy(idx_dst, draw_list->IdxBuffer.Data, draw_list->IdxBuffer.Size * sizeof(ImDrawIdx));
vtx_dst += draw_list->VtxBuffer.Size;
@@ -258,7 +260,8 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
ImGui_ImplDX10_RenderState render_state;
render_state.Device = bd->pd3dDevice;
render_state.SamplerDefault = bd->pFontSampler;
render_state.SamplerLinear = bd->pTexSamplerLinear;
render_state.SamplerNearest = bd->pTexSamplerNearest;
render_state.VertexConstantBuffer = bd->pVertexConstantBuffer;
platform_io.Renderer_RenderState = &render_state;
@@ -268,9 +271,8 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
int global_idx_offset = 0;
ImVec2 clip_off = draw_data->DisplayPos;
ImVec2 clip_scale = draw_data->FramebufferScale;
for (int n = 0; n < draw_data->CmdListsCount; n++)
for (const ImDrawList* draw_list : draw_data->CmdLists)
{
const ImDrawList* draw_list = draw_data->CmdLists[n];
for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
{
const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
@@ -326,18 +328,18 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
static void ImGui_ImplDX10_DestroyTexture(ImTextureData* tex)
{
ImGui_ImplDX10_Texture* backend_tex = (ImGui_ImplDX10_Texture*)tex->BackendUserData;
if (backend_tex == nullptr)
return;
IM_ASSERT(backend_tex->pTextureView == (ID3D10ShaderResourceView*)(intptr_t)tex->TexID);
backend_tex->pTexture->Release();
backend_tex->pTextureView->Release();
IM_DELETE(backend_tex);
if (ImGui_ImplDX10_Texture* backend_tex = (ImGui_ImplDX10_Texture*)tex->BackendUserData)
{
IM_ASSERT(backend_tex->pTextureView == (ID3D10ShaderResourceView*)(intptr_t)tex->TexID);
backend_tex->pTextureView->Release();
backend_tex->pTexture->Release();
IM_DELETE(backend_tex);
// 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->BackendUserData = nullptr;
}
tex->SetStatus(ImTextureStatus_Destroyed);
tex->BackendUserData = nullptr;
}
void ImGui_ImplDX10_UpdateTexture(ImTextureData* tex)
@@ -565,7 +567,9 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS;
desc.MinLOD = 0.f;
desc.MaxLOD = 0.f;
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pFontSampler);
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pTexSamplerLinear);
desc.Filter = D3D10_FILTER_MIN_MAG_MIP_POINT;
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pTexSamplerNearest);
}
return true;
@@ -581,7 +585,8 @@ void ImGui_ImplDX10_InvalidateDeviceObjects()
for (ImTextureData* tex : ImGui::GetPlatformIO().Textures)
if (tex->RefCount == 1)
ImGui_ImplDX10_DestroyTexture(tex);
if (bd->pFontSampler) { bd->pFontSampler->Release(); bd->pFontSampler = nullptr; }
if (bd->pTexSamplerLinear) { bd->pTexSamplerLinear->Release(); bd->pTexSamplerLinear = nullptr; }
if (bd->pTexSamplerNearest) { bd->pTexSamplerNearest->Release(); bd->pTexSamplerNearest = nullptr; }
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = nullptr; }
@@ -632,13 +637,16 @@ void ImGui_ImplDX10_Shutdown()
ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
ImGui_ImplDX10_InvalidateDeviceObjects();
if (bd->pFactory) { bd->pFactory->Release(); }
if (bd->pd3dDevice) { bd->pd3dDevice->Release(); }
io.BackendRendererName = nullptr;
io.BackendRendererUserData = nullptr;
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
platform_io.ClearRendererHandlers();
IM_DELETE(bd);
}

View File

@@ -32,7 +32,7 @@ IMGUI_IMPL_API void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data);
IMGUI_IMPL_API bool ImGui_ImplDX10_CreateDeviceObjects();
IMGUI_IMPL_API void ImGui_ImplDX10_InvalidateDeviceObjects();
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
// (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_ImplDX10_UpdateTexture(ImTextureData* tex);
// [BETA] Selected render state data shared with callbacks.
@@ -41,7 +41,8 @@ IMGUI_IMPL_API void ImGui_ImplDX10_UpdateTexture(ImTextureData* tex);
struct ImGui_ImplDX10_RenderState
{
ID3D10Device* Device;
ID3D10SamplerState* SamplerDefault;
ID3D10SamplerState* SamplerLinear;
ID3D10SamplerState* SamplerNearest;
ID3D10Buffer* VertexConstantBuffer;
};

View File

@@ -17,6 +17,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'.
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
// 2025-06-11: DirectX11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas.
// 2025-05-07: DirectX11: Honor draw_data->FramebufferScale to allow for custom backends and experiment using it (consistently with other renderer backends, even though in normal condition it is not set under Windows).
// 2025-01-06: DirectX11: Expose VertexConstantBuffer in ImGui_ImplDX11_RenderState. Reset projection matrix in ImDrawCallback_ResetRenderState handler.
@@ -76,7 +78,8 @@ struct ImGui_ImplDX11_Data
ID3D11InputLayout* pInputLayout;
ID3D11Buffer* pVertexConstantBuffer;
ID3D11PixelShader* pPixelShader;
ID3D11SamplerState* pFontSampler;
ID3D11SamplerState* pTexSamplerLinear;
ID3D11SamplerState* pTexSamplerNearest;
ID3D11RasterizerState* pRasterizerState;
ID3D11BlendState* pBlendState;
ID3D11DepthStencilState* pDepthStencilState;
@@ -99,7 +102,7 @@ static ImGui_ImplDX11_Data* ImGui_ImplDX11_GetBackendData()
}
// Functions
static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* device_ctx)
static void ImGui_ImplDX11_SetupRenderState(const ImDrawData* draw_data, ID3D11DeviceContext* device_ctx)
{
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
@@ -143,7 +146,7 @@ static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceC
device_ctx->VSSetShader(bd->pVertexShader, nullptr, 0);
device_ctx->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer);
device_ctx->PSSetShader(bd->pPixelShader, nullptr, 0);
device_ctx->PSSetSamplers(0, 1, &bd->pFontSampler);
device_ctx->PSSetSamplers(0, 1, &bd->pTexSamplerLinear);
device_ctx->GSSetShader(nullptr, nullptr, 0);
device_ctx->HSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
device_ctx->DSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
@@ -208,9 +211,8 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
return;
ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData;
ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData;
for (int n = 0; n < draw_data->CmdListsCount; n++)
for (const ImDrawList* draw_list : draw_data->CmdLists)
{
const ImDrawList* draw_list = draw_data->CmdLists[n];
memcpy(vtx_dst, draw_list->VtxBuffer.Data, draw_list->VtxBuffer.Size * sizeof(ImDrawVert));
memcpy(idx_dst, draw_list->IdxBuffer.Data, draw_list->IdxBuffer.Size * sizeof(ImDrawIdx));
vtx_dst += draw_list->VtxBuffer.Size;
@@ -272,7 +274,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.SamplerDefault = bd->pFontSampler;
render_state.SamplerLinear = bd->pTexSamplerLinear;
render_state.SamplerNearest = bd->pTexSamplerNearest;
render_state.VertexConstantBuffer = bd->pVertexConstantBuffer;
platform_io.Renderer_RenderState = &render_state;
@@ -282,9 +285,8 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
int global_vtx_offset = 0;
ImVec2 clip_off = draw_data->DisplayPos;
ImVec2 clip_scale = draw_data->FramebufferScale;
for (int n = 0; n < draw_data->CmdListsCount; n++)
for (const ImDrawList* draw_list : draw_data->CmdLists)
{
const ImDrawList* draw_list = draw_data->CmdLists[n];
for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
{
const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
@@ -342,18 +344,18 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
static void ImGui_ImplDX11_DestroyTexture(ImTextureData* tex)
{
ImGui_ImplDX11_Texture* backend_tex = (ImGui_ImplDX11_Texture*)tex->BackendUserData;
if (backend_tex == nullptr)
return;
IM_ASSERT(backend_tex->pTextureView == (ID3D11ShaderResourceView*)(intptr_t)tex->TexID);
backend_tex->pTextureView->Release();
backend_tex->pTexture->Release();
IM_DELETE(backend_tex);
if (ImGui_ImplDX11_Texture* backend_tex = (ImGui_ImplDX11_Texture*)tex->BackendUserData)
{
IM_ASSERT(backend_tex->pTextureView == (ID3D11ShaderResourceView*)(intptr_t)tex->TexID);
backend_tex->pTextureView->Release();
backend_tex->pTexture->Release();
IM_DELETE(backend_tex);
// 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->BackendUserData = nullptr;
}
tex->SetStatus(ImTextureStatus_Destroyed);
tex->BackendUserData = nullptr;
}
void ImGui_ImplDX11_UpdateTexture(ImTextureData* tex)
@@ -580,7 +582,9 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
desc.MinLOD = 0.f;
desc.MaxLOD = 0.f;
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pFontSampler);
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pTexSamplerLinear);
desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pTexSamplerNearest);
}
return true;
@@ -597,7 +601,8 @@ void ImGui_ImplDX11_InvalidateDeviceObjects()
if (tex->RefCount == 1)
ImGui_ImplDX11_DestroyTexture(tex);
if (bd->pFontSampler) { bd->pFontSampler->Release(); bd->pFontSampler = nullptr; }
if (bd->pTexSamplerLinear) { bd->pTexSamplerLinear->Release(); bd->pTexSamplerLinear = nullptr; }
if (bd->pTexSamplerNearest) { bd->pTexSamplerNearest->Release(); bd->pTexSamplerNearest = nullptr; }
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = nullptr; }
@@ -651,14 +656,17 @@ void ImGui_ImplDX11_Shutdown()
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
ImGui_ImplDX11_InvalidateDeviceObjects();
if (bd->pFactory) { bd->pFactory->Release(); }
if (bd->pd3dDevice) { bd->pd3dDevice->Release(); }
if (bd->pd3dDeviceContext) { bd->pd3dDeviceContext->Release(); }
io.BackendRendererName = nullptr;
io.BackendRendererUserData = nullptr;
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
platform_io.ClearRendererHandlers();
IM_DELETE(bd);
}

View File

@@ -34,7 +34,7 @@ IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data);
IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects();
IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects();
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
// (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_ImplDX11_UpdateTexture(ImTextureData* tex);
// [BETA] Selected render state data shared with callbacks.
@@ -44,7 +44,8 @@ struct ImGui_ImplDX11_RenderState
{
ID3D11Device* Device;
ID3D11DeviceContext* DeviceContext;
ID3D11SamplerState* SamplerDefault;
ID3D11SamplerState* SamplerLinear;
ID3D11SamplerState* SamplerNearest;
ID3D11Buffer* VertexConstantBuffer;
};

View File

@@ -20,6 +20,11 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 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)
// 2025-09-29: DirectX12: Reuse a command list and allocator for texture uploads instead of recreating them each time. (#8963)
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
// 2025-06-19: Fixed build on MinGW. (#8702, #4594)
// 2025-06-11: DirectX12: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas.
// 2025-05-07: DirectX12: Honor draw_data->FramebufferScale to allow for custom backends and experiment using it (consistently with other renderer backends, even though in normal condition it is not set under Windows).
@@ -56,7 +61,7 @@
// DirectX
#include <d3d12.h>
#include <dxgi1_4.h>
#include <dxgi1_5.h>
#include <d3dcompiler.h>
#ifdef _MSC_VER
#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below.
@@ -86,23 +91,34 @@ struct ImGui_ImplDX12_Texture
struct ImGui_ImplDX12_Data
{
ImGui_ImplDX12_InitInfo InitInfo;
IDXGIFactory5* pdxgiFactory;
ID3D12Device* pd3dDevice;
ID3D12RootSignature* pRootSignature;
ID3D12PipelineState* pPipelineState;
ID3D12RootSignature* pRootSignatureLinear;
ID3D12RootSignature* pRootSignatureNearest;
ID3D12PipelineState* pPipelineStateLinear;
ID3D12PipelineState* pPipelineStateNearest;
ID3D12CommandQueue* pCommandQueue;
bool commandQueueOwned;
DXGI_FORMAT RTVFormat;
DXGI_FORMAT DSVFormat;
ID3D12DescriptorHeap* pd3dSrvDescHeap;
ID3D12Fence* Fence;
UINT64 FenceLastSignaledValue;
HANDLE FenceEvent;
UINT numFramesInFlight;
bool tearingSupport;
bool LegacySingleDescriptorUsed;
ID3D12CommandAllocator* pTexCmdAllocator;
ID3D12GraphicsCommandList* pTexCmdList;
ID3D12Resource* pTexUploadBuffer;
UINT pTexUploadBufferSize;
void* pTexUploadBufferMapped;
ImGui_ImplDX12_RenderBuffers* pFrameResources;
UINT frameIndex;
ImGui_ImplDX12_Texture FontTexture;
bool LegacySingleDescriptorUsed;
ImGui_ImplDX12_Data() { memset((void*)this, 0, sizeof(*this)); frameIndex = UINT_MAX; }
ImGui_ImplDX12_Data() { memset((void*)this, 0, sizeof(*this)); }
};
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
@@ -126,11 +142,27 @@ 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
static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12GraphicsCommandList* command_list, ImGui_ImplDX12_RenderBuffers* fr)
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)
{
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
command_list->SetPipelineState(bd->pPipelineStateNearest);
command_list->SetGraphicsRootSignature(bd->pRootSignatureNearest);
}
static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12GraphicsCommandList* command_list, ImGui_ImplDX12_RenderBuffers* fr)
{
// Setup orthographic projection matrix into our constant buffer
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right).
VERTEX_CONSTANT_BUFFER_DX12 vertex_constant_buffer;
@@ -172,8 +204,7 @@ static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12Graphic
ibv.Format = sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT;
command_list->IASetIndexBuffer(&ibv);
command_list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
command_list->SetPipelineState(bd->pPipelineState);
command_list->SetGraphicsRootSignature(bd->pRootSignature);
ImGui_ImplDX12_SetupSamplerLinear(command_list);
command_list->SetGraphicsRoot32BitConstants(0, 16, &vertex_constant_buffer, 0);
// Setup blend factor
@@ -262,9 +293,8 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
return;
ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource;
ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource;
for (int n = 0; n < draw_data->CmdListsCount; n++)
for (const ImDrawList* draw_list : draw_data->CmdLists)
{
const ImDrawList* draw_list = draw_data->CmdLists[n];
memcpy(vtx_dst, draw_list->VtxBuffer.Data, draw_list->VtxBuffer.Size * sizeof(ImDrawVert));
memcpy(idx_dst, draw_list->IdxBuffer.Data, draw_list->IdxBuffer.Size * sizeof(ImDrawIdx));
vtx_dst += draw_list->VtxBuffer.Size;
@@ -295,9 +325,8 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
int global_idx_offset = 0;
ImVec2 clip_off = draw_data->DisplayPos;
ImVec2 clip_scale = draw_data->FramebufferScale;
for (int n = 0; n < draw_data->CmdListsCount; n++)
for (const ImDrawList* draw_list : draw_data->CmdLists)
{
const ImDrawList* draw_list = draw_data->CmdLists[n];
for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
{
const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
@@ -337,21 +366,21 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
static void ImGui_ImplDX12_DestroyTexture(ImTextureData* tex)
{
ImGui_ImplDX12_Texture* backend_tex = (ImGui_ImplDX12_Texture*)tex->BackendUserData;
if (backend_tex == nullptr)
return;
IM_ASSERT(backend_tex->hFontSrvGpuDescHandle.ptr == (UINT64)tex->TexID);
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
bd->InitInfo.SrvDescriptorFreeFn(&bd->InitInfo, backend_tex->hFontSrvCpuDescHandle, backend_tex->hFontSrvGpuDescHandle);
SafeRelease(backend_tex->pTextureResource);
backend_tex->hFontSrvCpuDescHandle.ptr = 0;
backend_tex->hFontSrvGpuDescHandle.ptr = 0;
IM_DELETE(backend_tex);
if (ImGui_ImplDX12_Texture* backend_tex = (ImGui_ImplDX12_Texture*)tex->BackendUserData)
{
IM_ASSERT(backend_tex->hFontSrvGpuDescHandle.ptr == (UINT64)tex->TexID);
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
bd->InitInfo.SrvDescriptorFreeFn(&bd->InitInfo, backend_tex->hFontSrvCpuDescHandle, backend_tex->hFontSrvGpuDescHandle);
SafeRelease(backend_tex->pTextureResource);
backend_tex->hFontSrvCpuDescHandle.ptr = 0;
backend_tex->hFontSrvGpuDescHandle.ptr = 0;
IM_DELETE(backend_tex);
// 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->BackendUserData = nullptr;
}
tex->SetStatus(ImTextureStatus_Destroyed);
tex->BackendUserData = nullptr;
}
void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex)
@@ -430,58 +459,53 @@ void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex)
UINT upload_pitch_dst = (upload_pitch_src + D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u) & ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u);
UINT upload_size = upload_pitch_dst * upload_h;
D3D12_RESOURCE_DESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
desc.Alignment = 0;
desc.Width = upload_size;
desc.Height = 1;
desc.DepthOrArraySize = 1;
desc.MipLevels = 1;
desc.Format = DXGI_FORMAT_UNKNOWN;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
if (bd->pTexUploadBuffer == nullptr || upload_size > bd->pTexUploadBufferSize)
{
if (bd->pTexUploadBufferMapped)
{
D3D12_RANGE range = { 0, bd->pTexUploadBufferSize };
bd->pTexUploadBuffer->Unmap(0, &range);
bd->pTexUploadBufferMapped = nullptr;
}
SafeRelease(bd->pTexUploadBuffer);
D3D12_HEAP_PROPERTIES props;
memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES));
props.Type = D3D12_HEAP_TYPE_UPLOAD;
props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
D3D12_RESOURCE_DESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
desc.Alignment = 0;
desc.Width = upload_size;
desc.Height = 1;
desc.DepthOrArraySize = 1;
desc.MipLevels = 1;
desc.Format = DXGI_FORMAT_UNKNOWN;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
// FIXME-OPT: Can upload buffer be reused?
ID3D12Resource* uploadBuffer = nullptr;
HRESULT hr = bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc,
D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&uploadBuffer));
IM_ASSERT(SUCCEEDED(hr));
D3D12_HEAP_PROPERTIES props;
memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES));
props.Type = D3D12_HEAP_TYPE_UPLOAD;
props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
// Create temporary command list and execute immediately
ID3D12Fence* fence = nullptr;
hr = bd->pd3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence));
IM_ASSERT(SUCCEEDED(hr));
HRESULT hr = bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc,
D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&bd->pTexUploadBuffer));
IM_ASSERT(SUCCEEDED(hr));
HANDLE event = ::CreateEvent(0, 0, 0, 0);
IM_ASSERT(event != nullptr);
D3D12_RANGE range = {0, upload_size};
hr = bd->pTexUploadBuffer->Map(0, &range, &bd->pTexUploadBufferMapped);
IM_ASSERT(SUCCEEDED(hr));
bd->pTexUploadBufferSize = upload_size;
}
// FIXME-OPT: Create once and reuse?
ID3D12CommandAllocator* cmdAlloc = nullptr;
hr = bd->pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&cmdAlloc));
IM_ASSERT(SUCCEEDED(hr));
// FIXME-OPT: Can be use the one from user? (pass ID3D12GraphicsCommandList* to ImGui_ImplDX12_UpdateTextures)
ID3D12GraphicsCommandList* cmdList = nullptr;
hr = bd->pd3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, cmdAlloc, nullptr, IID_PPV_ARGS(&cmdList));
IM_ASSERT(SUCCEEDED(hr));
bd->pTexCmdAllocator->Reset();
bd->pTexCmdList->Reset(bd->pTexCmdAllocator, nullptr);
ID3D12GraphicsCommandList* cmdList = bd->pTexCmdList;
// Copy to upload buffer
void* mapped = nullptr;
D3D12_RANGE range = { 0, upload_size };
hr = uploadBuffer->Map(0, &range, &mapped);
IM_ASSERT(SUCCEEDED(hr));
for (int y = 0; y < upload_h; y++)
memcpy((void*)((uintptr_t)mapped + y * upload_pitch_dst), tex->GetPixelsAt(upload_x, upload_y + y), upload_pitch_src);
uploadBuffer->Unmap(0, &range);
memcpy((void*)((uintptr_t)bd->pTexUploadBufferMapped + y * upload_pitch_dst), tex->GetPixelsAt(upload_x, upload_y + y), upload_pitch_src);
if (need_barrier_before_copy)
{
@@ -498,7 +522,7 @@ void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex)
D3D12_TEXTURE_COPY_LOCATION srcLocation = {};
D3D12_TEXTURE_COPY_LOCATION dstLocation = {};
{
srcLocation.pResource = uploadBuffer;
srcLocation.pResource = bd->pTexUploadBuffer;
srcLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
srcLocation.PlacedFootprint.Footprint.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
srcLocation.PlacedFootprint.Footprint.Width = upload_w;
@@ -522,26 +546,20 @@ void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex)
cmdList->ResourceBarrier(1, &barrier);
}
hr = cmdList->Close();
HRESULT hr = cmdList->Close();
IM_ASSERT(SUCCEEDED(hr));
ID3D12CommandQueue* cmdQueue = bd->pCommandQueue;
cmdQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&cmdList);
hr = cmdQueue->Signal(fence, 1);
hr = cmdQueue->Signal(bd->Fence, ++bd->FenceLastSignaledValue);
IM_ASSERT(SUCCEEDED(hr));
// FIXME-OPT: Suboptimal?
// - To remove this may need to create NumFramesInFlight x ImGui_ImplDX12_FrameContext in backend data (mimick docking version)
// - Store per-frame in flight: upload buffer?
// - Where do cmdList and cmdAlloc fit?
fence->SetEventOnCompletion(1, event);
::WaitForSingleObject(event, INFINITE);
bd->Fence->SetEventOnCompletion(bd->FenceLastSignaledValue, bd->FenceEvent);
::WaitForSingleObject(bd->FenceEvent, INFINITE);
cmdList->Release();
cmdAlloc->Release();
::CloseHandle(event);
fence->Release();
uploadBuffer->Release();
tex->SetStatus(ImTextureStatus_OK);
}
@@ -554,9 +572,16 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
if (!bd || !bd->pd3dDevice)
return false;
if (bd->pPipelineState)
if (bd->pPipelineStateLinear)
ImGui_ImplDX12_InvalidateDeviceObjects();
HRESULT hr = ::CreateDXGIFactory1(IID_PPV_ARGS(&bd->pdxgiFactory));
IM_ASSERT(hr == S_OK);
BOOL allow_tearing = FALSE;
bd->pdxgiFactory->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allow_tearing, sizeof(allow_tearing));
bd->tearingSupport = (allow_tearing == TRUE);
// Create the root signature
{
D3D12_DESCRIPTOR_RANGE descRange = {};
@@ -580,26 +605,26 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
param[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
// Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
D3D12_STATIC_SAMPLER_DESC staticSampler = {};
staticSampler.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
staticSampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
staticSampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
staticSampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
staticSampler.MipLODBias = 0.f;
staticSampler.MaxAnisotropy = 0;
staticSampler.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
staticSampler.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK;
staticSampler.MinLOD = 0.f;
staticSampler.MaxLOD = D3D12_FLOAT32_MAX;
staticSampler.ShaderRegister = 0;
staticSampler.RegisterSpace = 0;
staticSampler.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
D3D12_STATIC_SAMPLER_DESC staticSampler[1] = {};
staticSampler[0].Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
staticSampler[0].AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
staticSampler[0].AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
staticSampler[0].AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
staticSampler[0].MipLODBias = 0.f;
staticSampler[0].MaxAnisotropy = 0;
staticSampler[0].ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
staticSampler[0].BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK;
staticSampler[0].MinLOD = 0.f;
staticSampler[0].MaxLOD = D3D12_FLOAT32_MAX;
staticSampler[0].ShaderRegister = 0;
staticSampler[0].RegisterSpace = 0;
staticSampler[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
D3D12_ROOT_SIGNATURE_DESC desc = {};
desc.NumParameters = _countof(param);
desc.pParameters = param;
desc.NumStaticSamplers = 1;
desc.pStaticSamplers = &staticSampler;
desc.pStaticSamplers = &staticSampler[0];
desc.Flags =
D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |
D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS |
@@ -616,7 +641,7 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
// (2) there exists a version of d3d12.dll for Windows 7 (D3D12On7) in one of the following directories.
// See https://github.com/ocornut/imgui/pull/3696 for details.
const char* localD3d12Paths[] = { ".\\d3d12.dll", ".\\d3d12on7\\d3d12.dll", ".\\12on7\\d3d12.dll" }; // A. current directory, B. used by some games, C. used in Microsoft D3D12On7 sample
for (int i = 0; i < IM_ARRAYSIZE(localD3d12Paths); i++)
for (int i = 0; i < IM_COUNTOF(localD3d12Paths); i++)
if ((d3d12_dll = ::LoadLibraryA(localD3d12Paths[i])) != nullptr)
break;
@@ -636,7 +661,15 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
if (D3D12SerializeRootSignatureFn(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &blob, nullptr) != S_OK)
return false;
bd->pd3dDevice->CreateRootSignature(0, blob->GetBufferPointer(), blob->GetBufferSize(), IID_PPV_ARGS(&bd->pRootSignature));
bd->pd3dDevice->CreateRootSignature(0, blob->GetBufferPointer(), blob->GetBufferSize(), IID_PPV_ARGS(&bd->pRootSignatureLinear));
blob->Release();
// Root Signature for ImDrawCallback_SetSamplerNearest
staticSampler[0].Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
if (D3D12SerializeRootSignatureFn(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &blob, nullptr) != S_OK)
return false;
bd->pd3dDevice->CreateRootSignature(0, blob->GetBufferPointer(), blob->GetBufferSize(), IID_PPV_ARGS(&bd->pRootSignatureNearest));
blob->Release();
}
@@ -649,7 +682,7 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
psoDesc.NodeMask = 1;
psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
psoDesc.pRootSignature = bd->pRootSignature;
psoDesc.pRootSignature = bd->pRootSignatureLinear;
psoDesc.SampleMask = UINT_MAX;
psoDesc.NumRenderTargets = 1;
psoDesc.RTVFormats[0] = bd->RTVFormat;
@@ -772,12 +805,37 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
desc.BackFace = desc.FrontFace;
}
HRESULT result_pipeline_state = bd->pd3dDevice->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&bd->pPipelineState));
HRESULT result_pipeline_state = bd->pd3dDevice->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&bd->pPipelineStateLinear));
if (result_pipeline_state != S_OK)
{
vertexShaderBlob->Release();
pixelShaderBlob->Release();
return false;
}
// Pipeline State for ImDrawCallback_SetSamplerNearest
psoDesc.pRootSignature = bd->pRootSignatureNearest;
result_pipeline_state = bd->pd3dDevice->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&bd->pPipelineStateNearest));
vertexShaderBlob->Release();
pixelShaderBlob->Release();
if (result_pipeline_state != S_OK)
return false;
// Create command allocator and command list for ImGui_ImplDX12_UpdateTexture()
hr = bd->pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&bd->pTexCmdAllocator));
IM_ASSERT(SUCCEEDED(hr));
hr = bd->pd3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, bd->pTexCmdAllocator, nullptr, IID_PPV_ARGS(&bd->pTexCmdList));
IM_ASSERT(SUCCEEDED(hr));
hr = bd->pTexCmdList->Close();
IM_ASSERT(SUCCEEDED(hr));
// Create fence.
hr = bd->pd3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&bd->Fence));
IM_ASSERT(hr == S_OK);
bd->FenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
IM_ASSERT(bd->FenceEvent != nullptr);
return true;
}
@@ -787,11 +845,27 @@ void ImGui_ImplDX12_InvalidateDeviceObjects()
if (!bd || !bd->pd3dDevice)
return;
SafeRelease(bd->pdxgiFactory);
if (bd->commandQueueOwned)
SafeRelease(bd->pCommandQueue);
bd->commandQueueOwned = false;
SafeRelease(bd->pRootSignature);
SafeRelease(bd->pPipelineState);
SafeRelease(bd->pRootSignatureLinear);
SafeRelease(bd->pRootSignatureNearest);
SafeRelease(bd->pPipelineStateLinear);
SafeRelease(bd->pPipelineStateNearest);
if (bd->pTexUploadBufferMapped)
{
D3D12_RANGE range = { 0, bd->pTexUploadBufferSize };
bd->pTexUploadBuffer->Unmap(0, &range);
bd->pTexUploadBufferMapped = nullptr;
}
SafeRelease(bd->pTexUploadBuffer);
SafeRelease(bd->pTexCmdList);
SafeRelease(bd->pTexCmdAllocator);
SafeRelease(bd->Fence);
CloseHandle(bd->FenceEvent);
bd->FenceEvent = nullptr;
// Destroy all textures
for (ImTextureData* tex : ImGui::GetPlatformIO().Textures)
@@ -840,12 +914,13 @@ bool ImGui_ImplDX12_Init(ImGui_ImplDX12_InitInfo* init_info)
init_info = &bd->InitInfo;
bd->pd3dDevice = init_info->Device;
IM_ASSERT(init_info->CommandQueue != NULL);
IM_ASSERT(init_info->CommandQueue != nullptr);
bd->pCommandQueue = init_info->CommandQueue;
bd->RTVFormat = init_info->RTVFormat;
bd->DSVFormat = init_info->DSVFormat;
bd->numFramesInFlight = init_info->NumFramesInFlight;
bd->pd3dSrvDescHeap = init_info->SrvDescriptorHeap;
bd->tearingSupport = false;
io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_dx12";
@@ -908,14 +983,15 @@ void ImGui_ImplDX12_Shutdown()
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
// Clean up windows and device objects
ImGui_ImplDX12_InvalidateDeviceObjects();
delete[] bd->pFrameResources;
io.BackendRendererName = nullptr;
io.BackendRendererUserData = nullptr;
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
platform_io.ClearRendererHandlers();
IM_DELETE(bd);
}
@@ -924,7 +1000,7 @@ void ImGui_ImplDX12_NewFrame()
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplDX12_Init()?");
if (!bd->pPipelineState)
if (!bd->pPipelineStateLinear)
if (!ImGui_ImplDX12_CreateDeviceObjects())
IM_ASSERT(0 && "ImGui_ImplDX12_CreateDeviceObjects() failed!");
}

View File

@@ -24,6 +24,12 @@
#include <dxgiformat.h> // DXGI_FORMAT
#include <d3d12.h> // D3D12_CPU_DESCRIPTOR_HANDLE
// Clang/GCC warnings with -Weverything
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast
#endif
// Initialization data, for ImGui_ImplDX12_Init()
struct ImGui_ImplDX12_InitInfo
{
@@ -64,7 +70,7 @@ IMGUI_IMPL_API bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames
IMGUI_IMPL_API bool ImGui_ImplDX12_CreateDeviceObjects();
IMGUI_IMPL_API void ImGui_ImplDX12_InvalidateDeviceObjects();
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
// (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_ImplDX12_UpdateTexture(ImTextureData* tex);
// [BETA] Selected render state data shared with callbacks.
@@ -76,4 +82,8 @@ struct ImGui_ImplDX12_RenderState
ID3D12GraphicsCommandList* CommandList;
};
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
#endif // #ifndef IMGUI_DISABLE

View File

@@ -17,6 +17,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
// 2025-06-11: DirectX9: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas.
// 2024-10-07: DirectX9: Changed default texture sampler to Clamp instead of Repeat/Wrap.
// 2024-02-12: DirectX9: Using RGBA format when supported by the driver to avoid CPU side conversion. (#6575)
@@ -228,9 +229,8 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
// FIXME-OPT: This is a minor waste of resource, the ideal is to use imconfig.h and
// 1) to avoid repacking colors: #define IMGUI_USE_BGRA_PACKED_COLOR
// 2) to avoid repacking vertices: #define IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT struct ImDrawVert { ImVec2 pos; float z; ImU32 col; ImVec2 uv; }
for (int n = 0; n < draw_data->CmdListsCount; n++)
for (const ImDrawList* draw_list : draw_data->CmdLists)
{
const ImDrawList* draw_list = draw_data->CmdLists[n];
const ImDrawVert* vtx_src = draw_list->VtxBuffer.Data;
for (int i = 0; i < draw_list->VtxBuffer.Size; i++)
{
@@ -260,9 +260,8 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
int global_vtx_offset = 0;
int global_idx_offset = 0;
ImVec2 clip_off = draw_data->DisplayPos;
for (int n = 0; n < draw_data->CmdListsCount; n++)
for (const ImDrawList* draw_list : draw_data->CmdLists)
{
const ImDrawList* draw_list = draw_data->CmdLists[n];
for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
{
const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
@@ -353,12 +352,15 @@ void ImGui_ImplDX9_Shutdown()
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
ImGui_ImplDX9_InvalidateDeviceObjects();
if (bd->pd3dDevice) { bd->pd3dDevice->Release(); }
io.BackendRendererName = nullptr;
io.BackendRendererUserData = nullptr;
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
platform_io.ClearRendererHandlers();
IM_DELETE(bd);
}
@@ -429,14 +431,14 @@ void ImGui_ImplDX9_UpdateTexture(ImTextureData* tex)
}
else if (tex->Status == ImTextureStatus_WantDestroy)
{
LPDIRECT3DTEXTURE9 backend_tex = (LPDIRECT3DTEXTURE9)tex->TexID;
if (backend_tex == nullptr)
return;
IM_ASSERT(tex->TexID == (ImTextureID)(intptr_t)backend_tex);
backend_tex->Release();
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);
}
}

View File

@@ -31,7 +31,7 @@ IMGUI_IMPL_API void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data);
IMGUI_IMPL_API bool ImGui_ImplDX9_CreateDeviceObjects();
IMGUI_IMPL_API void ImGui_ImplDX9_InvalidateDeviceObjects();
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
// (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_ImplDX9_UpdateTexture(ImTextureData* tex);
#endif // #ifndef IMGUI_DISABLE

View File

@@ -1,18 +1,18 @@
// dear imgui: Platform Backend for GLFW
// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..)
// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
// (Requires: GLFW 3.1+. Prefer GLFW 3.3+ or GLFW 3.4+ for full feature support.)
// (Requires: GLFW 3.0+. Prefer GLFW 3.3+/3.4+ for full feature support.)
// Implemented features:
// [X] Platform: Clipboard support.
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors) with GLFW 3.1+. Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Multiple Dear ImGui contexts support.
// Missing features or Issues:
// [ ] Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround.
// [ ] Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors.
// [ ] Platform: Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround.
// [ ] Platform: Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors.
// 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.
@@ -29,6 +29,12 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 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).
// 2025-11-06: Lower minimum requirement to GLFW 3.0. Though a recent version e.g GLFW 3.4 is highly recommended.
// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown.
// 2025-09-15: Content Scales are always reported as 1.0 on Wayland. FramebufferScale are always reported as 1.0 on X11. (#8920, #8921)
// 2025-07-08: Made ImGui_ImplGlfw_GetContentScaleForWindow(), ImGui_ImplGlfw_GetContentScaleForMonitor() helpers return 1.0f on Emscripten and Android platforms, matching macOS logic. (#8742, #8733)
// 2025-06-18: Added support for multiple Dear ImGui contexts. (#8676, #8239, #8069)
// 2025-06-11: Added ImGui_ImplGlfw_GetContentScaleForWindow(GLFWwindow* window) and ImGui_ImplGlfw_GetContentScaleForMonitor(GLFWmonitor* monitor) helper to facilitate making DPI-aware apps.
@@ -98,26 +104,51 @@
// Clang warnings with -Weverything
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
#pragma clang diagnostic ignored "-Wexit-time-destructors" // warning: declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals.
#pragma clang diagnostic ignored "-Wglobal-constructors" // warning: declaration requires a global destructor // similar to above, not sure what the exact difference is.
#endif
#if defined(__has_include)
#if !__has_include(<X11/Xlib.h>) || !__has_include(<X11/extensions/Xrandr.h>)
#define IMGUI_IMPL_GLFW_DISABLE_X11
#endif
#if !__has_include(<wayland-client.h>)
#define IMGUI_IMPL_GLFW_DISABLE_WAYLAND
#endif
#endif
// GLFW
#if !defined(IMGUI_IMPL_GLFW_DISABLE_X11) && (defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__))
#define GLFW_HAS_X11 1
#else
#define GLFW_HAS_X11 0
#endif
#if !defined(IMGUI_IMPL_GLFW_DISABLE_WAYLAND) && (defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__))
#define GLFW_HAS_WAYLAND 1
#else
#define GLFW_HAS_WAYLAND 0
#endif
#include <GLFW/glfw3.h>
#ifdef _WIN32
#undef APIENTRY
#ifndef GLFW_EXPOSE_NATIVE_WIN32
#ifndef GLFW_EXPOSE_NATIVE_WIN32 // for glfwGetWin32Window()
#define GLFW_EXPOSE_NATIVE_WIN32
#endif
#include <GLFW/glfw3native.h> // for glfwGetWin32Window()
#endif
#ifdef __APPLE__
#ifndef GLFW_EXPOSE_NATIVE_COCOA
#include <GLFW/glfw3native.h>
#elif defined(__APPLE__)
#ifndef GLFW_EXPOSE_NATIVE_COCOA // for glfwGetCocoaWindow()
#define GLFW_EXPOSE_NATIVE_COCOA
#endif
#include <GLFW/glfw3native.h> // for glfwGetCocoaWindow()
#include <GLFW/glfw3native.h>
#elif GLFW_HAS_X11
#ifndef GLFW_EXPOSE_NATIVE_X11 // for glfwGetX11Display(), glfwGetX11Window() on Freedesktop (Linux, BSD, etc.)
#define GLFW_EXPOSE_NATIVE_X11
#endif
#include <GLFW/glfw3native.h>
#endif
#undef Status // X11 headers are leaking this.
#ifndef _WIN32
#include <unistd.h> // for usleep()
#endif
@@ -135,6 +166,7 @@
// We gather version tests as define in order to easily see which features are version-dependent.
#define GLFW_VERSION_COMBINED (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 + GLFW_VERSION_REVISION)
#define GLFW_HAS_CREATECURSOR (GLFW_VERSION_COMBINED >= 3100) // 3.1+ glfwCreateCursor()
#define GLFW_HAS_PER_MONITOR_DPI (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetMonitorContentScale
#ifdef GLFW_RESIZE_NESW_CURSOR // Let's be nice to people who pulled GLFW between 2019-04-16 (3.4 define) and 2019-11-29 (cursors defines) // FIXME: Remove when GLFW 3.4 is released?
#define GLFW_HAS_NEW_CURSORS (GLFW_VERSION_COMBINED >= 3400) // 3.4+ GLFW_RESIZE_ALL_CURSOR, GLFW_RESIZE_NESW_CURSOR, GLFW_RESIZE_NWSE_CURSOR, GLFW_NOT_ALLOWED_CURSOR
@@ -144,25 +176,26 @@
#define GLFW_HAS_GAMEPAD_API (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetGamepadState() new api
#define GLFW_HAS_GETKEYNAME (GLFW_VERSION_COMBINED >= 3200) // 3.2+ glfwGetKeyName()
#define GLFW_HAS_GETERROR (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetError()
#define GLFW_HAS_GETPLATFORM (GLFW_VERSION_COMBINED >= 3400) // 3.4+ glfwGetPlatform()
// Map GLFWWindow* to ImGuiContext*.
// Map GLFWWindow* to ImGuiContext*.
// - Would be simpler if we could use glfwSetWindowUserPointer()/glfwGetWindowUserPointer(), but this is a single and shared resource.
// - Would be simpler if we could use e.g. std::map<> as well. But we don't.
// - This is not particularly optimized as we expect size to be small and queries to be rare.
struct ImGui_ImplGlfw_WindowToContext { GLFWwindow* Window; ImGuiContext* Context; };
static ImVector<ImGui_ImplGlfw_WindowToContext> g_ContextMap;
static void ImGui_ImplGlfw_ContextMap_Add(GLFWwindow* window, ImGuiContext* ctx) { g_ContextMap.push_back(ImGui_ImplGlfw_WindowToContext{ window, ctx }); }
static void ImGui_ImplGlfw_ContextMap_Remove(GLFWwindow* window) { for (ImGui_ImplGlfw_WindowToContext& entry : g_ContextMap) if (entry.Window == window) { g_ContextMap.erase_unsorted(&entry); return; } }
static void ImGui_ImplGlfw_ContextMap_Remove(GLFWwindow* window) { for (ImGui_ImplGlfw_WindowToContext& entry : g_ContextMap) if (entry.Window == window) { g_ContextMap.erase_unsorted(&entry); if (g_ContextMap.empty()) g_ContextMap.clear(); return; } }
static ImGuiContext* ImGui_ImplGlfw_ContextMap_Get(GLFWwindow* window) { for (ImGui_ImplGlfw_WindowToContext& entry : g_ContextMap) if (entry.Window == window) return entry.Context; return nullptr; }
// GLFW data
enum GlfwClientApi
{
GlfwClientApi_Unknown,
GlfwClientApi_OpenGL,
GlfwClientApi_Vulkan,
GlfwClientApi_Unknown, // Anything else fits here.
};
// GLFW data
struct ImGui_ImplGlfw_Data
{
ImGuiContext* Context;
@@ -170,8 +203,12 @@ struct ImGui_ImplGlfw_Data
GlfwClientApi ClientApi;
double Time;
GLFWwindow* MouseWindow;
#if GLFW_HAS_CREATECURSOR
GLFWcursor* MouseCursors[ImGuiMouseCursor_COUNT];
GLFWcursor* LastMouseCursor;
#endif
ImVec2 LastValidMousePos;
bool IsWayland;
bool InstalledCallbacks;
bool CallbacksChainForAllWindows;
char BackendPlatformName[32];
@@ -216,6 +253,23 @@ static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData(GLFWwindow* window)
}
// Functions
static bool ImGui_ImplGlfw_IsWayland()
{
#if !GLFW_HAS_WAYLAND
return false;
#elif GLFW_HAS_GETPLATFORM
return glfwGetPlatform() == GLFW_PLATFORM_WAYLAND;
#else
const char* version = glfwGetVersionString();
if (strstr(version, "Wayland") == nullptr) // e.g. Ubuntu 22.04 ships with GLFW 3.3.6 compiled without Wayland
return false;
#ifdef GLFW_EXPOSE_NATIVE_X11
if (glfwGetX11Display() != nullptr)
return false;
#endif
return true;
#endif
}
// Not static to allow third-party code to use that if they want to (but undocumented)
ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int keycode, int scancode);
@@ -365,7 +419,6 @@ static bool ImGui_ImplGlfw_ShouldChainCallback(ImGui_ImplGlfw_Data* bd, GLFWwind
void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods)
{
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window);
if (bd->PrevUserCallbackMousebutton != nullptr && ImGui_ImplGlfw_ShouldChainCallback(bd, window))
bd->PrevUserCallbackMousebutton(window, button, action, mods);
@@ -411,7 +464,7 @@ static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode)
{
const char char_names[] = "`-=[]\\,;\'./";
const int char_keys[] = { GLFW_KEY_GRAVE_ACCENT, GLFW_KEY_MINUS, GLFW_KEY_EQUAL, GLFW_KEY_LEFT_BRACKET, GLFW_KEY_RIGHT_BRACKET, GLFW_KEY_BACKSLASH, GLFW_KEY_COMMA, GLFW_KEY_SEMICOLON, GLFW_KEY_APOSTROPHE, GLFW_KEY_PERIOD, GLFW_KEY_SLASH, 0 };
IM_ASSERT(IM_ARRAYSIZE(char_names) == IM_ARRAYSIZE(char_keys));
IM_ASSERT(IM_COUNTOF(char_names) == IM_COUNTOF(char_keys));
if (key_name[0] >= '0' && key_name[0] <= '9') { key = GLFW_KEY_0 + (key_name[0] - '0'); }
else if (key_name[0] >= 'A' && key_name[0] <= 'Z') { key = GLFW_KEY_A + (key_name[0] - 'A'); }
else if (key_name[0] >= 'a' && key_name[0] <= 'z') { key = GLFW_KEY_A + (key_name[0] - 'a'); }
@@ -594,7 +647,7 @@ void ImGui_ImplGlfw_RestoreCallbacks(GLFWwindow* window)
bd->PrevUserCallbackMonitor = nullptr;
}
// Set to 'true' to enable chaining installed callbacks for all windows (including secondary viewports created by backends or by user.
// Set to 'true' to enable chaining installed callbacks for all windows (including secondary viewports created by backends or by user).
// This is 'false' by default meaning we only chain callbacks for the main viewport.
// We cannot set this to 'true' by default because user callbacks code may be not testing the 'window' parameter of their callback.
// If you set this to 'true' your user callback code will need to make sure you are testing the 'window' parameter.
@@ -624,12 +677,15 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
snprintf(bd->BackendPlatformName, sizeof(bd->BackendPlatformName), "imgui_impl_glfw (%d)", GLFW_VERSION_COMBINED);
io.BackendPlatformUserData = (void*)bd;
io.BackendPlatformName = bd->BackendPlatformName;
#if GLFW_HAS_CREATECURSOR
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
#endif
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
bd->Context = ImGui::GetCurrentContext();
bd->Window = window;
bd->Time = 0.0;
bd->IsWayland = ImGui_ImplGlfw_IsWayland();
ImGui_ImplGlfw_ContextMap_Add(window, bd->Context);
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
@@ -649,6 +705,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
// (By design, on X11 cursors are user configurable and some cursors may be missing. When a cursor doesn't exist,
// GLFW will emit an error which will often be printed by the app, so we temporarily disable error reporting.
// Missing cursors will return nullptr and our _UpdateMouseCursor() function will use the Arrow cursor instead.)
#if GLFW_HAS_CREATECURSOR
GLFWerrorfun prev_error_callback = glfwSetErrorCallback(nullptr);
bd->MouseCursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
bd->MouseCursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR);
@@ -667,6 +724,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
#endif
glfwSetErrorCallback(prev_error_callback);
#endif
#if GLFW_HAS_GETERROR && !defined(__EMSCRIPTEN__) // Eat errors (see #5908)
(void)glfwGetError(nullptr);
#endif
@@ -735,7 +793,9 @@ void ImGui_ImplGlfw_Shutdown()
{
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
if (bd->InstalledCallbacks)
ImGui_ImplGlfw_RestoreCallbacks(bd->Window);
@@ -743,10 +803,10 @@ void ImGui_ImplGlfw_Shutdown()
if (bd->CanvasSelector)
emscripten_set_wheel_callback(bd->CanvasSelector, nullptr, false, nullptr);
#endif
#if GLFW_HAS_CREATECURSOR
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
glfwDestroyCursor(bd->MouseCursors[cursor_n]);
#endif
// Windows: restore our WndProc hook
#ifdef _WIN32
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
@@ -758,6 +818,7 @@ void ImGui_ImplGlfw_Shutdown()
io.BackendPlatformName = nullptr;
io.BackendPlatformUserData = nullptr;
io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad);
platform_io.ClearPlatformHandlers();
ImGui_ImplGlfw_ContextMap_Remove(bd->Window);
IM_DELETE(bd);
}
@@ -806,14 +867,25 @@ static void ImGui_ImplGlfw_UpdateMouseCursor()
GLFWwindow* window = bd->Window;
if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor)
{
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
if (bd->LastMouseCursor != nullptr)
{
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
bd->LastMouseCursor = nullptr;
}
}
else
{
// Show OS mouse cursor
// FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.
glfwSetCursor(window, bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]);
#if GLFW_HAS_CREATECURSOR
GLFWcursor* cursor = bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow];
if (bd->LastMouseCursor != cursor)
{
glfwSetCursor(window, cursor);
bd->LastMouseCursor = cursor;
}
#endif
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}
}
@@ -877,6 +949,11 @@ static void ImGui_ImplGlfw_UpdateGamepads()
// - Some accessibility applications are declaring virtual monitors with a DPI of 0.0f, see #7902. We preserve this value for caller to handle.
float ImGui_ImplGlfw_GetContentScaleForWindow(GLFWwindow* window)
{
#if GLFW_HAS_WAYLAND
if (ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window))
if (bd->IsWayland)
return 1.0f;
#endif
#if GLFW_HAS_PER_MONITOR_DPI && !(defined(__APPLE__) || defined(__EMSCRIPTEN__) || defined(__ANDROID__))
float x_scale, y_scale;
glfwGetWindowContentScale(window, &x_scale, &y_scale);
@@ -889,6 +966,10 @@ float ImGui_ImplGlfw_GetContentScaleForWindow(GLFWwindow* window)
float ImGui_ImplGlfw_GetContentScaleForMonitor(GLFWmonitor* monitor)
{
#if GLFW_HAS_WAYLAND
if (ImGui_ImplGlfw_IsWayland()) // We can't access our bd->IsWayland cache for a monitor.
return 1.0f;
#endif
#if GLFW_HAS_PER_MONITOR_DPI && !(defined(__APPLE__) || defined(__EMSCRIPTEN__) || defined(__ANDROID__))
float x_scale, y_scale;
glfwGetMonitorContentScale(monitor, &x_scale, &y_scale);
@@ -905,10 +986,17 @@ static void ImGui_ImplGlfw_GetWindowSizeAndFramebufferScale(GLFWwindow* window,
int display_w, display_h;
glfwGetWindowSize(window, &w, &h);
glfwGetFramebufferSize(window, &display_w, &display_h);
float fb_scale_x = (w > 0) ? (float)display_w / (float)w : 1.0f;
float fb_scale_y = (h > 0) ? (float)display_h / (float)h : 1.0f;
#if GLFW_HAS_WAYLAND
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window);
if (!bd->IsWayland)
fb_scale_x = fb_scale_y = 1.0f;
#endif
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 / (float)w, (float)display_h / (float)h) : ImVec2(1.0f, 1.0f);
*out_framebuffer_scale = ImVec2(fb_scale_x, fb_scale_y);
}
void ImGui_ImplGlfw_NewFrame()

View File

@@ -1,17 +1,18 @@
// dear imgui: Platform Backend for GLFW
// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..)
// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
// (Requires: GLFW 3.0+. Prefer GLFW 3.3+/3.4+ for full feature support.)
// Implemented features:
// [X] Platform: Clipboard support.
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors) with GLFW 3.1+. Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Multiple Dear ImGui contexts support.
// Missing features or Issues:
// [ ] Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround.
// [ ] Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors.
// [ ] Platform: Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround.
// [ ] Platform: Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors.
// 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.
@@ -47,7 +48,7 @@ IMGUI_IMPL_API void ImGui_ImplGlfw_InstallEmscriptenCallbacks(GLFWwindow* wi
IMGUI_IMPL_API void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window);
IMGUI_IMPL_API void ImGui_ImplGlfw_RestoreCallbacks(GLFWwindow* window);
// GFLW callbacks options:
// GLFW callbacks options:
// - Set 'chain_for_all_windows=true' to enable chaining callbacks for all windows (including secondary viewports created by backends or by user)
IMGUI_IMPL_API void ImGui_ImplGlfw_SetCallbacksChainForAllWindows(bool chain_for_all_windows);

View File

@@ -39,7 +39,7 @@ IMGUI_IMPL_API void ImGui_ImplMetal_RenderDrawData(ImDrawData* drawData,
IMGUI_IMPL_API bool ImGui_ImplMetal_CreateDeviceObjects(id<MTLDevice> device);
IMGUI_IMPL_API void ImGui_ImplMetal_DestroyDeviceObjects();
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
// (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_ImplMetal_UpdateTexture(ImTextureData* tex);
#endif
@@ -67,7 +67,7 @@ IMGUI_IMPL_API void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data,
IMGUI_IMPL_API bool ImGui_ImplMetal_CreateDeviceObjects(MTL::Device* device);
IMGUI_IMPL_API void ImGui_ImplMetal_DestroyDeviceObjects();
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
// (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_ImplMetal_UpdateTexture(ImTextureData* tex);
#endif

View File

@@ -16,9 +16,10 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
// 2025-06-11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplMetal_CreateFontsTexture() and ImGui_ImplMetal_DestroyFontsTexture().
// 2025-02-03: Metal: Crash fix. (#8367)
// 2024-01-08: Metal: Fixed memory leaks when using metal-cpp (#8276, #8166) or when using multiple contexts (#7419).
// 2025-01-08: Metal: Fixed memory leaks when using metal-cpp (#8276, #8166) or when using multiple contexts (#7419).
// 2022-08-23: Metal: Update deprecated property 'sampleCount'->'rasterSampleCount'.
// 2022-07-05: Metal: Add dispatch synchronization.
// 2022-06-30: Metal: Use __bridge for ARC based systems.
@@ -148,13 +149,16 @@ void ImGui_ImplMetal_Shutdown()
ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData();
IM_UNUSED(bd);
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
ImGui_ImplMetal_DestroyDeviceObjects();
ImGui_ImplMetal_DestroyBackendData();
ImGuiIO& io = ImGui::GetIO();
io.BackendRendererName = nullptr;
io.BackendRendererUserData = nullptr;
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
platform_io.ClearRendererHandlers();
}
void ImGui_ImplMetal_NewFrame(MTLRenderPassDescriptor* renderPassDescriptor)
@@ -223,7 +227,7 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer>
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
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 || draw_data->CmdListsCount == 0)
if (fb_width <= 0 || fb_height <= 0 || draw_data->CmdLists.Size == 0)
return;
// Catch up with texture updates. Most of the times, the list will have 1 element with an OK status, aka nothing to do.
@@ -259,10 +263,8 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer>
// Render command lists
size_t vertexBufferOffset = 0;
size_t indexBufferOffset = 0;
for (int n = 0; n < draw_data->CmdListsCount; n++)
for (const ImDrawList* draw_list : draw_data->CmdLists)
{
const ImDrawList* draw_list = draw_data->CmdLists[n];
memcpy((char*)vertexBuffer.buffer.contents + vertexBufferOffset, draw_list->VtxBuffer.Data, (size_t)draw_list->VtxBuffer.Size * sizeof(ImDrawVert));
memcpy((char*)indexBuffer.buffer.contents + indexBufferOffset, draw_list->IdxBuffer.Data, (size_t)draw_list->IdxBuffer.Size * sizeof(ImDrawIdx));
@@ -336,16 +338,16 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer>
static void ImGui_ImplMetal_DestroyTexture(ImTextureData* tex)
{
MetalTexture* backend_tex = (__bridge_transfer MetalTexture*)(tex->BackendUserData);
if (backend_tex == nullptr)
return;
IM_ASSERT(backend_tex.metalTexture == (__bridge id<MTLTexture>)(void*)(intptr_t)tex->TexID);
backend_tex.metalTexture = nil;
if (MetalTexture* backend_tex = (__bridge_transfer MetalTexture*)(tex->BackendUserData))
{
IM_ASSERT(backend_tex.metalTexture == (__bridge id<MTLTexture>)(void*)(intptr_t)tex->TexID);
backend_tex.metalTexture = nil;
// 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->BackendUserData = nullptr;
}
tex->SetStatus(ImTextureStatus_Destroyed);
tex->BackendUserData = nullptr;
}
void ImGui_ImplMetal_UpdateTexture(ImTextureData* tex)

View File

@@ -0,0 +1,102 @@
// dear imgui: Null Platform+Renderer Backends
// This is designed if you need to use a blind Dear Imgui context with no input and no output.
// 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
// - 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
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2025-11-17: Initial version.
#include "imgui.h"
#ifndef IMGUI_DISABLE
#include "imgui_impl_null.h"
// Clang/GCC warnings with -Weverything
#if defined(__clang__)
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse.
#endif
IMGUI_IMPL_API bool ImGui_ImplNull_Init()
{
ImGui_ImplNullPlatform_Init();
ImGui_ImplNullRender_Init();
return true;
}
IMGUI_IMPL_API void ImGui_ImplNull_Shutdown()
{
ImGui_ImplNullRender_Shutdown();
ImGui_ImplNullPlatform_Shutdown();
}
IMGUI_IMPL_API void ImGui_ImplNull_NewFrame()
{
ImGui_ImplNullPlatform_NewFrame();
ImGui_ImplNullRender_NewFrame();
}
IMGUI_IMPL_API bool ImGui_ImplNullPlatform_Init()
{
ImGuiIO& io = ImGui::GetIO();
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;
return true;
}
IMGUI_IMPL_API void ImGui_ImplNullPlatform_Shutdown()
{
ImGuiIO& io = ImGui::GetIO();
io.BackendFlags &= ~ImGuiBackendFlags_HasMouseCursors;
}
IMGUI_IMPL_API void ImGui_ImplNullPlatform_NewFrame()
{
ImGuiIO& io = ImGui::GetIO();
io.DisplaySize = ImVec2(1920, 1080);
io.DeltaTime = 1.0f / 60.0f;
}
IMGUI_IMPL_API bool ImGui_ImplNullRender_Init()
{
ImGuiIO& io = ImGui::GetIO();
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset;
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures;
return true;
}
IMGUI_IMPL_API void ImGui_ImplNullRender_Shutdown()
{
ImGuiIO& io = ImGui::GetIO();
io.BackendFlags &= ~ImGuiBackendFlags_RendererHasVtxOffset;
io.BackendFlags &= ~ImGuiBackendFlags_RendererHasTextures;
}
IMGUI_IMPL_API void ImGui_ImplNullRender_NewFrame()
{
}
static void ImGui_ImplNullRender_UpdateTexture(ImTextureData* tex)
{
if (tex->Status == ImTextureStatus_WantCreate || tex->Status == ImTextureStatus_WantDestroy)
tex->SetStatus(ImTextureStatus_OK);
if (tex->Status == ImTextureStatus_WantDestroy)
{
tex->SetTexID(ImTextureID_Invalid);
tex->SetStatus(ImTextureStatus_Destroyed);
}
}
IMGUI_IMPL_API void ImGui_ImplNullRender_RenderDrawData(ImDrawData* draw_data)
{
if (draw_data->Textures != nullptr)
for (ImTextureData* tex : *draw_data->Textures)
if (tex->Status != ImTextureStatus_OK)
ImGui_ImplNullRender_UpdateTexture(tex);
}
#endif // #ifndef IMGUI_DISABLE

View File

@@ -0,0 +1,34 @@
// dear imgui: Null Platform+Renderer Backends
// This is designed if you need to use a blind Dear Imgui context with no input and no output.
// 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
// - 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
#pragma once
#include "imgui.h" // IMGUI_IMPL_API
#ifndef IMGUI_DISABLE
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
// Null = NullPlatform + NullRender
IMGUI_IMPL_API bool ImGui_ImplNull_Init();
IMGUI_IMPL_API void ImGui_ImplNull_Shutdown();
IMGUI_IMPL_API void ImGui_ImplNull_NewFrame();
// Null platform only (single screen, fixed timestep, no inputs)
IMGUI_IMPL_API bool ImGui_ImplNullPlatform_Init();
IMGUI_IMPL_API void ImGui_ImplNullPlatform_Shutdown();
IMGUI_IMPL_API void ImGui_ImplNullPlatform_NewFrame();
// Null renderer only (no output)
IMGUI_IMPL_API bool ImGui_ImplNullRender_Init();
IMGUI_IMPL_API void ImGui_ImplNullRender_Shutdown();
IMGUI_IMPL_API void ImGui_ImplNullRender_NewFrame();
IMGUI_IMPL_API void ImGui_ImplNullRender_RenderDrawData(ImDrawData* draw_data);
#endif // #ifndef IMGUI_DISABLE

View File

@@ -25,6 +25,8 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
// 2025-07-15: OpenGL: Set GL_UNPACK_ALIGNMENT to 1 before updating textures. (#8802)
// 2025-06-11: OpenGL: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplOpenGL2_CreateFontsTexture() and ImGui_ImplOpenGL2_DestroyFontsTexture().
// 2024-10-07: OpenGL: Changed default texture sampler to Clamp instead of Repeat/Wrap.
// 2024-06-28: OpenGL: ImGui_ImplOpenGL2_NewFrame() recreates font texture if it has been destroyed by ImGui_ImplOpenGL2_DestroyFontsTexture(). (#7748)
@@ -114,11 +116,14 @@ void ImGui_ImplOpenGL2_Shutdown()
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
ImGui_ImplOpenGL2_DestroyDeviceObjects();
io.BackendRendererName = nullptr;
io.BackendRendererUserData = nullptr;
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasTextures);
platform_io.ClearRendererHandlers();
IM_DELETE(bd);
}
@@ -208,9 +213,8 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
// Render command lists
for (int n = 0; n < draw_data->CmdListsCount; n++)
for (const ImDrawList* draw_list : draw_data->CmdLists)
{
const ImDrawList* draw_list = draw_data->CmdLists[n];
const ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data;
const ImDrawIdx* idx_buffer = draw_list->IdxBuffer.Data;
glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + offsetof(ImDrawVert, pos)));
@@ -286,6 +290,7 @@ void ImGui_ImplOpenGL2_UpdateTexture(ImTextureData* tex)
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP));
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex->Width, tex->Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
// Store identifiers
@@ -305,6 +310,7 @@ void ImGui_ImplOpenGL2_UpdateTexture(ImTextureData* tex)
GLuint gl_tex_id = (GLuint)(intptr_t)tex->TexID;
GL_CALL(glBindTexture(GL_TEXTURE_2D, gl_tex_id));
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->Width));
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
for (ImTextureRect& r : tex->Updates)
GL_CALL(glTexSubImage2D(GL_TEXTURE_2D, 0, r.x, r.y, r.w, r.h, GL_RGBA, GL_UNSIGNED_BYTE, tex->GetPixelsAt(r.x, r.y)));
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));

View File

@@ -37,7 +37,7 @@ IMGUI_IMPL_API void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data);
IMGUI_IMPL_API bool ImGui_ImplOpenGL2_CreateDeviceObjects();
IMGUI_IMPL_API void ImGui_ImplOpenGL2_DestroyDeviceObjects();
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
// (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_ImplOpenGL2_UpdateTexture(ImTextureData* tex);
#endif // #ifndef IMGUI_DISABLE

View File

@@ -23,6 +23,10 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 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)
// 2025-07-15: OpenGL: Set GL_UNPACK_ALIGNMENT to 1 before updating textures (#8802) + restore non-WebGL/ES update path that doesn't require a CPU-side copy.
// 2025-06-11: OpenGL: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplOpenGL3_CreateFontsTexture() and ImGui_ImplOpenGL3_DestroyFontsTexture().
// 2025-06-04: OpenGL: Made GLES 3.20 contexts not access GL_CONTEXT_PROFILE_MASK nor GL_PRIMITIVE_RESTART. (#8664)
// 2025-02-18: OpenGL: Lazily reinitialize embedded GL loader for when calling backend from e.g. other DLL boundaries. (#8406)
@@ -37,7 +41,7 @@
// 2023-05-09: OpenGL: Support for glBindSampler() backup/restore on ES3. (#6375)
// 2023-04-18: OpenGL: Restore front and back polygon mode separately when supported by context. (#6333)
// 2023-03-23: OpenGL: Properly restoring "no shader program bound" if it was the case prior to running the rendering function. (#6267, #6220, #6224)
// 2023-03-15: OpenGL: Fixed GL loader crash when GL_VERSION returns NULL. (#6154, #4445, #3530)
// 2023-03-15: OpenGL: Fixed GL loader crash when GL_VERSION returns nullptr. (#6154, #4445, #3530)
// 2023-03-06: OpenGL: Fixed restoration of a potentially deleted OpenGL program, by calling glIsProgram(). (#6220, #6224)
// 2022-11-09: OpenGL: Reverted use of glBufferSubData(), too many corruptions issues + old issues seemingly can't be reproed with Intel drivers nowadays (revert 2021-12-15 and 2022-05-23 changes).
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
@@ -244,6 +248,7 @@ struct ImGui_ImplOpenGL3_Data
GLsizeiptr VertexBufferSize;
GLsizeiptr IndexBufferSize;
bool HasPolygonMode;
bool HasBindSampler;
bool HasClipOrigin;
bool UseBufferSubData;
ImVector<char> TempBuffer;
@@ -286,7 +291,8 @@ struct ImGui_ImplOpenGL3_VtxAttribState
bool ImGui_ImplOpenGL3_InitLoader();
bool ImGui_ImplOpenGL3_InitLoader()
{
// Initialize our loader
// Lazily initialize our loader if not already done
// (to facilitate handling multiple DLL boundaries and multiple context shutdowns we call this from all main entry points)
#ifdef IMGUI_IMPL_OPENGL_LOADER_IMGL3W
if (glGetIntegerv == nullptr && imgl3wInit() != 0)
{
@@ -297,6 +303,13 @@ bool ImGui_ImplOpenGL3_InitLoader()
return true;
}
static void ImGui_ImplOpenGL3_ShutdownLoader()
{
#ifdef IMGUI_IMPL_OPENGL_LOADER_IMGL3W
imgl3wShutdown();
#endif
}
// Functions
bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
{
@@ -382,7 +395,7 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
glsl_version = "#version 130";
#endif
}
IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(bd->GlslVersionString));
IM_ASSERT((int)strlen(glsl_version) + 2 < IM_COUNTOF(bd->GlslVersionString));
strcpy(bd->GlslVersionString, glsl_version);
strcat(bd->GlslVersionString, "\n");
@@ -394,6 +407,9 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
// 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
@@ -415,12 +431,17 @@ 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()
@@ -428,8 +449,7 @@ void ImGui_ImplOpenGL3_NewFrame()
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplOpenGL3_Init()?");
ImGui_ImplOpenGL3_InitLoader(); // Lazily init loader if not already done for e.g. DLL boundaries.
ImGui_ImplOpenGL3_InitLoader();
if (!bd->ShaderHandle)
if (!ImGui_ImplOpenGL3_CreateDeviceObjects())
IM_ASSERT(0 && "ImGui_ImplOpenGL3_CreateDeviceObjects() failed!");
@@ -489,7 +509,7 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
glUniformMatrix4fv(bd->AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
if (bd->GlVersion >= 330 || bd->GlProfileIsES3)
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.
#endif
@@ -520,7 +540,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
if (fb_width <= 0 || fb_height <= 0)
return;
ImGui_ImplOpenGL3_InitLoader(); // Lazily init loader if not already done for e.g. DLL boundaries.
ImGui_ImplOpenGL3_InitLoader();
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
@@ -537,7 +557,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
GLuint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&last_program);
GLuint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&last_texture);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
GLuint last_sampler; if (bd->GlVersion >= 330 || bd->GlProfileIsES3) { glGetIntegerv(GL_SAMPLER_BINDING, (GLint*)&last_sampler); } else { last_sampler = 0; }
GLuint last_sampler; if (bd->HasBindSampler) { glGetIntegerv(GL_SAMPLER_BINDING, (GLint*)&last_sampler); } else { last_sampler = 0; }
#endif
GLuint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint*)&last_array_buffer);
#ifndef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
@@ -584,10 +604,8 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
// Render command lists
for (int n = 0; n < draw_data->CmdListsCount; n++)
for (const ImDrawList* draw_list : draw_data->CmdLists)
{
const ImDrawList* draw_list = draw_data->CmdLists[n];
// Upload vertex/index buffers
// - OpenGL drivers are in a very sorry state nowadays....
// During 2021 we attempted to switch from glBufferData() to orphaning+glBufferSubData() following reports
@@ -664,7 +682,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
if (last_program == 0 || glIsProgram(last_program)) glUseProgram(last_program);
glBindTexture(GL_TEXTURE_2D, last_texture);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
if (bd->GlVersion >= 330 || bd->GlProfileIsES3)
if (bd->HasBindSampler)
glBindSampler(0, last_sampler);
#endif
glActiveTexture(last_active_texture);
@@ -711,6 +729,17 @@ static void ImGui_ImplOpenGL3_DestroyTexture(ImTextureData* tex)
void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex)
{
// FIXME: Consider backing up and restoring
if (tex->Status == ImTextureStatus_WantCreate || tex->Status == ImTextureStatus_WantUpdates)
{
#ifdef GL_UNPACK_ROW_LENGTH // Not on WebGL/ES
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
#endif
#ifdef GL_UNPACK_ALIGNMENT
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
#endif
}
if (tex->Status == ImTextureStatus_WantCreate)
{
// Create and upload new texture to graphics system
@@ -730,9 +759,6 @@ void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex)
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
#ifdef GL_UNPACK_ROW_LENGTH // Not on WebGL/ES
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
#endif
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex->Width, tex->Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
// Store identifiers
@@ -751,7 +777,7 @@ void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex)
GLuint gl_tex_id = (GLuint)(intptr_t)tex->TexID;
GL_CALL(glBindTexture(GL_TEXTURE_2D, gl_tex_id));
#if 0// GL_UNPACK_ROW_LENGTH // Not on WebGL/ES
#if GL_UNPACK_ROW_LENGTH // Not on WebGL/ES
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->Width));
for (ImTextureRect& r : tex->Updates)
GL_CALL(glTexSubImage2D(GL_TEXTURE_2D, 0, r.x, r.y, r.w, r.h, GL_RGBA, GL_UNSIGNED_BYTE, tex->GetPixelsAt(r.x, r.y)));
@@ -817,6 +843,7 @@ static bool CheckProgram(GLuint handle, const char* desc)
bool ImGui_ImplOpenGL3_CreateDeviceObjects()
{
ImGui_ImplOpenGL3_InitLoader();
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
// Backup GL state
@@ -1015,6 +1042,7 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
void ImGui_ImplOpenGL3_DestroyDeviceObjects()
{
ImGui_ImplOpenGL3_InitLoader();
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
if (bd->VboHandle) { glDeleteBuffers(1, &bd->VboHandle); bd->VboHandle = 0; }
if (bd->ElementsHandle) { glDeleteBuffers(1, &bd->ElementsHandle); bd->ElementsHandle = 0; }

View File

@@ -40,7 +40,7 @@ IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data);
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateDeviceObjects();
IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects();
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
// (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_ImplOpenGL3_UpdateTexture(ImTextureData* tex);
// Configuration flags to add in your imconfig file:

View File

@@ -166,6 +166,7 @@ typedef khronos_uint8_t GLubyte;
#define GL_SCISSOR_BOX 0x0C10
#define GL_SCISSOR_TEST 0x0C11
#define GL_UNPACK_ROW_LENGTH 0x0CF2
#define GL_UNPACK_ALIGNMENT 0x0CF5
#define GL_PACK_ALIGNMENT 0x0D05
#define GL_MAX_TEXTURE_SIZE 0x0D33
#define GL_TEXTURE_2D 0x0DE1
@@ -179,6 +180,7 @@ typedef khronos_uint8_t GLubyte;
#define GL_RENDERER 0x1F01
#define GL_VERSION 0x1F02
#define GL_EXTENSIONS 0x1F03
#define GL_NEAREST 0x2600
#define GL_LINEAR 0x2601
#define GL_TEXTURE_MAG_FILTER 0x2800
#define GL_TEXTURE_MIN_FILTER 0x2801
@@ -399,9 +401,15 @@ GLAPI void APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum
#ifndef GL_VERSION_3_3
#define GL_VERSION_3_3 1
#define GL_SAMPLER_BINDING 0x8919
typedef void (APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers);
typedef void (APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers);
typedef void (APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param);
#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glGenSamplers (GLsizei count, GLuint *samplers);
GLAPI void APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers);
GLAPI void APIENTRY glBindSampler (GLuint unit, GLuint sampler);
GLAPI void APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param);
#endif
#endif /* GL_VERSION_3_3 */
#ifndef GL_VERSION_4_1
@@ -476,12 +484,13 @@ typedef GL3WglProc (*GL3WGetProcAddressProc)(const char *proc);
/* gl3w api */
GL3W_API int imgl3wInit(void);
GL3W_API int imgl3wInit2(GL3WGetProcAddressProc proc);
GL3W_API void imgl3wShutdown(void);
GL3W_API int imgl3wIsSupported(int major, int minor);
GL3W_API GL3WglProc imgl3wGetProcAddress(const char *proc);
/* gl3w internal state */
union ImGL3WProcs {
GL3WglProc ptr[60];
GL3WglProc ptr[63];
struct {
PFNGLACTIVETEXTUREPROC ActiveTexture;
PFNGLATTACHSHADERPROC AttachShader;
@@ -501,6 +510,7 @@ union ImGL3WProcs {
PFNGLCREATESHADERPROC CreateShader;
PFNGLDELETEBUFFERSPROC DeleteBuffers;
PFNGLDELETEPROGRAMPROC DeleteProgram;
PFNGLDELETESAMPLERSPROC DeleteSamplers;
PFNGLDELETESHADERPROC DeleteShader;
PFNGLDELETETEXTURESPROC DeleteTextures;
PFNGLDELETEVERTEXARRAYSPROC DeleteVertexArrays;
@@ -513,6 +523,7 @@ union ImGL3WProcs {
PFNGLENABLEVERTEXATTRIBARRAYPROC EnableVertexAttribArray;
PFNGLFLUSHPROC Flush;
PFNGLGENBUFFERSPROC GenBuffers;
PFNGLGENSAMPLERSPROC GenSamplers;
PFNGLGENTEXTURESPROC GenTextures;
PFNGLGENVERTEXARRAYSPROC GenVertexArrays;
PFNGLGETATTRIBLOCATIONPROC GetAttribLocation;
@@ -533,6 +544,7 @@ union ImGL3WProcs {
PFNGLPIXELSTOREIPROC PixelStorei;
PFNGLPOLYGONMODEPROC PolygonMode;
PFNGLREADPIXELSPROC ReadPixels;
PFNGLSAMPLERPARAMETERIPROC SamplerParameteri;
PFNGLSCISSORPROC Scissor;
PFNGLSHADERSOURCEPROC ShaderSource;
PFNGLTEXIMAGE2DPROC TexImage2D;
@@ -567,6 +579,7 @@ GL3W_API extern union ImGL3WProcs imgl3wProcs;
#define glCreateShader imgl3wProcs.gl.CreateShader
#define glDeleteBuffers imgl3wProcs.gl.DeleteBuffers
#define glDeleteProgram imgl3wProcs.gl.DeleteProgram
#define glDeleteSamplers imgl3wProcs.gl.DeleteSamplers
#define glDeleteShader imgl3wProcs.gl.DeleteShader
#define glDeleteTextures imgl3wProcs.gl.DeleteTextures
#define glDeleteVertexArrays imgl3wProcs.gl.DeleteVertexArrays
@@ -579,6 +592,7 @@ GL3W_API extern union ImGL3WProcs imgl3wProcs;
#define glEnableVertexAttribArray imgl3wProcs.gl.EnableVertexAttribArray
#define glFlush imgl3wProcs.gl.Flush
#define glGenBuffers imgl3wProcs.gl.GenBuffers
#define glGenSamplers imgl3wProcs.gl.GenSamplers
#define glGenTextures imgl3wProcs.gl.GenTextures
#define glGenVertexArrays imgl3wProcs.gl.GenVertexArrays
#define glGetAttribLocation imgl3wProcs.gl.GetAttribLocation
@@ -599,6 +613,7 @@ GL3W_API extern union ImGL3WProcs imgl3wProcs;
#define glPixelStorei imgl3wProcs.gl.PixelStorei
#define glPolygonMode imgl3wProcs.gl.PolygonMode
#define glReadPixels imgl3wProcs.gl.ReadPixels
#define glSamplerParameteri imgl3wProcs.gl.SamplerParameteri
#define glScissor imgl3wProcs.gl.Scissor
#define glShaderSource imgl3wProcs.gl.ShaderSource
#define glTexImage2D imgl3wProcs.gl.TexImage2D
@@ -631,7 +646,7 @@ extern "C" {
#endif
#include <windows.h>
static HMODULE libgl;
static HMODULE libgl = NULL;
typedef PROC(__stdcall* GL3WglGetProcAddr)(LPCSTR);
static GL3WglGetProcAddr wgl_get_proc_address;
@@ -644,7 +659,7 @@ static int open_libgl(void)
return GL3W_OK;
}
static void close_libgl(void) { FreeLibrary(libgl); }
static void close_libgl(void) { FreeLibrary(libgl); libgl = NULL; }
static GL3WglProc get_proc(const char *proc)
{
GL3WglProc res;
@@ -656,7 +671,7 @@ static GL3WglProc get_proc(const char *proc)
#elif defined(__APPLE__)
#include <dlfcn.h>
static void *libgl;
static void *libgl = NULL;
static int open_libgl(void)
{
libgl = dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY | RTLD_LOCAL);
@@ -665,7 +680,7 @@ static int open_libgl(void)
return GL3W_OK;
}
static void close_libgl(void) { dlclose(libgl); }
static void close_libgl(void) { dlclose(libgl); libgl = NULL; }
static GL3WglProc get_proc(const char *proc)
{
@@ -699,7 +714,11 @@ static void close_libgl(void)
static int is_library_loaded(const char* name, void** lib)
{
#if defined(__HAIKU__)
*lib = NULL; // no support for RTLD_NOLOAD on Haiku.
#else
*lib = dlopen(name, RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
#endif
return *lib != NULL;
}
@@ -817,6 +836,7 @@ static int parse_version(void)
}
static void load_procs(GL3WGetProcAddressProc proc);
static void clear_procs();
int imgl3wInit(void)
{
@@ -833,6 +853,12 @@ int imgl3wInit2(GL3WGetProcAddressProc proc)
return parse_version();
}
void imgl3wShutdown(void)
{
close_libgl();
clear_procs();
}
int imgl3wIsSupported(int major, int minor)
{
if (major < 2)
@@ -863,6 +889,7 @@ static const char *proc_names[] = {
"glCreateShader",
"glDeleteBuffers",
"glDeleteProgram",
"glDeleteSamplers",
"glDeleteShader",
"glDeleteTextures",
"glDeleteVertexArrays",
@@ -875,6 +902,7 @@ static const char *proc_names[] = {
"glEnableVertexAttribArray",
"glFlush",
"glGenBuffers",
"glGenSamplers",
"glGenTextures",
"glGenVertexArrays",
"glGetAttribLocation",
@@ -895,6 +923,7 @@ static const char *proc_names[] = {
"glPixelStorei",
"glPolygonMode",
"glReadPixels",
"glSamplerParameteri",
"glScissor",
"glShaderSource",
"glTexImage2D",
@@ -916,6 +945,13 @@ static void load_procs(GL3WGetProcAddressProc proc)
imgl3wProcs.ptr[i] = proc(proc_names[i]);
}
static void clear_procs()
{
size_t i;
for (i = 0; i < GL3W_ARRAY_SIZE(proc_names); i++)
imgl3wProcs.ptr[i] = nullptr;
}
#ifdef __cplusplus
}
#endif

View File

@@ -29,6 +29,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown.
// 2025-06-27: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support.
// 2025-06-12: ImGui_ImplOSX_HandleEvent() only process event for window containing our view. (#8644)
// 2025-03-21: Fill gamepad inputs and set ImGuiBackendFlags_HasGamepad regardless of ImGuiConfigFlags_NavEnableGamepad being set.
@@ -147,9 +148,11 @@ static bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view);
NSWindow* window = view.window;
if (!window)
return;
NSRect contentRect = [window contentRectForFrameRect:window.frame];
NSRect rect = NSMakeRect(_posX, contentRect.size.height - _posY, 0, 0);
_imeRect = [window convertRectToScreen:rect];
{
NSRect contentRect = [window contentRectForFrameRect:window.frame];
NSRect rect = NSMakeRect(_posX, contentRect.size.height - _posY, 0, 0);
_imeRect = [window convertRectToScreen:rect];
}
}
- (void)viewDidMoveToWindow
@@ -514,9 +517,12 @@ void ImGui_ImplOSX_Shutdown()
ImGui_ImplOSX_DestroyBackendData();
ImGuiIO& io = ImGui::GetIO();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
io.BackendPlatformName = nullptr;
io.BackendPlatformUserData = nullptr;
io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasGamepad);
platform_io.ClearPlatformHandlers();
}
static void ImGui_ImplOSX_UpdateMouseCursor()
@@ -625,9 +631,9 @@ void ImGui_ImplOSX_NewFrame(NSView* view)
// Setup display size
if (view)
{
const float dpi = (float)[view.window backingScaleFactor];
const float fb_scale = (float)[view.window backingScaleFactor];
io.DisplaySize = ImVec2((float)view.bounds.size.width, (float)view.bounds.size.height);
io.DisplayFramebufferScale = ImVec2(dpi, dpi);
io.DisplayFramebufferScale = ImVec2(fb_scale, fb_scale);
}
// Setup time step

View File

@@ -21,12 +21,17 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 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)
// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown.
// 2025-09-15: Content Scales are always reported as 1.0 on Wayland. (#8921)
// 2025-07-08: Made ImGui_ImplSDL2_GetContentScaleForWindow(), ImGui_ImplSDL2_GetContentScaleForDisplay() helpers return 1.0f on Emscripten and Android platforms, matching macOS logic. (#8742, #8733)
// 2025-06-11: Added ImGui_ImplSDL2_GetContentScaleForWindow(SDL_Window* window) and ImGui_ImplSDL2_GetContentScaleForDisplay(int display_index) helper to facilitate making DPI-aware apps.
// 2025-04-09: Don't attempt to call SDL_CaptureMouse() on drivers where we don't call SDL_GetGlobalMouseState(). (#8561)
// 2025-03-21: Fill gamepad inputs and set ImGuiBackendFlags_HasGamepad regardless of ImGuiConfigFlags_NavEnableGamepad being set.
// 2025-03-10: When dealing with OEM keys, use scancodes instead of translated keycodes to choose ImGuiKey values. (#7136, #7201, #7206, #7306, #7670, #7672, #8468)
// 2025-02-26: Only start SDL_CaptureMouse() when mouse is being dragged, to mitigate issues with e.g.Linux debuggers not claiming capture back. (#6410, #3650)
// 2025-02-26: Only start SDL_CaptureMouse() when mouse is being dragged, to mitigate issues with e.g. Linux debuggers not claiming capture back. (#6410, #3650)
// 2025-02-24: Avoid calling SDL_GetGlobalMouseState() when mouse is in relative mode.
// 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support.
// 2025-02-10: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler.
@@ -137,7 +142,7 @@
struct ImGui_ImplSDL2_Data
{
SDL_Window* Window;
Uint32 WindowID;
Uint32 WindowID; // Stored in ImGuiViewport::PlatformHandle. Use SDL_GetWindowFromID() to get SDL_Window* from Uint32 WindowID.
SDL_Renderer* Renderer;
Uint64 Time;
char* ClipboardTextData;
@@ -150,7 +155,7 @@ struct ImGui_ImplSDL2_Data
SDL_Cursor* MouseLastCursor;
int MouseLastLeaveFrame;
bool MouseCanUseGlobalState;
bool MouseCanUseCapture;
ImGui_ImplSDL2_MouseCaptureMode MouseCaptureMode;
// Gamepad handling
ImVector<SDL_GameController*> Gamepads;
@@ -175,7 +180,10 @@ static const char* ImGui_ImplSDL2_GetClipboardText(ImGuiContext*)
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
if (bd->ClipboardTextData)
SDL_free(bd->ClipboardTextData);
bd->ClipboardTextData = SDL_GetClipboardText();
if (SDL_HasClipboardText())
bd->ClipboardTextData = SDL_GetClipboardText();
else
bd->ClipboardTextData = nullptr;
return bd->ClipboardTextData;
}
@@ -365,7 +373,6 @@ static ImGuiViewport* ImGui_ImplSDL2_GetViewportForWindowID(Uint32 window_id)
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
// If you have multiple SDL events and some of them are not meant to be used by dear imgui, you may need to filter events based on their windowID field.
bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
{
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
@@ -459,7 +466,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
bd->MouseLastLeaveFrame = ImGui::GetFrameCount() + 1;
if (window_event == SDL_WINDOWEVENT_FOCUS_GAINED)
io.AddFocusEvent(true);
else if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST)
if (window_event == SDL_WINDOWEVENT_FOCUS_LOST)
io.AddFocusEvent(false);
return true;
}
@@ -484,6 +491,7 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
//SDL_SetHint(SDL_HINT_EVENT_LOGGING, "2");
// Obtain compiled and runtime versions
SDL_version ver_compiled;
@@ -507,13 +515,16 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void
// Check and store if we are on a SDL backend that supports SDL_GetGlobalMouseState() and SDL_CaptureMouse()
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
bd->MouseCanUseGlobalState = false;
bd->MouseCanUseCapture = false;
bd->MouseCaptureMode = ImGui_ImplSDL2_MouseCaptureMode_Disabled;
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
const char* sdl_backend = SDL_GetCurrentVideoDriver();
const char* capture_and_global_state_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" };
for (const char* item : capture_and_global_state_whitelist)
if (strncmp(sdl_backend, item, strlen(item)) == 0)
bd->MouseCanUseGlobalState = bd->MouseCanUseCapture = true;
{
bd->MouseCanUseGlobalState = true;
bd->MouseCaptureMode = (strcmp(item, "x11") == 0) ? ImGui_ImplSDL2_MouseCaptureMode_EnabledAfterDrag : ImGui_ImplSDL2_MouseCaptureMode_Enabled;
}
#endif
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
@@ -628,6 +639,7 @@ void ImGui_ImplSDL2_Shutdown()
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
if (bd->ClipboardTextData)
SDL_free(bd->ClipboardTextData);
@@ -638,9 +650,18 @@ void ImGui_ImplSDL2_Shutdown()
io.BackendPlatformName = nullptr;
io.BackendPlatformUserData = nullptr;
io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad);
platform_io.ClearPlatformHandlers();
IM_DELETE(bd);
}
void ImGui_ImplSDL2_SetMouseCaptureMode(ImGui_ImplSDL2_MouseCaptureMode mode)
{
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
if (mode == ImGui_ImplSDL2_MouseCaptureMode_Disabled && bd->MouseCaptureMode != ImGui_ImplSDL2_MouseCaptureMode_Disabled)
SDL_CaptureMouse(SDL_FALSE);
bd->MouseCaptureMode = mode;
}
static void ImGui_ImplSDL2_UpdateMouseData()
{
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
@@ -649,8 +670,12 @@ static void ImGui_ImplSDL2_UpdateMouseData()
// We forward mouse input when hovered or captured (via SDL_MOUSEMOTION) or when focused (below)
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
// - SDL_CaptureMouse() let the OS know e.g. that our drags can extend outside of parent boundaries (we want updated position) and shouldn't trigger other operations outside.
// - Debuggers under Linux tends to leave captured mouse on break, which may be very inconvenient, so to mitigate the issue we wait until mouse has moved to begin capture.
if (bd->MouseCanUseCapture)
// - Debuggers under Linux tends to leave captured mouse on break, which may be very inconvenient, so to mitigate the issue on X11 we we wait until mouse has moved to begin capture.
if (bd->MouseCaptureMode == ImGui_ImplSDL2_MouseCaptureMode_Enabled)
{
SDL_CaptureMouse((bd->MouseButtonsDown != 0) ? SDL_TRUE : SDL_FALSE);
}
else if (bd->MouseCaptureMode == ImGui_ImplSDL2_MouseCaptureMode_EnabledAfterDrag)
{
bool want_capture = false;
for (int button_n = 0; button_n < ImGuiMouseButton_COUNT && !want_capture; button_n++)
@@ -662,6 +687,7 @@ static void ImGui_ImplSDL2_UpdateMouseData()
SDL_Window* focused_window = SDL_GetKeyboardFocus();
const bool is_app_focused = (bd->Window == focused_window);
#else
SDL_Window* focused_window = bd->Window;
const bool is_app_focused = (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_INPUT_FOCUS) != 0; // SDL 2.0.3 and non-windowed systems: single-viewport only
#endif
if (is_app_focused)
@@ -670,15 +696,20 @@ static void ImGui_ImplSDL2_UpdateMouseData()
if (io.WantSetMousePos)
SDL_WarpMouseInWindow(bd->Window, (int)io.MousePos.x, (int)io.MousePos.y);
// (Optional) Fallback to provide mouse position when focused (SDL_MOUSEMOTION already provides this when hovered or captured)
// (Optional) Fallback to provide unclamped mouse position when focused but not hovered (SDL_MOUSEMOTION already provides this when hovered or captured)
// Note that SDL_GetGlobalMouseState() is in theory slow on X11, but this only runs on rather specific cases. If a problem we may provide a way to opt-out this feature.
SDL_Window* hovered_window = SDL_GetMouseFocus();
const bool is_relative_mouse_mode = SDL_GetRelativeMouseMode() != 0;
if (bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0 && !is_relative_mouse_mode)
if (hovered_window == nullptr && bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0 && !is_relative_mouse_mode)
{
// Single-viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window)
int window_x, window_y, mouse_x_global, mouse_y_global;
SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global);
SDL_GetWindowPosition(bd->Window, &window_x, &window_y);
io.AddMousePosEvent((float)(mouse_x_global - window_x), (float)(mouse_y_global - window_y));
int mouse_x, mouse_y;
int window_x, window_y;
SDL_GetGlobalMouseState(&mouse_x, &mouse_y);
SDL_GetWindowPosition(focused_window, &window_x, &window_y);
mouse_x -= window_x;
mouse_y -= window_y;
io.AddMousePosEvent((float)mouse_x, (float)mouse_y);
}
}
}
@@ -719,6 +750,9 @@ float ImGui_ImplSDL2_GetContentScaleForWindow(SDL_Window* window)
float ImGui_ImplSDL2_GetContentScaleForDisplay(int display_index)
{
const char* sdl_driver = SDL_GetCurrentVideoDriver();
if (sdl_driver && strcmp(sdl_driver, "wayland") == 0)
return 1.0f;
#if SDL_HAS_PER_MONITOR_DPI
#if !defined(__APPLE__) && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__)
float dpi = 0.0f;

View File

@@ -47,4 +47,11 @@ IMGUI_IMPL_API float ImGui_ImplSDL2_GetContentScaleForDisplay(int display_ind
enum ImGui_ImplSDL2_GamepadMode { ImGui_ImplSDL2_GamepadMode_AutoFirst, ImGui_ImplSDL2_GamepadMode_AutoAll, ImGui_ImplSDL2_GamepadMode_Manual };
IMGUI_IMPL_API void ImGui_ImplSDL2_SetGamepadMode(ImGui_ImplSDL2_GamepadMode mode, struct _SDL_GameController** manual_gamepads_array = nullptr, int manual_gamepads_count = -1);
// (Advanced, for X11 users) Override Mouse Capture mode. Mouse capture allows receiving updated mouse position after clicking inside our window and dragging outside it.
// Having this 'Enabled' is in theory always better. But, on X11 if you crash/break to debugger while capture is active you may temporarily lose access to your mouse.
// The best solution is to setup your debugger to automatically release capture, e.g. 'setxkbmap -option grab:break_actions && xdotool key XF86Ungrab' or via a GDB script. See #3650.
// But you may independently decide on X11, when a debugger is attached, to set this value to ImGui_ImplSDL2_MouseCaptureMode_Disabled.
enum ImGui_ImplSDL2_MouseCaptureMode { ImGui_ImplSDL2_MouseCaptureMode_Enabled, ImGui_ImplSDL2_MouseCaptureMode_EnabledAfterDrag, ImGui_ImplSDL2_MouseCaptureMode_Disabled };
IMGUI_IMPL_API void ImGui_ImplSDL2_SetMouseCaptureMode(ImGui_ImplSDL2_MouseCaptureMode mode);
#endif // #ifndef IMGUI_DISABLE

View File

@@ -20,13 +20,20 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 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_ImplSDL3_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-11-05: Fixed an issue with missing characters events when an already active text field changes viewports. (#9054)
// 2025-10-22: Fixed Platform_OpenInShellFn() return value (unused in core).
// 2025-09-24: Skip using the SDL_GetGlobalMouseState() state when one of our window is hovered, as the SDL_EVENT_MOUSE_MOTION data is reliable. Fix macOS notch mouse coordinates issue in fullscreen mode + better perf on X11. (#7919, #7786)
// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown.
// 2025-09-15: Use SDL_GetWindowDisplayScale() on Mac to output DisplayFrameBufferScale. The function is more reliable during resolution changes e.g. going fullscreen. (#8703, #4414)
// 2025-06-27: IME: avoid calling SDL_StartTextInput() again if already active. (#8727)
// 2025-04-22: IME: honor ImGuiPlatformImeData->WantTextInput as an alternative way to call SDL_StartTextInput(), without IME being necessarily visible.
// 2025-04-09: Don't attempt to call SDL_CaptureMouse() on drivers where we don't call SDL_GetGlobalMouseState(). (#8561)
// 2025-03-30: Update for SDL3 api changes: Revert SDL_GetClipboardText() memory ownership change. (#8530, #7801)
// 2025-03-21: Fill gamepad inputs and set ImGuiBackendFlags_HasGamepad regardless of ImGuiConfigFlags_NavEnableGamepad being set.
// 2025-03-10: When dealing with OEM keys, use scancodes instead of translated keycodes to choose ImGuiKey values. (#7136, #7201, #7206, #7306, #7670, #7672, #8468)
// 2025-02-26: Only start SDL_CaptureMouse() when mouse is being dragged, to mitigate issues with e.g.Linux debuggers not claiming capture back. (#6410, #3650)
// 2025-02-26: Only start SDL_CaptureMouse() when mouse is being dragged, to mitigate issues with e.g. Linux debuggers not claiming capture back. (#6410, #3650)
// 2025-02-24: Avoid calling SDL_GetGlobalMouseState() when mouse is in relative mode.
// 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support.
// 2025-02-10: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler.
@@ -108,6 +115,8 @@ struct ImGui_ImplSDL3_Data
// IME handling
SDL_Window* ImeWindow;
ImGuiPlatformImeData ImeData;
bool ImeDirty;
// Mouse handling
Uint32 MouseWindowID;
@@ -116,7 +125,7 @@ struct ImGui_ImplSDL3_Data
SDL_Cursor* MouseLastCursor;
int MousePendingLeaveFrame;
bool MouseCanUseGlobalState;
bool MouseCanUseCapture;
ImGui_ImplSDL3_MouseCaptureMode MouseCaptureMode;
// Gamepad handling
ImVector<SDL_Gamepad*> Gamepads;
@@ -135,13 +144,19 @@ static ImGui_ImplSDL3_Data* ImGui_ImplSDL3_GetBackendData()
return ImGui::GetCurrentContext() ? (ImGui_ImplSDL3_Data*)ImGui::GetIO().BackendPlatformUserData : nullptr;
}
// Forward Declarations
static void ImGui_ImplSDL3_UpdateIme();
// Functions
static const char* ImGui_ImplSDL3_GetClipboardText(ImGuiContext*)
{
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
if (bd->ClipboardTextData)
SDL_free(bd->ClipboardTextData);
bd->ClipboardTextData = SDL_GetClipboardText();
if (SDL_HasClipboardText())
bd->ClipboardTextData = SDL_GetClipboardText();
else
bd->ClipboardTextData = nullptr;
return bd->ClipboardTextData;
}
@@ -150,16 +165,38 @@ static void ImGui_ImplSDL3_SetClipboardText(ImGuiContext*, const char* text)
SDL_SetClipboardText(text);
}
static void ImGui_ImplSDL3_PlatformSetImeData(ImGuiContext*, ImGuiViewport* viewport, ImGuiPlatformImeData* data)
static ImGuiViewport* ImGui_ImplSDL3_GetViewportForWindowID(SDL_WindowID window_id)
{
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
SDL_WindowID window_id = (SDL_WindowID)(intptr_t)viewport->PlatformHandle;
SDL_Window* window = SDL_GetWindowFromID(window_id);
return (window_id == bd->WindowID) ? ImGui::GetMainViewport() : nullptr;
}
static void ImGui_ImplSDL3_PlatformSetImeData(ImGuiContext*, ImGuiViewport*, ImGuiPlatformImeData* data)
{
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
bd->ImeData = *data;
bd->ImeDirty = true;
ImGui_ImplSDL3_UpdateIme();
}
// We discard viewport passed via ImGuiPlatformImeData and always call SDL_StartTextInput() on SDL_GetKeyboardFocus().
static void ImGui_ImplSDL3_UpdateIme()
{
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
ImGuiPlatformImeData* data = &bd->ImeData;
SDL_Window* window = SDL_GetKeyboardFocus();
// Stop previous input
if ((!(data->WantVisible || data->WantTextInput) || bd->ImeWindow != window) && bd->ImeWindow != nullptr)
{
SDL_StopTextInput(bd->ImeWindow);
bd->ImeWindow = nullptr;
}
if ((!bd->ImeDirty && bd->ImeWindow == window) || (window == nullptr))
return;
// Start/update current input
bd->ImeDirty = false;
if (data->WantVisible)
{
SDL_Rect r;
@@ -336,18 +373,10 @@ static void ImGui_ImplSDL3_UpdateKeyModifiers(SDL_Keymod sdl_key_mods)
io.AddKeyEvent(ImGuiMod_Super, (sdl_key_mods & SDL_KMOD_GUI) != 0);
}
static ImGuiViewport* ImGui_ImplSDL3_GetViewportForWindowID(SDL_WindowID window_id)
{
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
return (window_id == bd->WindowID) ? ImGui::GetMainViewport() : nullptr;
}
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
// If you have multiple SDL events and some of them are not meant to be used by dear imgui, you may need to filter events based on their windowID field.
bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event)
{
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
@@ -470,6 +499,7 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
IM_UNUSED(sdl_gl_context); // Unused in this branch
//SDL_SetHint(SDL_HINT_EVENT_LOGGING, "2");
const int ver_linked = SDL_GetVersion();
@@ -489,20 +519,23 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void
// Check and store if we are on a SDL backend that supports SDL_GetGlobalMouseState() and SDL_CaptureMouse()
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
bd->MouseCanUseGlobalState = false;
bd->MouseCanUseCapture = false;
bd->MouseCaptureMode = ImGui_ImplSDL3_MouseCaptureMode_Disabled;
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
const char* sdl_backend = SDL_GetCurrentVideoDriver();
const char* capture_and_global_state_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" };
for (const char* item : capture_and_global_state_whitelist)
if (strncmp(sdl_backend, item, strlen(item)) == 0)
bd->MouseCanUseGlobalState = bd->MouseCanUseCapture = true;
{
bd->MouseCanUseGlobalState = true;
bd->MouseCaptureMode = (strcmp(item, "x11") == 0) ? ImGui_ImplSDL3_MouseCaptureMode_EnabledAfterDrag : ImGui_ImplSDL3_MouseCaptureMode_Enabled;
}
#endif
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Platform_SetClipboardTextFn = ImGui_ImplSDL3_SetClipboardText;
platform_io.Platform_GetClipboardTextFn = ImGui_ImplSDL3_GetClipboardText;
platform_io.Platform_SetImeDataFn = ImGui_ImplSDL3_PlatformSetImeData;
platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { return SDL_OpenURL(url) == 0; };
platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { return SDL_OpenURL(url); };
// Gamepad handling
bd->GamepadMode = ImGui_ImplSDL3_GamepadMode_AutoFirst;
@@ -530,22 +563,18 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void
// Without this, when clicking to gain focus, our widgets wouldn't activate even though they showed as hovered.
// (This is unfortunately a global SDL setting, so enabling it might have a side-effect on your application.
// It is unlikely to make a difference, but if your app absolutely needs to ignore the initial on-focus click:
// you can ignore SDL_EVENT_MOUSE_BUTTON_DOWN events coming right after a SDL_WINDOWEVENT_FOCUS_GAINED)
#ifdef SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH
// you can ignore SDL_EVENT_MOUSE_BUTTON_DOWN events coming right after a SDL_EVENT_WINDOW_FOCUS_GAINED)
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
#endif
// From 2.0.22: Disable auto-capture, this is preventing drag and drop across multiple windows (see #5710)
#ifdef SDL_HINT_MOUSE_AUTO_CAPTURE
SDL_SetHint(SDL_HINT_MOUSE_AUTO_CAPTURE, "0");
#endif
return true;
}
// Should technically be a SDL_GLContext but due to typedef it is sane to keep it void* in public interface.
bool ImGui_ImplSDL3_InitForOpenGL(SDL_Window* window, void* sdl_gl_context)
{
IM_UNUSED(sdl_gl_context); // Viewport branch will need this.
return ImGui_ImplSDL3_Init(window, nullptr, sdl_gl_context);
}
@@ -589,6 +618,7 @@ void ImGui_ImplSDL3_Shutdown()
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
if (bd->ClipboardTextData)
SDL_free(bd->ClipboardTextData);
@@ -599,9 +629,18 @@ void ImGui_ImplSDL3_Shutdown()
io.BackendPlatformName = nullptr;
io.BackendPlatformUserData = nullptr;
io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad);
platform_io.ClearPlatformHandlers();
IM_DELETE(bd);
}
void ImGui_ImplSDL3_SetMouseCaptureMode(ImGui_ImplSDL3_MouseCaptureMode mode)
{
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
if (mode == ImGui_ImplSDL3_MouseCaptureMode_Disabled && bd->MouseCaptureMode != ImGui_ImplSDL3_MouseCaptureMode_Disabled)
SDL_CaptureMouse(false);
bd->MouseCaptureMode = mode;
}
static void ImGui_ImplSDL3_UpdateMouseData()
{
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
@@ -610,8 +649,12 @@ static void ImGui_ImplSDL3_UpdateMouseData()
// We forward mouse input when hovered or captured (via SDL_EVENT_MOUSE_MOTION) or when focused (below)
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
// - SDL_CaptureMouse() let the OS know e.g. that our drags can extend outside of parent boundaries (we want updated position) and shouldn't trigger other operations outside.
// - Debuggers under Linux tends to leave captured mouse on break, which may be very inconvenient, so to mitigate the issue we wait until mouse has moved to begin capture.
if (bd->MouseCanUseCapture)
// - Debuggers under Linux tends to leave captured mouse on break, which may be very inconvenient, so to mitigate the issue on X11 we we wait until mouse has moved to begin capture.
if (bd->MouseCaptureMode == ImGui_ImplSDL3_MouseCaptureMode_Enabled)
{
SDL_CaptureMouse(bd->MouseButtonsDown != 0);
}
else if (bd->MouseCaptureMode == ImGui_ImplSDL3_MouseCaptureMode_EnabledAfterDrag)
{
bool want_capture = false;
for (int button_n = 0; button_n < ImGuiMouseButton_COUNT && !want_capture; button_n++)
@@ -632,16 +675,20 @@ static void ImGui_ImplSDL3_UpdateMouseData()
if (io.WantSetMousePos)
SDL_WarpMouseInWindow(bd->Window, io.MousePos.x, io.MousePos.y);
// (Optional) Fallback to provide mouse position when focused (SDL_EVENT_MOUSE_MOTION already provides this when hovered or captured)
// (Optional) Fallback to provide unclamped mouse position when focused but not hovered (SDL_EVENT_MOUSE_MOTION already provides this when hovered or captured)
// Note that SDL_GetGlobalMouseState() is in theory slow on X11, but this only runs on rather specific cases. If a problem we may provide a way to opt-out this feature.
SDL_Window* hovered_window = SDL_GetMouseFocus();
const bool is_relative_mouse_mode = SDL_GetWindowRelativeMouseMode(bd->Window);
if (bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0 && !is_relative_mouse_mode)
if (hovered_window == nullptr && bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0 && !is_relative_mouse_mode)
{
// Single-viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window)
float mouse_x_global, mouse_y_global;
float mouse_x, mouse_y;
int window_x, window_y;
SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global);
SDL_GetGlobalMouseState(&mouse_x, &mouse_y);
SDL_GetWindowPosition(focused_window, &window_x, &window_y);
io.AddMousePosEvent(mouse_x_global - window_x, mouse_y_global - window_y);
mouse_x -= window_x;
mouse_y -= window_y;
io.AddMousePosEvent(mouse_x, mouse_y);
}
}
}
@@ -778,15 +825,24 @@ static void ImGui_ImplSDL3_UpdateGamepads()
static void ImGui_ImplSDL3_GetWindowSizeAndFramebufferScale(SDL_Window* window, ImVec2* out_size, ImVec2* out_framebuffer_scale)
{
int w, h;
int display_w, display_h;
SDL_GetWindowSize(window, &w, &h);
if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED)
w = h = 0;
#if defined(__APPLE__)
float fb_scale_x = SDL_GetWindowDisplayScale(window); // Seems more reliable during resolution change (#8703)
float fb_scale_y = fb_scale_x;
#else
int display_w, display_h;
SDL_GetWindowSizeInPixels(window, &display_w, &display_h);
float fb_scale_x = (w > 0) ? (float)display_w / (float)w : 1.0f;
float fb_scale_y = (h > 0) ? (float)display_h / (float)h : 1.0f;
#endif
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 = ImVec2(fb_scale_x, fb_scale_y);
}
void ImGui_ImplSDL3_NewFrame()
@@ -816,6 +872,7 @@ void ImGui_ImplSDL3_NewFrame()
ImGui_ImplSDL3_UpdateMouseData();
ImGui_ImplSDL3_UpdateMouseCursor();
ImGui_ImplSDL3_UpdateIme();
// Update game controllers (if enabled and available)
ImGui_ImplSDL3_UpdateGamepads();

View File

@@ -44,4 +44,11 @@ IMGUI_IMPL_API bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event);
enum ImGui_ImplSDL3_GamepadMode { ImGui_ImplSDL3_GamepadMode_AutoFirst, ImGui_ImplSDL3_GamepadMode_AutoAll, ImGui_ImplSDL3_GamepadMode_Manual };
IMGUI_IMPL_API void ImGui_ImplSDL3_SetGamepadMode(ImGui_ImplSDL3_GamepadMode mode, SDL_Gamepad** manual_gamepads_array = nullptr, int manual_gamepads_count = -1);
// (Advanced, for X11 users) Override Mouse Capture mode. Mouse capture allows receiving updated mouse position after clicking inside our window and dragging outside it.
// Having this 'Enabled' is in theory always better. But, on X11 if you crash/break to debugger while capture is active you may temporarily lose access to your mouse.
// The best solution is to setup your debugger to automatically release capture, e.g. 'setxkbmap -option grab:break_actions && xdotool key XF86Ungrab' or via a GDB script. See #3650.
// But you may independently decide on X11, when a debugger is attached, to set this value to ImGui_ImplSDL3_MouseCaptureMode_Disabled.
enum ImGui_ImplSDL3_MouseCaptureMode { ImGui_ImplSDL3_MouseCaptureMode_Enabled, ImGui_ImplSDL3_MouseCaptureMode_EnabledAfterDrag, ImGui_ImplSDL3_MouseCaptureMode_Disabled };
IMGUI_IMPL_API void ImGui_ImplSDL3_SetMouseCaptureMode(ImGui_ImplSDL3_MouseCaptureMode mode);
#endif // #ifndef IMGUI_DISABLE

View File

@@ -2,7 +2,7 @@
// This needs to be used along with the SDL3 Platform Backend
// Implemented features:
// [X] Renderer: User texture binding. Use simply cast a reference to your SDL_GPUTextureSamplerBinding to ImTextureID.
// [X] Renderer: User texture binding. Use 'SDL_GPUTexture*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef! **IMPORTANT** Before 2025/08/08, ImTextureID was a reference to a SDL_GPUTextureSamplerBinding struct.
// [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).
@@ -22,6 +22,11 @@
// Calling the function is MANDATORY, otherwise the ImGui will not upload neither the vertex nor the index buffer for the GPU. See imgui_impl_sdlgpu3.cpp for more info.
// CHANGELOG
// 2025-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.
// 2025-08-20: Added ImGui_ImplSDLGPU3_InitInfo::SwapchainComposition and ImGui_ImplSDLGPU3_InitInfo::PresentMode to configure how secondary viewports are created.
// 2025-08-08: *BREAKING* Changed ImTextureID type from SDL_GPUTextureSamplerBinding* to SDL_GPUTexture*, which is more natural and easier for user to manage. If you need to change the current sampler, you can access the ImGui_ImplSDLGPU3_RenderState struct. (#8866, #8163, #7998, #7988)
// 2025-08-08: Expose SamplerDefault and SamplerCurrent in ImGui_ImplSDLGPU3_RenderState. Allow callback to change sampler.
// 2025-06-25: Mapping transfer buffer for texture update use cycle=true. Fixes artifacts e.g. on Metal backend.
// 2025-06-11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplSDLGPU3_CreateFontsTexture() and ImGui_ImplSDLGPU3_DestroyFontsTexture().
// 2025-04-28: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
@@ -36,11 +41,6 @@
#include "imgui_impl_sdlgpu3_shaders.h"
// SDL_GPU Data
struct ImGui_ImplSDLGPU3_Texture
{
SDL_GPUTexture* Texture = nullptr;
SDL_GPUTextureSamplerBinding TextureSamplerBinding = { nullptr, nullptr };
};
// Reusable buffers used for rendering 1 current in-flight frame, for ImGui_ImplSDLGPU3_RenderDrawData()
struct ImGui_ImplSDLGPU3_FrameData
@@ -61,7 +61,8 @@ struct ImGui_ImplSDLGPU3_Data
SDL_GPUShader* VertexShader = nullptr;
SDL_GPUShader* FragmentShader = nullptr;
SDL_GPUGraphicsPipeline* Pipeline = nullptr;
SDL_GPUSampler* TexSampler = nullptr;
SDL_GPUSampler* TexSamplerLinear = nullptr;
SDL_GPUSampler* TexSamplerNearest = nullptr;
SDL_GPUTransferBuffer* TexTransferBuffer = nullptr;
uint32_t TexTransferBufferSize = 0;
@@ -84,12 +85,13 @@ 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, 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, 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)
{
//ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
render_state->SamplerCurrent = bd->TexSamplerLinear;
// Bind graphics pipeline
SDL_BindGPUGraphicsPipeline(render_pass,pipeline);
SDL_BindGPUGraphicsPipeline(render_pass, pipeline);
// Bind Vertex And Index Buffers
if (draw_data->TotalVtxCount > 0)
@@ -180,9 +182,8 @@ void ImGui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuff
ImDrawVert* vtx_dst = (ImDrawVert*)SDL_MapGPUTransferBuffer(v->Device, fd->VertexTransferBuffer, true);
ImDrawIdx* idx_dst = (ImDrawIdx*)SDL_MapGPUTransferBuffer(v->Device, fd->IndexTransferBuffer, true);
for (int n = 0; n < draw_data->CmdListsCount; n++)
for (const ImDrawList* draw_list : draw_data->CmdLists)
{
const ImDrawList* draw_list = draw_data->CmdLists[n];
memcpy(vtx_dst, draw_list->VtxBuffer.Data, draw_list->VtxBuffer.Size * sizeof(ImDrawVert));
memcpy(idx_dst, draw_list->IdxBuffer.Data, draw_list->IdxBuffer.Size * sizeof(ImDrawIdx));
vtx_dst += draw_list->VtxBuffer.Size;
@@ -228,19 +229,26 @@ void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffe
if (pipeline == nullptr)
pipeline = bd->Pipeline;
ImGui_ImplSDLGPU3_SetupRenderState(draw_data, pipeline, command_buffer, render_pass, fd, fb_width, fb_height);
// Will project scissor/clipping rectangles into framebuffer space
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
// Setup render state structure (for callbacks and custom texture bindings)
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;
ImGui_ImplSDLGPU3_SetupRenderState(draw_data, &render_state, 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)
int global_vtx_offset = 0;
int global_idx_offset = 0;
for (int n = 0; n < draw_data->CmdListsCount; n++)
for (const ImDrawList* draw_list : draw_data->CmdLists)
{
const ImDrawList* draw_list = draw_data->CmdLists[n];
for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
{
const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
@@ -249,7 +257,7 @@ void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffe
// 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, pipeline, command_buffer, render_pass, fd, fb_width, fb_height);
ImGui_ImplSDLGPU3_SetupRenderState(draw_data, &render_state, pipeline, command_buffer, render_pass, fd, fb_width, fb_height);
else
pcmd->UserCallback(draw_list, pcmd);
}
@@ -276,9 +284,14 @@ void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffe
SDL_SetGPUScissor(render_pass,&scissor_rect);
// Bind DescriptorSet with font or user texture
SDL_BindGPUFragmentSamplers(render_pass, 0, (SDL_GPUTextureSamplerBinding*)pcmd->GetTexID(), 1);
SDL_GPUTextureSamplerBinding texture_sampler_binding;
texture_sampler_binding.texture = (SDL_GPUTexture*)(intptr_t)pcmd->GetTexID();
texture_sampler_binding.sampler = render_state.SamplerCurrent;
SDL_BindGPUFragmentSamplers(render_pass, 0, &texture_sampler_binding, 1);
// Draw
// **IF YOU GET A CRASH HERE** In 1.92.2 on 2025/08/08 we have changed ImTextureID to store 'SDL_GPUTexture*' instead of storing 'SDL_GPUTextureSamplerBinding'.
// Any code loading custom texture using this backend needs to be updated.
SDL_DrawGPUIndexedPrimitives(render_pass, pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
}
}
@@ -297,18 +310,12 @@ void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffe
static void ImGui_ImplSDLGPU3_DestroyTexture(ImTextureData* tex)
{
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
ImGui_ImplSDLGPU3_Texture* backend_tex = (ImGui_ImplSDLGPU3_Texture*)tex->BackendUserData;
if (backend_tex == nullptr)
return;
SDL_GPUTextureSamplerBinding* binding = (SDL_GPUTextureSamplerBinding*)(intptr_t)tex->BackendUserData;
IM_ASSERT(backend_tex->Texture == binding->texture);
SDL_ReleaseGPUTexture(bd->InitInfo.Device, backend_tex->Texture);
IM_DELETE(backend_tex);
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);
tex->SetStatus(ImTextureStatus_Destroyed);
tex->BackendUserData = nullptr;
}
void ImGui_ImplSDLGPU3_UpdateTexture(ImTextureData* tex)
@@ -322,7 +329,6 @@ void ImGui_ImplSDLGPU3_UpdateTexture(ImTextureData* tex)
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
ImGui_ImplSDLGPU3_Texture* backend_tex = IM_NEW(ImGui_ImplSDLGPU3_Texture)();
// Create texture
SDL_GPUTextureCreateInfo texture_info = {};
@@ -335,19 +341,16 @@ void ImGui_ImplSDLGPU3_UpdateTexture(ImTextureData* tex)
texture_info.num_levels = 1;
texture_info.sample_count = SDL_GPU_SAMPLECOUNT_1;
backend_tex->Texture = SDL_CreateGPUTexture(v->Device, &texture_info);
backend_tex->TextureSamplerBinding.texture = backend_tex->Texture;
backend_tex->TextureSamplerBinding.sampler = bd->TexSampler;
IM_ASSERT(backend_tex->Texture && "Failed to create font texture, call SDL_GetError() for more info");
SDL_GPUTexture* raw_tex = SDL_CreateGPUTexture(v->Device, &texture_info);
IM_ASSERT(raw_tex != nullptr && "Failed to create texture, call SDL_GetError() for more info");
// Store identifiers
tex->SetTexID((ImTextureID)(intptr_t)&backend_tex->TextureSamplerBinding);
tex->BackendUserData = backend_tex;
tex->SetTexID((ImTextureID)(intptr_t)raw_tex);
}
if (tex->Status == ImTextureStatus_WantCreate || tex->Status == ImTextureStatus_WantUpdates)
{
ImGui_ImplSDLGPU3_Texture* backend_tex = (ImGui_ImplSDLGPU3_Texture*)tex->BackendUserData;
SDL_GPUTexture* raw_tex = (SDL_GPUTexture*)(intptr_t)tex->GetTexID();
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
// Update full texture or selected blocks. We only ever write to textures regions which have never been used before!
@@ -369,7 +372,7 @@ void ImGui_ImplSDLGPU3_UpdateTexture(ImTextureData* tex)
transferbuffer_info.size = upload_size + 1024;
bd->TexTransferBufferSize = upload_size + 1024;
bd->TexTransferBuffer = SDL_CreateGPUTransferBuffer(v->Device, &transferbuffer_info);
IM_ASSERT(bd->TexTransferBuffer != nullptr && "Failed to create font transfer buffer, call SDL_GetError() for more information");
IM_ASSERT(bd->TexTransferBuffer != nullptr && "Failed to create transfer buffer, call SDL_GetError() for more information");
}
// Copy to transfer buffer
@@ -385,7 +388,7 @@ void ImGui_ImplSDLGPU3_UpdateTexture(ImTextureData* tex)
transfer_info.transfer_buffer = bd->TexTransferBuffer;
SDL_GPUTextureRegion texture_region = {};
texture_region.texture = backend_tex->Texture;
texture_region.texture = raw_tex;
texture_region.x = (Uint32)upload_x;
texture_region.y = (Uint32)upload_y;
texture_region.w = (Uint32)upload_w;
@@ -452,14 +455,31 @@ static void ImGui_ImplSDLGPU3_CreateShaders()
#ifdef __APPLE__
else
{
vertex_shader_info.entrypoint = "main0";
vertex_shader_info.format = SDL_GPU_SHADERFORMAT_METALLIB;
vertex_shader_info.code = metallib_vertex;
vertex_shader_info.code_size = sizeof(metallib_vertex);
fragment_shader_info.entrypoint = "main0";
fragment_shader_info.format = SDL_GPU_SHADERFORMAT_METALLIB;
fragment_shader_info.code = metallib_fragment;
fragment_shader_info.code_size = sizeof(metallib_fragment);
SDL_GPUShaderFormat supported_formats = SDL_GetGPUShaderFormats(v->Device);
if (supported_formats & SDL_GPU_SHADERFORMAT_METALLIB)
{
// Using metallib blobs (macOS 14+, iOS)
vertex_shader_info.entrypoint = "main0";
vertex_shader_info.format = SDL_GPU_SHADERFORMAT_METALLIB;
vertex_shader_info.code = metallib_vertex;
vertex_shader_info.code_size = sizeof(metallib_vertex);
fragment_shader_info.entrypoint = "main0";
fragment_shader_info.format = SDL_GPU_SHADERFORMAT_METALLIB;
fragment_shader_info.code = metallib_fragment;
fragment_shader_info.code_size = sizeof(metallib_fragment);
}
else if (supported_formats & SDL_GPU_SHADERFORMAT_MSL)
{
// macOS: using MSL source
vertex_shader_info.entrypoint = "main0";
vertex_shader_info.format = SDL_GPU_SHADERFORMAT_MSL;
vertex_shader_info.code = msl_vertex;
vertex_shader_info.code_size = sizeof(msl_vertex);
fragment_shader_info.entrypoint = "main0";
fragment_shader_info.format = SDL_GPU_SHADERFORMAT_MSL;
fragment_shader_info.code = msl_fragment;
fragment_shader_info.code_size = sizeof(msl_fragment);
}
}
#endif
bd->VertexShader = SDL_CreateGPUShader(v->Device, &vertex_shader_info);
@@ -558,7 +578,7 @@ void ImGui_ImplSDLGPU3_CreateDeviceObjects()
ImGui_ImplSDLGPU3_DestroyDeviceObjects();
if (bd->TexSampler == nullptr)
if (bd->TexSamplerLinear == nullptr)
{
// Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
SDL_GPUSamplerCreateInfo sampler_info = {};
@@ -574,9 +594,14 @@ void ImGui_ImplSDLGPU3_CreateDeviceObjects()
sampler_info.enable_anisotropy = false;
sampler_info.max_anisotropy = 1.0f;
sampler_info.enable_compare = false;
bd->TexSamplerLinear = SDL_CreateGPUSampler(v->Device, &sampler_info);
IM_ASSERT(bd->TexSamplerLinear != nullptr && "Failed to create sampler, call SDL_GetError() for more information");
bd->TexSampler = SDL_CreateGPUSampler(v->Device, &sampler_info);
IM_ASSERT(bd->TexSampler != nullptr && "Failed to create font sampler, call SDL_GetError() for more information");
sampler_info.min_filter = SDL_GPU_FILTER_NEAREST;
sampler_info.mag_filter = SDL_GPU_FILTER_NEAREST;
sampler_info.mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_NEAREST;
bd->TexSamplerNearest = SDL_CreateGPUSampler(v->Device, &sampler_info);
IM_ASSERT(bd->TexSamplerNearest != nullptr && "Failed to create sampler, call SDL_GetError() for more information");
}
ImGui_ImplSDLGPU3_CreateGraphicsPipeline();
@@ -611,7 +636,8 @@ void ImGui_ImplSDLGPU3_DestroyDeviceObjects()
if (bd->TexTransferBuffer) { SDL_ReleaseGPUTransferBuffer(v->Device, bd->TexTransferBuffer); bd->TexTransferBuffer = nullptr; }
if (bd->VertexShader) { SDL_ReleaseGPUShader(v->Device, bd->VertexShader); bd->VertexShader = nullptr; }
if (bd->FragmentShader) { SDL_ReleaseGPUShader(v->Device, bd->FragmentShader); bd->FragmentShader = nullptr; }
if (bd->TexSampler) { SDL_ReleaseGPUSampler(v->Device, bd->TexSampler); bd->TexSampler = nullptr; }
if (bd->TexSamplerLinear) { SDL_ReleaseGPUSampler(v->Device, bd->TexSamplerLinear); bd->TexSamplerLinear = nullptr; }
if (bd->TexSamplerNearest) { SDL_ReleaseGPUSampler(v->Device, bd->TexSamplerNearest); bd->TexSamplerNearest = nullptr; }
if (bd->Pipeline) { SDL_ReleaseGPUGraphicsPipeline(v->Device, bd->Pipeline); bd->Pipeline = nullptr; }
}
@@ -641,11 +667,14 @@ void ImGui_ImplSDLGPU3_Shutdown()
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
ImGui_ImplSDLGPU3_DestroyDeviceObjects();
io.BackendRendererName = nullptr;
io.BackendRendererUserData = nullptr;
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
platform_io.ClearRendererHandlers();
IM_DELETE(bd);
}
@@ -654,7 +683,7 @@ void ImGui_ImplSDLGPU3_NewFrame()
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplSDLGPU3_Init()?");
if (!bd->TexSampler)
if (!bd->TexSamplerLinear)
ImGui_ImplSDLGPU3_CreateDeviceObjects();
}

View File

@@ -2,7 +2,7 @@
// This needs to be used along with the SDL3 Platform Backend
// Implemented features:
// [X] Renderer: User texture binding. Use simply cast a reference to your SDL_GPUTextureSamplerBinding to ImTextureID.
// [X] Renderer: User texture binding. Use 'SDL_GPUTexture*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef! **IMPORTANT** Before 2025/08/08, ImTextureID was a reference to a SDL_GPUTextureSamplerBinding struct.
// [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).
@@ -27,12 +27,14 @@
#include <SDL3/SDL_gpu.h>
// Initialization data, for ImGui_ImplSDLGPU_Init()
// - Remember to set ColorTargetFormat to the correct format. If you're rendering to the swapchain, call SDL_GetGPUSwapchainTextureFormat to query the right value
// - Remember to set ColorTargetFormat to the correct format. If you're rendering to the swapchain, call SDL_GetGPUSwapchainTextureFormat() to query the right value
struct ImGui_ImplSDLGPU3_InitInfo
{
SDL_GPUDevice* Device = nullptr;
SDL_GPUTextureFormat ColorTargetFormat = SDL_GPU_TEXTUREFORMAT_INVALID;
SDL_GPUSampleCount MSAASamples = SDL_GPU_SAMPLECOUNT_1;
SDL_GPUDevice* Device = nullptr;
SDL_GPUTextureFormat ColorTargetFormat = SDL_GPU_TEXTUREFORMAT_INVALID;
SDL_GPUSampleCount MSAASamples = SDL_GPU_SAMPLECOUNT_1;
SDL_GPUSwapchainComposition SwapchainComposition = SDL_GPU_SWAPCHAINCOMPOSITION_SDR; // Only used in multi-viewports mode.
SDL_GPUPresentMode PresentMode = SDL_GPU_PRESENTMODE_VSYNC; // Only used in multi-viewports mode.
};
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
@@ -46,7 +48,18 @@ IMGUI_IMPL_API void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data,
IMGUI_IMPL_API void ImGui_ImplSDLGPU3_CreateDeviceObjects();
IMGUI_IMPL_API void ImGui_ImplSDLGPU3_DestroyDeviceObjects();
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
// (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_ImplSDLGPU3_UpdateTexture(ImTextureData* tex);
// [BETA] Selected render state data shared with callbacks.
// This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplSDLGPU3_RenderDrawData() call.
// (Please open an issue if you feel you need access to more data)
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

View File

@@ -221,6 +221,40 @@ const uint8_t metallib_fragment[3787] = {
148,161,0,0,0,0,109,97,105,110,48,97,105,114,46,115,97,109,112,108,101,95,116,101,120,116,117,114,101,95,50,100,46,118,52,102,51,50,51,50,48,50,51,46,51,54,56,97,105,114,54,52,45,97,
112,112,108,101,45,109,97,99,111,115,120,49,52,46,48,46,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};
static uint8_t msl_vertex[800] =
{
35,105,110,99,108,117,100,101,32,60,109,101,116,97,108,95,115,116,100,108,105,98,62,10,35,105,110,99,108,117,100,101,32,60,115,105,109,100,47,115,105,109,100,46,104,62,10,10,117,115,
105,110,103,32,110,97,109,101,115,112,97,99,101,32,109,101,116,97,108,59,10,10,115,116,114,117,99,116,32,95,57,10,123,10,32,32,32,32,102,108,111,97,116,52,32,67,111,108,111,114,59,
10,32,32,32,32,102,108,111,97,116,50,32,85,86,59,10,125,59,10,10,115,116,114,117,99,116,32,85,66,79,10,123,10,32,32,32,32,102,108,111,97,116,50,32,117,83,99,97,108,101,59,10,32,32,
32,32,102,108,111,97,116,50,32,117,84,114,97,110,115,108,97,116,101,59,10,125,59,10,10,115,116,114,117,99,116,32,109,97,105,110,48,95,111,117,116,10,123,10,32,32,32,32,102,108,111,
97,116,52,32,79,117,116,95,67,111,108,111,114,32,91,91,117,115,101,114,40,108,111,99,110,48,41,93,93,59,10,32,32,32,32,102,108,111,97,116,50,32,79,117,116,95,85,86,32,91,91,117,115,
101,114,40,108,111,99,110,49,41,93,93,59,10,32,32,32,32,102,108,111,97,116,52,32,103,108,95,80,111,115,105,116,105,111,110,32,91,91,112,111,115,105,116,105,111,110,93,93,59,10,125,
59,10,10,115,116,114,117,99,116,32,109,97,105,110,48,95,105,110,10,123,10,32,32,32,32,102,108,111,97,116,50,32,97,80,111,115,32,91,91,97,116,116,114,105,98,117,116,101,40,48,41,93,
93,59,10,32,32,32,32,102,108,111,97,116,50,32,97,85,86,32,91,91,97,116,116,114,105,98,117,116,101,40,49,41,93,93,59,10,32,32,32,32,102,108,111,97,116,52,32,97,67,111,108,111,114,32,
91,91,97,116,116,114,105,98,117,116,101,40,50,41,93,93,59,10,125,59,10,10,118,101,114,116,101,120,32,109,97,105,110,48,95,111,117,116,32,109,97,105,110,48,40,109,97,105,110,48,95,105,
110,32,105,110,32,91,91,115,116,97,103,101,95,105,110,93,93,44,32,99,111,110,115,116,97,110,116,32,85,66,79,38,32,117,98,111,32,91,91,98,117,102,102,101,114,40,48,41,93,93,41,10,123,
10,32,32,32,32,109,97,105,110,48,95,111,117,116,32,111,117,116,32,61,32,123,125,59,10,32,32,32,32,95,57,32,79,117,116,32,61,32,123,125,59,10,32,32,32,32,79,117,116,46,67,111,108,111,
114,32,61,32,105,110,46,97,67,111,108,111,114,59,10,32,32,32,32,79,117,116,46,85,86,32,61,32,105,110,46,97,85,86,59,10,32,32,32,32,111,117,116,46,103,108,95,80,111,115,105,116,105,
111,110,32,61,32,102,108,111,97,116,52,40,40,105,110,46,97,80,111,115,32,42,32,117,98,111,46,117,83,99,97,108,101,41,32,43,32,117,98,111,46,117,84,114,97,110,115,108,97,116,101,44,
32,48,46,48,44,32,49,46,48,41,59,10,32,32,32,32,111,117,116,46,103,108,95,80,111,115,105,116,105,111,110,46,121,32,42,61,32,40,45,49,46,48,41,59,10,32,32,32,32,111,117,116,46,79,117,
116,95,67,111,108,111,114,32,61,32,79,117,116,46,67,111,108,111,114,59,10,32,32,32,32,111,117,116,46,79,117,116,95,85,86,32,61,32,79,117,116,46,85,86,59,10,32,32,32,32,114,101,116,
117,114,110,32,111,117,116,59,10,125,10,10,
};
static uint8_t msl_fragment[580] =
{
35,105,110,99,108,117,100,101,32,60,109,101,116,97,108,95,115,116,100,108,105,98,62,10,35,105,110,99,108,117,100,101,32,60,115,105,109,100,47,115,105,109,100,46,104,62,10,10,117,115,
105,110,103,32,110,97,109,101,115,112,97,99,101,32,109,101,116,97,108,59,10,10,115,116,114,117,99,116,32,95,49,49,10,123,10,32,32,32,32,102,108,111,97,116,52,32,67,111,108,111,114,
59,10,32,32,32,32,102,108,111,97,116,50,32,85,86,59,10,125,59,10,10,115,116,114,117,99,116,32,109,97,105,110,48,95,111,117,116,10,123,10,32,32,32,32,102,108,111,97,116,52,32,102,67,
111,108,111,114,32,91,91,99,111,108,111,114,40,48,41,93,93,59,10,125,59,10,10,115,116,114,117,99,116,32,109,97,105,110,48,95,105,110,10,123,10,32,32,32,32,102,108,111,97,116,52,32,
73,110,95,67,111,108,111,114,32,91,91,117,115,101,114,40,108,111,99,110,48,41,93,93,59,10,32,32,32,32,102,108,111,97,116,50,32,73,110,95,85,86,32,91,91,117,115,101,114,40,108,111,99,
110,49,41,93,93,59,10,125,59,10,10,102,114,97,103,109,101,110,116,32,109,97,105,110,48,95,111,117,116,32,109,97,105,110,48,40,109,97,105,110,48,95,105,110,32,105,110,32,91,91,115,116,
97,103,101,95,105,110,93,93,44,32,116,101,120,116,117,114,101,50,100,60,102,108,111,97,116,62,32,115,84,101,120,116,117,114,101,32,91,91,116,101,120,116,117,114,101,40,48,41,93,93,
44,32,115,97,109,112,108,101,114,32,115,84,101,120,116,117,114,101,83,109,112,108,114,32,91,91,115,97,109,112,108,101,114,40,48,41,93,93,41,10,123,10,32,32,32,32,109,97,105,110,48,
95,111,117,116,32,111,117,116,32,61,32,123,125,59,10,32,32,32,32,95,49,49,32,73,110,32,61,32,123,125,59,10,32,32,32,32,73,110,46,67,111,108,111,114,32,61,32,105,110,46,73,110,95,67,
111,108,111,114,59,10,32,32,32,32,73,110,46,85,86,32,61,32,105,110,46,73,110,95,85,86,59,10,32,32,32,32,111,117,116,46,102,67,111,108,111,114,32,61,32,73,110,46,67,111,108,111,114,
32,42,32,115,84,101,120,116,117,114,101,46,115,97,109,112,108,101,40,115,84,101,120,116,117,114,101,83,109,112,108,114,44,32,73,110,46,85,86,41,59,10,32,32,32,32,114,101,116,117,114,
110,32,111,117,116,59,10,125,10,10,
};
#elif TARGET_OS_IPHONE
const uint8_t metallib_vertex[3876] = {
77,84,76,66,1,0,2,0,7,0,0,130,18,0,1,0,36,15,0,0,0,0,0,0,88,0,0,0,0,0,0,0,123,0,0,0,0,0,0,0,219,0,0,0,0,0,0,0,49,0,0,0,0,0,0,0,12,1,0,0,0,0,0,0,8,0,0,0,0,0,0,0,20,1,0,0,0,0,0,0,16,

View File

@@ -24,6 +24,7 @@
// - Introduction, links and more at the top of imgui.cpp
// CHANGELOG
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
// 2025-06-11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplSDLRenderer2_CreateFontsTexture() and ImGui_ImplSDLRenderer2_DestroyFontsTexture().
// 2025-01-18: Use endian-dependent RGBA32 texture format, to match SDL_Color.
// 2024-10-09: Expose selected render state in ImGui_ImplSDLRenderer2_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
@@ -94,12 +95,14 @@ void ImGui_ImplSDLRenderer2_Shutdown()
ImGui_ImplSDLRenderer2_Data* bd = ImGui_ImplSDLRenderer2_GetBackendData();
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
ImGui_ImplSDLRenderer2_DestroyDeviceObjects();
io.BackendRendererName = nullptr;
io.BackendRendererUserData = nullptr;
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
platform_io.ClearRendererHandlers();
IM_DELETE(bd);
}
@@ -169,9 +172,8 @@ void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
ImVec2 clip_scale = render_scale;
// Render command lists
for (int n = 0; n < draw_data->CmdListsCount; n++)
for (const ImDrawList* draw_list : draw_data->CmdLists)
{
const ImDrawList* draw_list = draw_data->CmdLists[n];
const ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data;
const ImDrawIdx* idx_buffer = draw_list->IdxBuffer.Data;
@@ -265,10 +267,8 @@ void ImGui_ImplSDLRenderer2_UpdateTexture(ImTextureData* tex)
}
else if (tex->Status == ImTextureStatus_WantDestroy)
{
SDL_Texture* sdl_texture = (SDL_Texture*)(intptr_t)tex->TexID;
if (sdl_texture == nullptr)
return;
SDL_DestroyTexture(sdl_texture);
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);

View File

@@ -39,7 +39,7 @@ IMGUI_IMPL_API void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_d
IMGUI_IMPL_API void ImGui_ImplSDLRenderer2_CreateDeviceObjects();
IMGUI_IMPL_API void ImGui_ImplSDLRenderer2_DestroyDeviceObjects();
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
// (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_ImplSDLRenderer2_UpdateTexture(ImTextureData* tex);
// [BETA] Selected render state data shared with callbacks.

View File

@@ -24,6 +24,7 @@
// - Introduction, links and more at the top of imgui.cpp
// CHANGELOG
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
// 2025-06-11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplSDLRenderer3_CreateFontsTexture() and ImGui_ImplSDLRenderer3_DestroyFontsTexture().
// 2025-01-18: Use endian-dependent RGBA32 texture format, to match SDL_Color.
// 2024-10-09: Expose selected render state in ImGui_ImplSDLRenderer3_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
@@ -92,12 +93,14 @@ void ImGui_ImplSDLRenderer3_Shutdown()
ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData();
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
ImGui_ImplSDLRenderer3_DestroyDeviceObjects();
io.BackendRendererName = nullptr;
io.BackendRendererUserData = nullptr;
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
platform_io.ClearRendererHandlers();
IM_DELETE(bd);
}
@@ -189,9 +192,8 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
ImVec2 clip_scale = render_scale;
// Render command lists
for (int n = 0; n < draw_data->CmdListsCount; n++)
for (const ImDrawList* draw_list : draw_data->CmdLists)
{
const ImDrawList* draw_list = draw_data->CmdLists[n];
const ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data;
const ImDrawIdx* idx_buffer = draw_list->IdxBuffer.Data;
@@ -281,10 +283,8 @@ void ImGui_ImplSDLRenderer3_UpdateTexture(ImTextureData* tex)
}
else if (tex->Status == ImTextureStatus_WantDestroy)
{
SDL_Texture* sdl_texture = (SDL_Texture*)(intptr_t)tex->TexID;
if (sdl_texture == nullptr)
return;
SDL_DestroyTexture(sdl_texture);
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);

View File

@@ -39,7 +39,7 @@ IMGUI_IMPL_API void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_d
IMGUI_IMPL_API void ImGui_ImplSDLRenderer3_CreateDeviceObjects();
IMGUI_IMPL_API void ImGui_ImplSDLRenderer3_DestroyDeviceObjects();
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
// (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_ImplSDLRenderer3_UpdateTexture(ImTextureData* tex);
// [BETA] Selected render state data shared with callbacks.

View File

@@ -27,6 +27,17 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 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)
// 2025-11-24: [Helpers] Vulkan: Helper for creating a swap-chain (used by examples and multi-viewports) selects VkSwapchainCreateInfoKHR's compositeAlpha based on cap.supportedCompositeAlpha. (#8784)
// 2025-10-15: Vulkan: Added IMGUI_IMPL_VULKAN_VOLK_FILENAME to configure path to volk.h header. (#9008)
// 2025-09-26: *BREAKING CHANGE*: moved some fields in ImGui_ImplVulkan_InitInfo: init_info.RenderPass --> init_info.PipelineInfoMain.RenderPass, init_info.Subpass --> init_info.PipelineInfoMain.Subpass, init_info.MSAASamples --> init_info.PipelineInfoMain.MSAASamples, init_info.PipelineRenderingCreateInfo --> init_info.PipelineInfoMain.PipelineRenderingCreateInfo.
// 2025-09-26: *BREAKING CHANGE*: renamed ImGui_ImplVulkan_MainPipelineCreateInfo to ImGui_ImplVulkan_PipelineInfo. Introduced very recently so shouldn't affect many users.
// 2025-09-26: [Helpers] *BREAKING CHANGE*: Helper ImGui_ImplVulkanH_CreateOrResizeWindow() added a VkImageUsageFlags image_usage` argument, default to VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT if 0.
// 2025-09-26: Vulkan: Added a way to customize shaders by filling ImGui_ImplVulkan_InitInfo::CustomShaderVertCreateInfo/CustomShaderFragCreateInfo. (#8585)
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
// 2025-09-04: Vulkan: Added ImGui_ImplVulkan_CreateMainPipeline(). (#8110, #8111)
// 2025-07-27: Vulkan: Fixed texture update corruption introduced on 2025-06-11. (#8801, #8755, #8840)
// 2025-07-07: Vulkan: Fixed texture synchronization issue introduced on 2025-06-11. (#8772)
// 2025-06-27: Vulkan: Fixed validation errors during texture upload/update by aligning upload size to 'nonCoherentAtomSize'. (#8743, #8744)
// 2025-06-11: Vulkan: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplVulkan_CreateFontsTexture() and ImGui_ImplVulkan_DestroyFontsTexture().
@@ -36,8 +47,8 @@
// 2025-02-14: *BREAKING CHANGE*: Added uint32_t api_version to ImGui_ImplVulkan_LoadFunctions().
// 2025-02-13: Vulkan: Added ApiVersion field in ImGui_ImplVulkan_InitInfo. Default to header version if unspecified. Dynamic rendering path loads "vkCmdBeginRendering/vkCmdEndRendering" (without -KHR suffix) on API 1.3. (#8326)
// 2025-01-09: Vulkan: Added IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE to clarify how many image sampler descriptors are expected to be available in descriptor pool. (#6642)
// 2025-01-06: Vulkan: Added more ImGui_ImplVulkanH_XXXX helper functions to simplify our examples.
// 2024-12-11: Vulkan: Fixed setting VkSwapchainCreateInfoKHR::preTransform for platforms not supporting VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR. (#8222)
// 2025-01-06: [Helpers] Vulkan: Added more ImGui_ImplVulkanH_XXXX helper functions to simplify our examples.
// 2024-12-11: [Helpers] Vulkan: Fixed setting VkSwapchainCreateInfoKHR::preTransform for platforms not supporting VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR. (#8222)
// 2024-11-27: Vulkan: Make user-provided descriptor pool optional. As a convenience, when setting init_info->DescriptorPoolSize the backend will create one itself. (#8172, #4867)
// 2024-10-07: Vulkan: Changed default texture sampler to Clamp instead of Repeat/Wrap.
// 2024-10-07: Vulkan: Expose selected render state in ImGui_ImplVulkan_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
@@ -45,7 +56,7 @@
// 2024-04-19: Vulkan: Added convenience support for Volk via IMGUI_IMPL_VULKAN_USE_VOLK define (you can also use IMGUI_IMPL_VULKAN_NO_PROTOTYPES + wrap Volk via ImGui_ImplVulkan_LoadFunctions().)
// 2024-02-14: *BREAKING CHANGE*: Moved RenderPass parameter from ImGui_ImplVulkan_Init() function to ImGui_ImplVulkan_InitInfo structure. Not required when using dynamic rendering.
// 2024-02-12: *BREAKING CHANGE*: Dynamic rendering now require filling PipelineRenderingCreateInfo structure.
// 2024-01-19: Vulkan: Fixed vkAcquireNextImageKHR() validation errors in VulkanSDK 1.3.275 by allocating one extra semaphore than in-flight frames. (#7236)
// 2024-01-19: [Helpers] Vulkan: Fixed vkAcquireNextImageKHR() validation errors in VulkanSDK 1.3.275 by allocating one extra semaphore than in-flight frames. (#7236)
// 2024-01-11: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size (#3957). Fixed MinAllocationSize handing (#7189).
// 2024-01-03: Vulkan: Added MinAllocationSize field in ImGui_ImplVulkan_InitInfo to workaround zealous "best practice" validation layer. (#7189, #4238)
// 2024-01-03: Vulkan: Stopped creating command pools with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT as we don't reset them.
@@ -73,16 +84,16 @@
// 2019-05-29: Vulkan: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
// 2019-04-30: Vulkan: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
// 2019-04-04: *BREAKING CHANGE*: Vulkan: Added ImageCount/MinImageCount fields in ImGui_ImplVulkan_InitInfo, required for initialization (was previously a hard #define IMGUI_VK_QUEUED_FRAMES 2). Added ImGui_ImplVulkan_SetMinImageCount().
// 2019-04-04: Vulkan: Added VkInstance argument to ImGui_ImplVulkanH_CreateWindow() optional helper.
// 2019-04-04: [Helpers] Vulkan: Added VkInstance argument to ImGui_ImplVulkanH_CreateWindow() optional helper.
// 2019-04-04: Vulkan: Avoid passing negative coordinates to vkCmdSetScissor, which debug validation layers do not like.
// 2019-04-01: Vulkan: Support for 32-bit index buffer (#define ImDrawIdx unsigned int).
// 2019-02-16: Vulkan: Viewport and clipping rectangles correctly using draw_data->FramebufferScale to allow retina display.
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
// 2018-08-25: Vulkan: Fixed mishandled VkSurfaceCapabilitiesKHR::maxImageCount=0 case.
// 2018-08-25: [Helpers] Vulkan: Fixed mishandled VkSurfaceCapabilitiesKHR::maxImageCount=0 case.
// 2018-06-22: Inverted the parameters to ImGui_ImplVulkan_RenderDrawData() to be consistent with other backends.
// 2018-06-08: Misc: Extracted imgui_impl_vulkan.cpp/.h away from the old combined GLFW+Vulkan example.
// 2018-06-08: Vulkan: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
// 2018-03-03: Vulkan: Various refactor, created a couple of ImGui_ImplVulkanH_XXX helper that the example can use and that viewport support will use.
// 2018-03-03: [Helpers] Vulkan: Various refactor, created a couple of ImGui_ImplVulkanH_XXX helper that the example can use and that viewport support will use.
// 2018-03-01: Vulkan: Renamed ImGui_ImplVulkan_Init_Info to ImGui_ImplVulkan_InitInfo and fields to match more closely Vulkan terminology.
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback, ImGui_ImplVulkan_Render() calls ImGui_ImplVulkan_RenderDrawData() itself.
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
@@ -105,6 +116,14 @@
#pragma warning (disable: 4127) // condition expression is constant
#endif
// Clang/GCC warnings with -Weverything
#if defined(__clang__)
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision
#pragma clang diagnostic ignored "-Wcast-function-type" // warning: cast between incompatible function types (for loader)
#endif
// Forward Declarations
struct ImGui_ImplVulkan_FrameRenderBuffers;
struct ImGui_ImplVulkan_WindowRenderBuffers;
@@ -114,11 +133,11 @@ void ImGui_ImplVulkan_DestroyFrameRenderBuffers(VkDevice device, ImGui_ImplVulka
void ImGui_ImplVulkan_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulkan_WindowRenderBuffers* buffers, const VkAllocationCallbacks* allocator);
void ImGui_ImplVulkanH_DestroyFrame(VkDevice device, ImGui_ImplVulkanH_Frame* fd, const VkAllocationCallbacks* allocator);
void ImGui_ImplVulkanH_DestroyFrameSemaphores(VkDevice device, ImGui_ImplVulkanH_FrameSemaphores* fsd, const VkAllocationCallbacks* allocator);
void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count);
void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count, VkImageUsageFlags image_usage);
void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator);
// Vulkan prototypes for use with custom loaders
// (see description of IMGUI_IMPL_VULKAN_NO_PROTOTYPES in imgui_impl_vulkan.h
// (see description of IMGUI_IMPL_VULKAN_NO_PROTOTYPES in imgui_impl_vulkan.h)
#if defined(VK_NO_PROTOTYPES) && !defined(VOLK_H_)
#define IMGUI_IMPL_VULKAN_USE_LOADER
static bool g_FunctionsLoaded = false;
@@ -251,13 +270,14 @@ struct ImGui_ImplVulkan_Data
VkPipelineCreateFlags PipelineCreateFlags;
VkDescriptorSetLayout DescriptorSetLayout;
VkPipelineLayout PipelineLayout;
VkPipeline Pipeline;
VkPipeline Pipeline; // pipeline for main render pass (created by app)
VkShaderModule ShaderModuleVert;
VkShaderModule ShaderModuleFrag;
VkDescriptorPool DescriptorPool;
ImVector<VkFormat> PipelineRenderingCreateInfoColorAttachmentFormats; // Deep copy of format array
// Texture management
VkSampler TexSampler;
VkSampler TexSamplerLinear;
VkCommandPool TexCommandPool;
VkCommandBuffer TexCommandBuffer;
@@ -550,9 +570,8 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
check_vk_result(err);
err = vkMapMemory(v->Device, rb->IndexBufferMemory, 0, index_size, 0, (void**)&idx_dst);
check_vk_result(err);
for (int n = 0; n < draw_data->CmdListsCount; n++)
for (const ImDrawList* draw_list : draw_data->CmdLists)
{
const ImDrawList* draw_list = draw_data->CmdLists[n];
memcpy(vtx_dst, draw_list->VtxBuffer.Data, draw_list->VtxBuffer.Size * sizeof(ImDrawVert));
memcpy(idx_dst, draw_list->IdxBuffer.Data, draw_list->IdxBuffer.Size * sizeof(ImDrawIdx));
vtx_dst += draw_list->VtxBuffer.Size;
@@ -588,11 +607,11 @@ 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;
int global_vtx_offset = 0;
int global_idx_offset = 0;
for (int n = 0; n < draw_data->CmdListsCount; n++)
for (const ImDrawList* draw_list : draw_data->CmdLists)
{
const ImDrawList* draw_list = draw_data->CmdLists[n];
for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
{
const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
@@ -604,6 +623,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
ImGui_ImplVulkan_SetupRenderState(draw_data, pipeline, command_buffer, rb, fb_width, fb_height);
else
pcmd->UserCallback(draw_list, pcmd);
last_desc_set = VK_NULL_HANDLE;
}
else
{
@@ -629,7 +649,9 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
// Bind DescriptorSet with font or user texture
VkDescriptorSet desc_set = (VkDescriptorSet)pcmd->GetTexID();
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 0, 1, &desc_set, 0, nullptr);
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;
// Draw
vkCmdDrawIndexed(command_buffer, pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
@@ -653,22 +675,22 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
static void ImGui_ImplVulkan_DestroyTexture(ImTextureData* tex)
{
ImGui_ImplVulkan_Texture* backend_tex = (ImGui_ImplVulkan_Texture*)tex->BackendUserData;
if (backend_tex == nullptr)
return;
IM_ASSERT(backend_tex->DescriptorSet == (VkDescriptorSet)tex->TexID);
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
ImGui_ImplVulkan_RemoveTexture(backend_tex->DescriptorSet);
vkDestroyImageView(v->Device, backend_tex->ImageView, v->Allocator);
vkDestroyImage(v->Device, backend_tex->Image, v->Allocator);
vkFreeMemory(v->Device, backend_tex->Memory, v->Allocator);
IM_DELETE(backend_tex);
if (ImGui_ImplVulkan_Texture* backend_tex = (ImGui_ImplVulkan_Texture*)tex->BackendUserData)
{
IM_ASSERT(backend_tex->DescriptorSet == (VkDescriptorSet)tex->TexID);
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
ImGui_ImplVulkan_RemoveTexture(backend_tex->DescriptorSet);
vkDestroyImageView(v->Device, backend_tex->ImageView, v->Allocator);
vkDestroyImage(v->Device, backend_tex->Image, v->Allocator);
vkFreeMemory(v->Device, backend_tex->Memory, v->Allocator);
IM_DELETE(backend_tex);
// 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->BackendUserData = nullptr;
}
tex->SetStatus(ImTextureStatus_Destroyed);
tex->BackendUserData = nullptr;
}
void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex)
@@ -732,7 +754,7 @@ void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex)
}
// Create the Descriptor Set
backend_tex->DescriptorSet = ImGui_ImplVulkan_AddTexture(bd->TexSampler, backend_tex->ImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
backend_tex->DescriptorSet = ImGui_ImplVulkan_AddTexture(bd->TexSamplerLinear, backend_tex->ImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
// Store identifiers
tex->SetTexID((ImTextureID)backend_tex->DescriptorSet);
@@ -820,7 +842,7 @@ void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex)
VkImageMemoryBarrier copy_barrier[1] = {};
copy_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
copy_barrier[0].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
copy_barrier[0].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
copy_barrier[0].oldLayout = (tex->Status == ImTextureStatus_WantCreate) ? VK_IMAGE_LAYOUT_UNDEFINED : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
copy_barrier[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
copy_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
copy_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
@@ -881,29 +903,35 @@ void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex)
static void ImGui_ImplVulkan_CreateShaderModules(VkDevice device, const VkAllocationCallbacks* allocator)
{
// Create the shader modules
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
if (bd->ShaderModuleVert == VK_NULL_HANDLE)
{
VkShaderModuleCreateInfo vert_info = {};
vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
vert_info.codeSize = sizeof(__glsl_shader_vert_spv);
vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv;
VkResult err = vkCreateShaderModule(device, &vert_info, allocator, &bd->ShaderModuleVert);
VkShaderModuleCreateInfo default_vert_info = {};
default_vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
default_vert_info.codeSize = sizeof(__glsl_shader_vert_spv);
default_vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv;
VkShaderModuleCreateInfo* p_vert_info = (v->CustomShaderVertCreateInfo.sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO) ? &v->CustomShaderVertCreateInfo : &default_vert_info;
VkResult err = vkCreateShaderModule(device, p_vert_info, allocator, &bd->ShaderModuleVert);
check_vk_result(err);
}
if (bd->ShaderModuleFrag == VK_NULL_HANDLE)
{
VkShaderModuleCreateInfo frag_info = {};
frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
frag_info.codeSize = sizeof(__glsl_shader_frag_spv);
frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv;
VkResult err = vkCreateShaderModule(device, &frag_info, allocator, &bd->ShaderModuleFrag);
VkShaderModuleCreateInfo default_frag_info = {};
default_frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
default_frag_info.codeSize = sizeof(__glsl_shader_frag_spv);
default_frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv;
VkShaderModuleCreateInfo* p_frag_info = (v->CustomShaderFragCreateInfo.sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO) ? &v->CustomShaderFragCreateInfo : &default_frag_info;
VkResult err = vkCreateShaderModule(device, p_frag_info, allocator, &bd->ShaderModuleFrag);
check_vk_result(err);
}
}
static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationCallbacks* allocator, VkPipelineCache pipelineCache, VkRenderPass renderPass, VkSampleCountFlagBits MSAASamples, VkPipeline* pipeline, uint32_t subpass)
#if !defined(IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING) && !(defined(VK_VERSION_1_3) || defined(VK_KHR_dynamic_rendering))
typedef void VkPipelineRenderingCreateInfoKHR;
#endif
static VkPipeline ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationCallbacks* allocator, VkPipelineCache pipelineCache, const ImGui_ImplVulkan_PipelineInfo* info)
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
ImGui_ImplVulkan_CreateShaderModules(device, allocator);
@@ -961,7 +989,7 @@ static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationC
VkPipelineMultisampleStateCreateInfo ms_info = {};
ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
ms_info.rasterizationSamples = (MSAASamples != 0) ? MSAASamples : VK_SAMPLE_COUNT_1_BIT;
ms_info.rasterizationSamples = (info->MSAASamples != 0) ? info->MSAASamples : VK_SAMPLE_COUNT_1_BIT;
VkPipelineColorBlendAttachmentState color_attachment[1] = {};
color_attachment[0].blendEnable = VK_TRUE;
@@ -984,38 +1012,39 @@ static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationC
VkDynamicState dynamic_states[2] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
VkPipelineDynamicStateCreateInfo dynamic_state = {};
dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamic_state.dynamicStateCount = (uint32_t)IM_ARRAYSIZE(dynamic_states);
dynamic_state.dynamicStateCount = (uint32_t)IM_COUNTOF(dynamic_states);
dynamic_state.pDynamicStates = dynamic_states;
VkGraphicsPipelineCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
info.flags = bd->PipelineCreateFlags;
info.stageCount = 2;
info.pStages = stage;
info.pVertexInputState = &vertex_info;
info.pInputAssemblyState = &ia_info;
info.pViewportState = &viewport_info;
info.pRasterizationState = &raster_info;
info.pMultisampleState = &ms_info;
info.pDepthStencilState = &depth_info;
info.pColorBlendState = &blend_info;
info.pDynamicState = &dynamic_state;
info.layout = bd->PipelineLayout;
info.renderPass = renderPass;
info.subpass = subpass;
VkGraphicsPipelineCreateInfo create_info = {};
create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
create_info.flags = bd->PipelineCreateFlags;
create_info.stageCount = 2;
create_info.pStages = stage;
create_info.pVertexInputState = &vertex_info;
create_info.pInputAssemblyState = &ia_info;
create_info.pViewportState = &viewport_info;
create_info.pRasterizationState = &raster_info;
create_info.pMultisampleState = &ms_info;
create_info.pDepthStencilState = &depth_info;
create_info.pColorBlendState = &blend_info;
create_info.pDynamicState = &dynamic_state;
create_info.layout = bd->PipelineLayout;
create_info.renderPass = info->RenderPass;
create_info.subpass = info->Subpass;
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
if (bd->VulkanInitInfo.UseDynamicRendering)
{
IM_ASSERT(bd->VulkanInitInfo.PipelineRenderingCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR && "PipelineRenderingCreateInfo sType must be VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR");
IM_ASSERT(bd->VulkanInitInfo.PipelineRenderingCreateInfo.pNext == nullptr && "PipelineRenderingCreateInfo pNext must be nullptr");
info.pNext = &bd->VulkanInitInfo.PipelineRenderingCreateInfo;
info.renderPass = VK_NULL_HANDLE; // Just make sure it's actually nullptr.
IM_ASSERT(info->PipelineRenderingCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR && "PipelineRenderingCreateInfo::sType must be VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR");
IM_ASSERT(info->PipelineRenderingCreateInfo.pNext == nullptr && "PipelineRenderingCreateInfo::pNext must be nullptr");
create_info.pNext = &info->PipelineRenderingCreateInfo;
create_info.renderPass = VK_NULL_HANDLE; // Just make sure it's actually nullptr.
}
#endif
VkResult err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &info, allocator, pipeline);
VkPipeline pipeline;
VkResult err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &create_info, allocator, &pipeline);
check_vk_result(err);
return pipeline;
}
bool ImGui_ImplVulkan_CreateDeviceObjects()
@@ -1024,7 +1053,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
VkResult err;
if (!bd->TexSampler)
if (!bd->TexSamplerLinear)
{
// Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
VkSamplerCreateInfo info = {};
@@ -1038,7 +1067,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
info.minLod = -1000;
info.maxLod = 1000;
info.maxAnisotropy = 1.0f;
err = vkCreateSampler(v->Device, &info, v->Allocator, &bd->TexSampler);
err = vkCreateSampler(v->Device, &info, v->Allocator, &bd->TexSamplerLinear);
check_vk_result(err);
}
@@ -1089,7 +1118,13 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
check_vk_result(err);
}
ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, v->PipelineCache, v->RenderPass, v->MSAASamples, &bd->Pipeline, v->Subpass);
// Create pipeline
bool create_main_pipeline = (v->PipelineInfoMain.RenderPass != VK_NULL_HANDLE);
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
create_main_pipeline |= (v->UseDynamicRendering && v->PipelineInfoMain.PipelineRenderingCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR);
#endif
if (create_main_pipeline)
ImGui_ImplVulkan_CreateMainPipeline(&v->PipelineInfoMain);
// Create command pool/buffer for texture upload
if (!bd->TexCommandPool)
@@ -1114,6 +1149,34 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
return true;
}
void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_PipelineInfo* pipeline_info_in)
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
if (bd->Pipeline)
{
vkDestroyPipeline(v->Device, bd->Pipeline, v->Allocator);
bd->Pipeline = VK_NULL_HANDLE;
}
ImGui_ImplVulkan_PipelineInfo* pipeline_info = &v->PipelineInfoMain;
if (pipeline_info != pipeline_info_in)
*pipeline_info = *pipeline_info_in;
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
VkPipelineRenderingCreateInfoKHR* pipeline_rendering_create_info = &pipeline_info->PipelineRenderingCreateInfo;
if (v->UseDynamicRendering && pipeline_rendering_create_info->pColorAttachmentFormats != nullptr)
{
// Deep copy buffer to reduce error-rate for end user (#8282)
ImVector<VkFormat> formats;
formats.resize((int)pipeline_rendering_create_info->colorAttachmentCount);
memcpy(formats.Data, pipeline_rendering_create_info->pColorAttachmentFormats, (size_t)formats.size_in_bytes());
formats.swap(bd->PipelineRenderingCreateInfoColorAttachmentFormats);
pipeline_rendering_create_info->pColorAttachmentFormats = bd->PipelineRenderingCreateInfoColorAttachmentFormats.Data;
}
#endif
bd->Pipeline = ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, v->PipelineCache, pipeline_info);
}
void ImGui_ImplVulkan_DestroyDeviceObjects()
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
@@ -1127,7 +1190,7 @@ 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->TexSampler) { vkDestroySampler(v->Device, bd->TexSampler, v->Allocator); bd->TexSampler = VK_NULL_HANDLE; }
if (bd->TexSamplerLinear) { vkDestroySampler(v->Device, bd->TexSamplerLinear, v->Allocator); bd->TexSamplerLinear = 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; }
@@ -1226,18 +1289,19 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info)
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
// Sanity checks
IM_ASSERT(info->Instance != VK_NULL_HANDLE);
IM_ASSERT(info->PhysicalDevice != VK_NULL_HANDLE);
IM_ASSERT(info->Device != VK_NULL_HANDLE);
IM_ASSERT(info->Queue != VK_NULL_HANDLE);
IM_ASSERT(info->MinImageCount >= 2);
IM_ASSERT(info->ImageCount >= info->MinImageCount);
if (info->DescriptorPool != VK_NULL_HANDLE) // Either DescriptorPool or DescriptorPoolSize must be set, not both!
IM_ASSERT(info->DescriptorPoolSize == 0);
else
IM_ASSERT(info->DescriptorPoolSize > 0);
IM_ASSERT(info->MinImageCount >= 2);
IM_ASSERT(info->ImageCount >= info->MinImageCount);
if (info->UseDynamicRendering == false)
IM_ASSERT(info->RenderPass != VK_NULL_HANDLE);
if (info->UseDynamicRendering)
IM_ASSERT(info->PipelineInfoMain.RenderPass == VK_NULL_HANDLE);
bd->VulkanInitInfo = *info;
@@ -1245,17 +1309,6 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info)
vkGetPhysicalDeviceProperties(info->PhysicalDevice, &properties);
bd->NonCoherentAtomSize = properties.limits.nonCoherentAtomSize;
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
if (v->PipelineRenderingCreateInfo.pColorAttachmentFormats != NULL)
{
// Deep copy buffer to reduce error-rate for end user (#8282)
VkFormat* formats_copy = (VkFormat*)IM_ALLOC(sizeof(VkFormat) * v->PipelineRenderingCreateInfo.colorAttachmentCount);
memcpy(formats_copy, v->PipelineRenderingCreateInfo.pColorAttachmentFormats, sizeof(VkFormat) * v->PipelineRenderingCreateInfo.colorAttachmentCount);
v->PipelineRenderingCreateInfo.pColorAttachmentFormats = formats_copy;
}
#endif
if (!ImGui_ImplVulkan_CreateDeviceObjects())
IM_ASSERT(0 && "ImGui_ImplVulkan_CreateDeviceObjects() failed!"); // <- Can't be hit yet.
@@ -1267,15 +1320,14 @@ void ImGui_ImplVulkan_Shutdown()
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
ImGui_ImplVulkan_DestroyDeviceObjects();
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
IM_FREE((void*)const_cast<VkFormat*>(bd->VulkanInitInfo.PipelineRenderingCreateInfo.pColorAttachmentFormats));
#endif
io.BackendRendererName = nullptr;
io.BackendRendererUserData = nullptr;
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
platform_io.ClearRendererHandlers();
IM_DELETE(bd);
}
@@ -1366,7 +1418,7 @@ void ImGui_ImplVulkan_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulk
//-------------------------------------------------------------------------
// Internal / Miscellaneous Vulkan Helpers
// (Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own app.)
// (Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own engine/app.)
//-------------------------------------------------------------------------
// You probably do NOT need to use or care about those functions.
// Those functions only exist because:
@@ -1376,7 +1428,7 @@ void ImGui_ImplVulkan_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulk
// but it is too much code to duplicate everywhere so we exceptionally expose them.
//
// Your engine/app will likely _already_ have code to setup all that stuff (swap chain, render pass, frame buffers, etc.).
// You may read this code to learn about Vulkan, but it is recommended you use you own custom tailored code to do equivalent work.
// You may read this code to learn about Vulkan, but it is recommended you use your own custom tailored code to do equivalent work.
// (The ImGui_ImplVulkanH_XXX functions do not interact with any of the state used by the regular ImGui_ImplVulkan_XXX functions)
//-------------------------------------------------------------------------
@@ -1554,7 +1606,7 @@ int ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(VkPresentModeKHR present_m
}
// Also destroy old swap chain and in-flight frames data, if any.
void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count)
void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count, VkImageUsageFlags image_usage)
{
VkResult err;
VkSwapchainKHR old_swapchain = wd->Swapchain;
@@ -1593,10 +1645,15 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
info.imageFormat = wd->SurfaceFormat.format;
info.imageColorSpace = wd->SurfaceFormat.colorSpace;
info.imageArrayLayers = 1;
info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | image_usage;
info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; // Assume that graphics family == present family
info.preTransform = (cap.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : cap.currentTransform;
info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
if (cap.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR)
info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
else if (cap.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR)
info.compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
else
IM_ASSERT(false && "No supported composite alpha mode found!");
info.presentMode = wd->PresentMode;
info.clipped = VK_TRUE;
info.oldSwapchain = old_swapchain;
@@ -1620,7 +1677,7 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
check_vk_result(err);
VkImage backbuffers[16] = {};
IM_ASSERT(wd->ImageCount >= min_image_count);
IM_ASSERT(wd->ImageCount < IM_ARRAYSIZE(backbuffers));
IM_ASSERT(wd->ImageCount < IM_COUNTOF(backbuffers));
err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, backbuffers);
check_vk_result(err);
@@ -1638,15 +1695,9 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
// Create the Render Pass
if (wd->UseDynamicRendering == false)
{
VkAttachmentDescription attachment = {};
attachment.format = wd->SurfaceFormat.format;
attachment.samples = VK_SAMPLE_COUNT_1_BIT;
attachment.loadOp = wd->ClearEnable ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
VkAttachmentDescription attachment = wd->AttachmentDesc;
if (attachment.format == VK_FORMAT_UNDEFINED)
attachment.format = wd->SurfaceFormat.format;
VkAttachmentReference color_attachment = {};
color_attachment.attachment = 0;
color_attachment.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
@@ -1721,11 +1772,14 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
}
// Create or resize window
void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int width, int height, uint32_t min_image_count)
// - 2025/09/26: v1.92.4 added a trailing 'VkImageUsageFlags image_usage' parameter which is usually VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT.
void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int width, int height, uint32_t min_image_count, VkImageUsageFlags image_usage)
{
IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!");
(void)instance;
ImGui_ImplVulkanH_CreateWindowSwapChain(physical_device, device, wd, allocator, width, height, min_image_count);
IM_ASSERT(wd->Surface != VK_NULL_HANDLE);
IM_UNUSED(instance);
ImGui_ImplVulkanH_CreateWindowSwapChain(physical_device, device, wd, allocator, width, height, min_image_count, image_usage);
ImGui_ImplVulkanH_CreateWindowCommandBuffers(physical_device, device, wd, queue_family, allocator);
// FIXME: to submit the command buffer, we need a queue. In the examples folder, the ImGui_ImplVulkanH_CreateOrResizeWindow function is called
@@ -1807,6 +1861,7 @@ void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevic
void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator)
{
IM_UNUSED(instance);
vkDeviceWaitIdle(device); // FIXME: We could wait on the Queue if we had the queue in wd-> (otherwise VulkanH functions can't use globals)
//vkQueueWaitIdle(bd->Queue);
@@ -1819,9 +1874,11 @@ void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui
vkDestroyPipeline(device, wd->Pipeline, allocator);
vkDestroyRenderPass(device, wd->RenderPass, allocator);
vkDestroySwapchainKHR(device, wd->Swapchain, allocator);
vkDestroySurfaceKHR(instance, wd->Surface, allocator);
*wd = ImGui_ImplVulkanH_Window();
wd->RenderPass = VK_NULL_HANDLE;
wd->Swapchain = VK_NULL_HANDLE;
wd->Width = wd->Height = 0;
wd->FrameIndex = wd->ImageCount = wd->SemaphoreCount = wd->SemaphoreIndex = 0;
//vkDestroySurfaceKHR(instance, wd->Surface, allocator); // v1.92.6 (~2026-01-16): because wd->Surface is user provided we don't attempt to destroy it ourself.
}
void ImGui_ImplVulkanH_DestroyFrame(VkDevice device, ImGui_ImplVulkanH_Frame* fd, const VkAllocationCallbacks* allocator)

View File

@@ -41,9 +41,20 @@
// If you have no idea what this is, leave it alone!
//#define IMGUI_IMPL_VULKAN_NO_PROTOTYPES
// Convenience support for Volk
// [Configuration] Convenience support for Volk
// (you can also technically use IMGUI_IMPL_VULKAN_NO_PROTOTYPES + wrap Volk via ImGui_ImplVulkan_LoadFunctions().)
// (When using Volk from directory outside your include directories list you can specify full path to the volk.h header,
// for example when using Volk from VulkanSDK and using include_directories(${Vulkan_INCLUDE_DIRS})' from 'find_package(Vulkan REQUIRED)')
//#define IMGUI_IMPL_VULKAN_USE_VOLK
//#define IMGUI_IMPL_VULKAN_VOLK_FILENAME <Volk/volk.h>
//#define IMGUI_IMPL_VULKAN_VOLK_FILENAME <volk.h> // Default
// Reminder: make those changes in your imconfig.h file, not here!
// Clang/GCC warnings with -Weverything
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast
#endif
#if defined(IMGUI_IMPL_VULKAN_NO_PROTOTYPES) && !defined(VK_NO_PROTOTYPES)
#define VK_NO_PROTOTYPES
@@ -54,7 +65,11 @@
// Vulkan includes
#ifdef IMGUI_IMPL_VULKAN_USE_VOLK
#ifdef IMGUI_IMPL_VULKAN_VOLK_FILENAME
#include IMGUI_IMPL_VULKAN_VOLK_FILENAME
#else
#include <volk.h>
#endif
#else
#include <vulkan/vulkan.h>
#endif
@@ -65,6 +80,17 @@
// Backend uses a small number of descriptors per font atlas + as many as additional calls done to ImGui_ImplVulkan_AddTexture().
#define IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE (8) // Minimum per atlas
// Specify settings to create pipeline and swapchain
struct ImGui_ImplVulkan_PipelineInfo
{
VkRenderPass RenderPass; // Ignored if using dynamic rendering
uint32_t Subpass; //
VkSampleCountFlagBits MSAASamples = {}; // 0 defaults to VK_SAMPLE_COUNT_1_BIT
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; // Optional, valid if .sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR
#endif
};
// Initialization data, for ImGui_ImplVulkan_Init()
// [Please zero-clear before use!]
// - About descriptor pool:
@@ -72,7 +98,7 @@
// and must contain a pool size large enough to hold a small number of VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptors.
// - As an convenience, by setting DescriptorPoolSize > 0 the backend will create one for you.
// - About dynamic rendering:
// - When using dynamic rendering, set UseDynamicRendering=true and fill PipelineRenderingCreateInfo structure.
// - When using dynamic rendering, set UseDynamicRendering=true + fill PipelineInfoMain.PipelineRenderingCreateInfo structure.
struct ImGui_ImplVulkan_InitInfo
{
uint32_t ApiVersion; // Fill with API version of Instance, e.g. VK_API_VERSION_1_3 or your value of VkApplicationInfo::apiVersion. May be lower than header version (VK_HEADER_VERSION_COMPLETE)
@@ -82,29 +108,32 @@ struct ImGui_ImplVulkan_InitInfo
uint32_t QueueFamily;
VkQueue Queue;
VkDescriptorPool DescriptorPool; // See requirements in note above; ignored if using DescriptorPoolSize > 0
VkRenderPass RenderPass; // Ignored if using dynamic rendering
uint32_t DescriptorPoolSize; // Optional: set to create internal descriptor pool automatically instead of using DescriptorPool.
uint32_t MinImageCount; // >= 2
uint32_t ImageCount; // >= MinImageCount
VkSampleCountFlagBits MSAASamples; // 0 defaults to VK_SAMPLE_COUNT_1_BIT
VkPipelineCache PipelineCache; // Optional
// (Optional)
VkPipelineCache PipelineCache;
uint32_t Subpass;
// (Optional) Set to create internal descriptor pool instead of using DescriptorPool
uint32_t DescriptorPoolSize;
// Pipeline
ImGui_ImplVulkan_PipelineInfo PipelineInfoMain; // Infos for Main Viewport (created by app/user)
//VkRenderPass RenderPass; // --> Since 2025/09/26: set 'PipelineInfoMain.RenderPass' instead
//uint32_t Subpass; // --> Since 2025/09/26: set 'PipelineInfoMain.Subpass' instead
//VkSampleCountFlagBits MSAASamples; // --> Since 2025/09/26: set 'PipelineInfoMain.MSAASamples' instead
//VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; // Since 2025/09/26: set 'PipelineInfoMain.PipelineRenderingCreateInfo' instead
// (Optional) Dynamic Rendering
// Need to explicitly enable VK_KHR_dynamic_rendering extension to use this, even for Vulkan 1.3.
// Need to explicitly enable VK_KHR_dynamic_rendering extension to use this, even for Vulkan 1.3 + setup PipelineInfoMain.PipelineRenderingCreateInfo.
bool UseDynamicRendering;
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo;
#endif
// (Optional) Allocation, Debugging
const VkAllocationCallbacks* Allocator;
void (*CheckVkResultFn)(VkResult err);
VkDeviceSize MinAllocationSize; // Minimum allocation size. Set to 1024*1024 to satisfy zealous best practices validation layer and waste a little memory.
// (Optional) Customize default vertex/fragment shaders.
// - if .sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO we use specified structs, otherwise we use defaults.
// - Shader inputs/outputs need to match ours. Code/data pointed to by the structure needs to survive for whole during of backend usage.
VkShaderModuleCreateInfo CustomShaderVertCreateInfo;
VkShaderModuleCreateInfo CustomShaderFragCreateInfo;
};
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
@@ -114,7 +143,12 @@ IMGUI_IMPL_API void ImGui_ImplVulkan_NewFrame();
IMGUI_IMPL_API void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline = VK_NULL_HANDLE);
IMGUI_IMPL_API void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated)
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
// (Advanced) Use e.g. if you need to recreate pipeline without reinitializing the backend (see #8110, #8111)
// The main window pipeline will be created by ImGui_ImplVulkan_Init() if possible (== RenderPass xor (UseDynamicRendering && PipelineRenderingCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR))
// Else, the pipeline can be created, or re-created, using ImGui_ImplVulkan_CreateMainPipeline() before rendering.
IMGUI_IMPL_API void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_PipelineInfo* info);
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
IMGUI_IMPL_API void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex);
// Register a texture (VkDescriptorSet == ImTextureID)
@@ -143,6 +177,7 @@ struct ImGui_ImplVulkan_RenderState
// Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own engine/app.
//
// You probably do NOT need to use or care about those functions.
// WE DO NOT PROVIDE STRONG GUARANTEES OF BACKWARD/FORWARD COMPATIBILITY.
// Those functions only exist because:
// 1) they facilitate the readability and maintenance of the multiple main.cpp examples files.
// 2) the multi-viewport / platform window implementation needs them internally.
@@ -151,20 +186,18 @@ struct ImGui_ImplVulkan_RenderState
//
// Your engine/app will likely _already_ have code to setup all that stuff (swap chain,
// render pass, frame buffers, etc.). You may read this code if you are curious, but
// it is recommended you use you own custom tailored code to do equivalent work.
//
// We don't provide a strong guarantee that we won't change those functions API.
// it is recommended you use your own custom tailored code to do equivalent work.
//
// The ImGui_ImplVulkanH_XXX functions should NOT interact with any of the state used
// by the regular ImGui_ImplVulkan_XXX functions).
// by the regular ImGui_ImplVulkan_XXX functions.
//-------------------------------------------------------------------------
struct ImGui_ImplVulkanH_Frame;
struct ImGui_ImplVulkanH_Window;
// Helpers
IMGUI_IMPL_API void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wnd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count);
IMGUI_IMPL_API void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wnd, const VkAllocationCallbacks* allocator);
IMGUI_IMPL_API void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count, VkImageUsageFlags image_usage);
IMGUI_IMPL_API void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator);
IMGUI_IMPL_API VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space);
IMGUI_IMPL_API VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count);
IMGUI_IMPL_API VkPhysicalDevice ImGui_ImplVulkanH_SelectPhysicalDevice(VkInstance instance);
@@ -194,30 +227,48 @@ struct ImGui_ImplVulkanH_FrameSemaphores
// (Used by example's main.cpp. Used by multi-viewport features. Probably NOT used by your own engine/app.)
struct ImGui_ImplVulkanH_Window
{
int Width;
int Height;
VkSwapchainKHR Swapchain;
VkSurfaceKHR Surface;
VkSurfaceFormatKHR SurfaceFormat;
VkPresentModeKHR PresentMode;
VkRenderPass RenderPass;
VkPipeline Pipeline; // The window pipeline may uses a different VkRenderPass than the one passed in ImGui_ImplVulkan_InitInfo
bool UseDynamicRendering;
bool ClearEnable;
VkClearValue ClearValue;
uint32_t FrameIndex; // Current frame being rendered to (0 <= FrameIndex < FrameInFlightCount)
uint32_t ImageCount; // Number of simultaneous in-flight frames (returned by vkGetSwapchainImagesKHR, usually derived from min_image_count)
uint32_t SemaphoreCount; // Number of simultaneous in-flight frames + 1, to be able to use it in vkAcquireNextImageKHR
uint32_t SemaphoreIndex; // Current set of swapchain wait semaphores we're using (needs to be distinct from per frame data)
// Input
bool UseDynamicRendering;
VkSurfaceKHR Surface; // Surface created and destroyed by caller.
VkSurfaceFormatKHR SurfaceFormat;
VkPresentModeKHR PresentMode;
VkAttachmentDescription AttachmentDesc; // RenderPass creation: main attachment description.
VkClearValue ClearValue; // RenderPass creation: clear value when using VK_ATTACHMENT_LOAD_OP_CLEAR.
// Internal
int Width; // Generally same as passed to ImGui_ImplVulkanH_CreateOrResizeWindow()
int Height;
VkSwapchainKHR Swapchain;
VkRenderPass RenderPass;
VkPipeline Pipeline; // The window pipeline may uses a different VkRenderPass than the one passed in ImGui_ImplVulkan_InitInfo
uint32_t FrameIndex; // Current frame being rendered to (0 <= FrameIndex < FrameInFlightCount)
uint32_t ImageCount; // Number of simultaneous in-flight frames (returned by vkGetSwapchainImagesKHR, usually derived from min_image_count)
uint32_t SemaphoreCount; // Number of simultaneous in-flight frames + 1, to be able to use it in vkAcquireNextImageKHR
uint32_t SemaphoreIndex; // Current set of swapchain wait semaphores we're using (needs to be distinct from per frame data)
ImVector<ImGui_ImplVulkanH_Frame> Frames;
ImVector<ImGui_ImplVulkanH_FrameSemaphores> FrameSemaphores;
ImGui_ImplVulkanH_Window()
{
memset((void*)this, 0, sizeof(*this));
PresentMode = (VkPresentModeKHR)~0; // Ensure we get an error if user doesn't set this.
ClearEnable = true;
// Parameters to create SwapChain
PresentMode = (VkPresentModeKHR)~0; // 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.
AttachmentDesc.samples = VK_SAMPLE_COUNT_1_BIT;
AttachmentDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
AttachmentDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
AttachmentDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
AttachmentDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
AttachmentDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
AttachmentDesc.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
}
};
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
#endif // #ifndef IMGUI_DISABLE

View File

@@ -1,6 +1,6 @@
// dear imgui: Renderer for WebGPU
// This needs to be used along with a Platform Binding (e.g. GLFW)
// (Please note that WebGPU is currently experimental, will not run on non-beta browsers, and may break.)
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL2, SDL3)
// (Please note that WebGPU is a recent API, may not be supported by all browser, and its ecosystem is generally a mess)
// Implemented features:
// [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID/ImTextureRef!
@@ -8,6 +8,8 @@
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
// [X] Renderer: Texture updates support for dynamic font system (ImGuiBackendFlags_RendererHasTextures).
// Read imgui_impl_wgpu.h about how to use the IMGUI_IMPL_WEBGPU_BACKEND_WGPU or IMGUI_IMPL_WEBGPU_BACKEND_DAWN flags.
// 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:
@@ -18,6 +20,8 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 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.
// 2025-06-12: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. (#8465)
// 2025-02-26: Recreate image bind groups during render. (#8426, #8046, #7765, #8027) + Update for latest webgpu-native changes.
// 2024-10-14: Update Dawn support for change of string usages. (#8082, #8083)
@@ -45,22 +49,21 @@
#include "imgui.h"
// When targeting native platforms (i.e. NOT emscripten), one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN
// or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be provided. See imgui_impl_wgpu.h for more details.
#ifndef __EMSCRIPTEN__
#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!
#endif
#else
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#error neither IMGUI_IMPL_WEBGPU_BACKEND_DAWN nor IMGUI_IMPL_WEBGPU_BACKEND_WGPU may be defined if targeting emscripten!
#endif
#endif
#ifndef IMGUI_DISABLE
#include "imgui_impl_wgpu.h"
#include <limits.h>
#include <webgpu/webgpu.h>
#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!
#endif
// This condition is true when it's built with EMSCRIPTEN using -sUSE_WEBGPU=1 flag (deprecated from 4.0.10)
// This condition is false for all other 3 cases: WGPU-Native, DAWN-Native or DAWN-EMSCRIPTEN (using --use-port=emdawnwebgpu flag)
#if defined(__EMSCRIPTEN__) && defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#define IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN
#endif
#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN
// Dawn renamed WGPUProgrammableStageDescriptor to WGPUComputeState (see: https://github.com/webgpu-native/webgpu-headers/pull/413)
@@ -258,7 +261,7 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule(const c
{
ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData();
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN)
WGPUShaderSourceWGSL wgsl_desc = {};
wgsl_desc.chain.sType = WGPUSType_ShaderSourceWGSL;
wgsl_desc.code = { wgsl_source, WGPU_STRLEN };
@@ -269,12 +272,12 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule(const c
#endif
WGPUShaderModuleDescriptor desc = {};
desc.nextInChain = reinterpret_cast<WGPUChainedStruct*>(&wgsl_desc);
desc.nextInChain = (WGPUChainedStruct*)&wgsl_desc;
WGPUProgrammableStageDescriptor stage_desc = {};
stage_desc.module = wgpuDeviceCreateShaderModule(bd->wgpuDevice, &desc);
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN)
stage_desc.entryPoint = { "main", WGPU_STRLEN };
#else
stage_desc.entryPoint = "main";
@@ -367,7 +370,7 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
// Avoid rendering when minimized
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 || draw_data->CmdListsCount == 0)
if (fb_width <= 0 || fb_height <= 0 || draw_data->CmdLists.Size == 0)
return;
// Catch up with texture updates. Most of the times, the list will have 1 element with an OK status, aka nothing to do.
@@ -397,9 +400,10 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
WGPUBufferDescriptor vb_desc =
{
nullptr,
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN)
{ "Dear ImGui Vertex buffer", WGPU_STRLEN, },
#else
"Dear ImGui Vertex buffer",
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
WGPU_STRLEN,
#endif
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Vertex,
MEMALIGN(fr->VertexBufferSize * sizeof(ImDrawVert), 4),
@@ -424,9 +428,10 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
WGPUBufferDescriptor ib_desc =
{
nullptr,
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN)
{ "Dear ImGui Index buffer", WGPU_STRLEN, },
#else
"Dear ImGui Index buffer",
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
WGPU_STRLEN,
#endif
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Index,
MEMALIGN(fr->IndexBufferSize * sizeof(ImDrawIdx), 4),
@@ -442,9 +447,8 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
// Upload vertex/index data into a single contiguous GPU buffer
ImDrawVert* vtx_dst = (ImDrawVert*)fr->VertexBufferHost;
ImDrawIdx* idx_dst = (ImDrawIdx*)fr->IndexBufferHost;
for (int n = 0; n < draw_data->CmdListsCount; n++)
for (const ImDrawList* draw_list : draw_data->CmdLists)
{
const ImDrawList* draw_list = draw_data->CmdLists[n];
memcpy(vtx_dst, draw_list->VtxBuffer.Data, draw_list->VtxBuffer.Size * sizeof(ImDrawVert));
memcpy(idx_dst, draw_list->IdxBuffer.Data, draw_list->IdxBuffer.Size * sizeof(ImDrawIdx));
vtx_dst += draw_list->VtxBuffer.Size;
@@ -471,9 +475,8 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
int global_idx_offset = 0;
ImVec2 clip_scale = draw_data->FramebufferScale;
ImVec2 clip_off = draw_data->DisplayPos;
for (int n = 0; n < draw_data->CmdListsCount; n++)
for (const ImDrawList* draw_list : draw_data->CmdLists)
{
const ImDrawList* draw_list = draw_data->CmdLists[n];
for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
{
const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
@@ -534,19 +537,18 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
static void ImGui_ImplWGPU_DestroyTexture(ImTextureData* tex)
{
ImGui_ImplWGPU_Texture* backend_tex = (ImGui_ImplWGPU_Texture*)tex->BackendUserData;
if (backend_tex == nullptr)
return;
if (ImGui_ImplWGPU_Texture* backend_tex = (ImGui_ImplWGPU_Texture*)tex->BackendUserData)
{
IM_ASSERT(backend_tex->TextureView == (WGPUTextureView)(intptr_t)tex->TexID);
wgpuTextureViewRelease(backend_tex->TextureView);
wgpuTextureRelease(backend_tex->Texture);
IM_DELETE(backend_tex);
IM_ASSERT(backend_tex->TextureView == (WGPUTextureView)(intptr_t)tex->TexID);
wgpuTextureViewRelease(backend_tex->TextureView);
wgpuTextureRelease(backend_tex->Texture);
IM_DELETE(backend_tex);
// 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->BackendUserData = nullptr;
}
tex->SetStatus(ImTextureStatus_Destroyed);
tex->BackendUserData = nullptr;
}
void ImGui_ImplWGPU_UpdateTexture(ImTextureData* tex)
@@ -562,7 +564,7 @@ void ImGui_ImplWGPU_UpdateTexture(ImTextureData* tex)
// Create texture
WGPUTextureDescriptor tex_desc = {};
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN)
tex_desc.label = { "Dear ImGui Texture", WGPU_STRLEN };
#else
tex_desc.label = "Dear ImGui Texture";
@@ -607,7 +609,7 @@ void ImGui_ImplWGPU_UpdateTexture(ImTextureData* tex)
// Update full texture or selected blocks. We only ever write to textures regions which have never been used before!
// This backend choose to use tex->UpdateRect but you can use tex->Updates[] to upload individual regions.
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN)
WGPUTexelCopyTextureInfo dst_view = {};
#else
WGPUImageCopyTexture dst_view = {};
@@ -616,7 +618,7 @@ void ImGui_ImplWGPU_UpdateTexture(ImTextureData* tex)
dst_view.mipLevel = 0;
dst_view.origin = { (uint32_t)upload_x, (uint32_t)upload_y, 0 };
dst_view.aspect = WGPUTextureAspect_All;
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN)
WGPUTexelCopyBufferLayout layout = {};
#else
WGPUTextureDataLayout layout = {};
@@ -638,9 +640,10 @@ static void ImGui_ImplWGPU_CreateUniformBuffer()
WGPUBufferDescriptor ub_desc =
{
nullptr,
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN)
{ "Dear ImGui Uniform buffer", WGPU_STRLEN, },
#else
"Dear ImGui Uniform buffer",
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
WGPU_STRLEN,
#endif
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform,
MEMALIGN(sizeof(Uniforms), 16),
@@ -753,7 +756,7 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
// Create depth-stencil State
WGPUDepthStencilState depth_stencil_state = {};
depth_stencil_state.format = bd->depthStencilFormat;
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN)
depth_stencil_state.depthWriteEnabled = WGPUOptionalBool_False;
#else
depth_stencil_state.depthWriteEnabled = false;
@@ -835,14 +838,18 @@ bool ImGui_ImplWGPU_Init(ImGui_ImplWGPU_InitInfo* init_info)
// Setup backend capabilities flags
ImGui_ImplWGPU_Data* bd = IM_NEW(ImGui_ImplWGPU_Data)();
io.BackendRendererUserData = (void*)bd;
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
#if defined(__EMSCRIPTEN__)
io.BackendRendererName = "imgui_impl_webgpu_emscripten";
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
io.BackendRendererName = "imgui_impl_webgpu_dawn";
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
io.BackendRendererName = "imgui_impl_webgpu_wgpu";
io.BackendRendererName = "imgui_impl_wgpu (Dawn, Emscripten)"; // compiled & linked using EMSCRIPTEN with "--use-port=emdawnwebgpu" flag
#else
io.BackendRendererName = "imgui_impl_webgpu";
io.BackendRendererName = "imgui_impl_wgpu (Dawn, Native)";
#endif
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#if defined(__EMSCRIPTEN__)
io.BackendRendererName = "imgui_impl_wgpu (WGPU, Emscripten)"; // linked using EMSCRIPTEN with "-sUSE_WEBGPU=1" flag, deprecated from EMSCRIPTEN 4.0.10
#else
io.BackendRendererName = "imgui_impl_wgpu (WGPU, Native)";
#endif
#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.
@@ -882,6 +889,7 @@ void ImGui_ImplWGPU_Shutdown()
ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData();
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
ImGui_ImplWGPU_InvalidateDeviceObjects();
delete[] bd->pFrameResources;
@@ -894,6 +902,7 @@ void ImGui_ImplWGPU_Shutdown()
io.BackendRendererName = nullptr;
io.BackendRendererUserData = nullptr;
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
platform_io.ClearRendererHandlers();
IM_DELETE(bd);
}
@@ -905,6 +914,176 @@ void ImGui_ImplWGPU_NewFrame()
IM_ASSERT(0 && "ImGui_ImplWGPU_CreateDeviceObjects() failed!");
}
//-------------------------------------------------------------------------
// Internal Helpers
// Those are currently used by our example applications.
//-------------------------------------------------------------------------
bool ImGui_ImplWGPU_IsSurfaceStatusError(WGPUSurfaceGetCurrentTextureStatus status)
{
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
return (status == WGPUSurfaceGetCurrentTextureStatus_Error);
#else
return (status == WGPUSurfaceGetCurrentTextureStatus_OutOfMemory || status == WGPUSurfaceGetCurrentTextureStatus_DeviceLost);
#endif
}
bool ImGui_ImplWGPU_IsSurfaceStatusSubOptimal(WGPUSurfaceGetCurrentTextureStatus status)
{
#if defined(__EMSCRIPTEN__) && !defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
return (status == WGPUSurfaceGetCurrentTextureStatus_Timeout || status == WGPUSurfaceGetCurrentTextureStatus_Outdated || status == WGPUSurfaceGetCurrentTextureStatus_Lost);
#else
return (status == WGPUSurfaceGetCurrentTextureStatus_Timeout || status == WGPUSurfaceGetCurrentTextureStatus_Outdated || status == WGPUSurfaceGetCurrentTextureStatus_Lost || status == WGPUSurfaceGetCurrentTextureStatus_SuccessSuboptimal);
#endif
}
// Helpers to obtain a string
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
const char* ImGui_ImplWGPU_GetErrorTypeName(WGPUErrorType type)
{
switch (type)
{
case WGPUErrorType_Validation: return "Validation";
case WGPUErrorType_OutOfMemory: return "OutOfMemory";
case WGPUErrorType_Unknown: return "Unknown";
case WGPUErrorType_Internal: return "Internal";
default: return "Unknown";
}
}
const char* ImGui_ImplWGPU_GetDeviceLostReasonName(WGPUDeviceLostReason type)
{
switch (type)
{
case WGPUDeviceLostReason_Unknown: return "Unknown";
case WGPUDeviceLostReason_Destroyed: return "Destroyed";
case WGPUDeviceLostReason_CallbackCancelled: return "CallbackCancelled";
case WGPUDeviceLostReason_FailedCreation: return "FailedCreation";
default: return "Unknown";
}
}
#elif !defined(__EMSCRIPTEN__)
const char* ImGui_ImplWGPU_GetLogLevelName(WGPULogLevel level)
{
switch (level)
{
case WGPULogLevel_Error: return "Error";
case WGPULogLevel_Warn: return "Warn";
case WGPULogLevel_Info: return "Info";
case WGPULogLevel_Debug: return "Debug";
case WGPULogLevel_Trace: return "Trace";
default: return "Unknown";
}
}
#endif
const char* ImGui_ImplWGPU_GetBackendTypeName(WGPUBackendType type)
{
switch (type)
{
case WGPUBackendType_WebGPU: return "WebGPU";
case WGPUBackendType_D3D11: return "D3D11";
case WGPUBackendType_D3D12: return "D3D12";
case WGPUBackendType_Metal: return "Metal";
case WGPUBackendType_Vulkan: return "Vulkan";
case WGPUBackendType_OpenGL: return "OpenGL";
case WGPUBackendType_OpenGLES: return "OpenGLES";
default: return "Unknown";
}
}
const char* ImGui_ImplWGPU_GetAdapterTypeName(WGPUAdapterType type)
{
switch (type)
{
case WGPUAdapterType_DiscreteGPU: return "DiscreteGPU";
case WGPUAdapterType_IntegratedGPU: return "IntegratedGPU";
case WGPUAdapterType_CPU: return "CPU";
default: return "Unknown";
}
}
void ImGui_ImplWGPU_DebugPrintAdapterInfo(const WGPUAdapter& adapter)
{
WGPUAdapterInfo info = {};
wgpuAdapterGetInfo(adapter, &info);
printf("description: \"%.*s\"\n", (int)info.description.length, info.description.data);
printf("vendor: \"%.*s\", vendorID: %x\n", (int)info.vendor.length, info.vendor.data, info.vendorID);
printf("architecture: \"%.*s\"\n", (int) info.architecture.length, info.architecture.data);
printf("device: \"%.*s\", deviceID: %x\n", (int)info.device.length, info.device.data, info.deviceID);
printf("backendType: \"%s\"\n", ImGui_ImplWGPU_GetBackendTypeName(info.backendType));
printf("adapterType: \"%s\"\n", ImGui_ImplWGPU_GetAdapterTypeName(info.adapterType));
wgpuAdapterInfoFreeMembers(info);
}
#ifndef __EMSCRIPTEN__
#if defined(__APPLE__)
// MacOS specific: is necessary to compile with "-x objective-c++" flags
// (e.g. using cmake: set_source_files_properties(${IMGUI_DIR}/backends/imgui_impl_wgpu.cpp PROPERTIES COMPILE_FLAGS "-x objective-c++") )
#include <TargetConditionals.h>
#if TARGET_OS_OSX
#include <Cocoa/Cocoa.h>
#include <QuartzCore/CAMetalLayer.h>
#endif
#endif
WGPUSurface ImGui_ImplWGPU_CreateWGPUSurfaceHelper(ImGui_ImplWGPU_CreateSurfaceInfo* info)
{
WGPUSurfaceDescriptor surface_descriptor = {};
WGPUSurface surface = {};
#if defined(__APPLE__) && TARGET_OS_OSX
if (strcmp(info->System, "cocoa") == 0)
{
IM_ASSERT(info->RawWindow != nullptr);
NSWindow* ns_window = (NSWindow*)info->RawWindow;
id metal_layer = [CAMetalLayer layer];
[ns_window.contentView setWantsLayer : YES] ;
[ns_window.contentView setLayer : metal_layer] ;
WGPUSurfaceSourceMetalLayer surface_src_metal = {};
surface_src_metal.chain.sType = WGPUSType_SurfaceSourceMetalLayer;
surface_src_metal.layer = metal_layer;
surface_descriptor.nextInChain = &surface_src_metal.chain;
surface = wgpuInstanceCreateSurface(info->Instance, &surface_descriptor);
}
#elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
if (strcmp(info->System, "wayland") == 0)
{
IM_ASSERT(info->RawDisplay != nullptr && info->RawSurface != nullptr);
WGPUSurfaceSourceWaylandSurface surface_src_wayland = {};
surface_src_wayland.chain.sType = WGPUSType_SurfaceSourceWaylandSurface;
surface_src_wayland.display = info->RawDisplay;
surface_src_wayland.surface = info->RawSurface;
surface_descriptor.nextInChain = &surface_src_wayland.chain;
surface = wgpuInstanceCreateSurface(info->Instance, &surface_descriptor);
}
else if (strcmp(info->System, "x11") == 0)
{
IM_ASSERT(info->RawDisplay != nullptr && info->RawWindow != nullptr);
WGPUSurfaceSourceXlibWindow surface_src_xlib = {};
surface_src_xlib.chain.sType = WGPUSType_SurfaceSourceXlibWindow;
surface_src_xlib.display = info->RawDisplay;
surface_src_xlib.window = (uint64_t)info->RawWindow;
surface_descriptor.nextInChain = &surface_src_xlib.chain;
surface = wgpuInstanceCreateSurface(info->Instance, &surface_descriptor);
}
#elif defined(_WIN32)
if (strcmp(info->System, "win32") == 0)
{
IM_ASSERT(info->RawWindow != nullptr && info->RawInstance != nullptr);
WGPUSurfaceSourceWindowsHWND surface_src_hwnd = {};
surface_src_hwnd.chain.sType = WGPUSType_SurfaceSourceWindowsHWND;
surface_src_hwnd.hinstance = info->RawInstance;
surface_src_hwnd.hwnd = info->RawWindow;
surface_descriptor.nextInChain = &surface_src_hwnd.chain;
surface = wgpuInstanceCreateSurface(info->Instance, &surface_descriptor);
}
#else
IM_ASSERT(0 && "Unsupported WebGPU native platform!");
#endif
return surface;
}
#endif // #ifndef __EMSCRIPTEN__
//-----------------------------------------------------------------------------
#endif // #ifndef IMGUI_DISABLE

View File

@@ -1,11 +1,14 @@
// dear imgui: Renderer for WebGPU
// This needs to be used along with a Platform Binding (e.g. GLFW)
// (Please note that WebGPU is currently experimental, will not run on non-beta browsers, and may break.)
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL2, SDL3)
// (Please note that WebGPU is a recent API, may not be supported by all browser, and its ecosystem is generally a mess)
// Important note to dawn and/or wgpu users: when targeting native platforms (i.e. NOT emscripten),
// one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be provided.
// When targeting native platforms:
// - One of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU *must* be provided.
// When targeting Emscripten:
// - We now defaults to IMGUI_IMPL_WEBGPU_BACKEND_DAWN is Emscripten version is 4.0.10+, which correspond to using Emscripten '--use-port=emdawnwebgpu'.
// - We can still define IMGUI_IMPL_WEBGPU_BACKEND_WGPU to use Emscripten '-s USE_WEBGPU=1' which is marked as obsolete by Emscripten.
// Add #define to your imconfig.h file, or as a compilation flag in your build system.
// This requirement will be removed once WebGPU stabilizes and backends converge on a unified interface.
// 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
@@ -27,12 +30,34 @@
#include "imgui.h" // IMGUI_IMPL_API
#ifndef IMGUI_DISABLE
// Setup Emscripten default if not specified.
#if defined(__EMSCRIPTEN__) && !defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) && !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#include <emscripten/version.h>
#ifdef __EMSCRIPTEN_MAJOR__
#if (__EMSCRIPTEN_MAJOR__ >= 4) && (__EMSCRIPTEN_MINOR__ >= 0) && (__EMSCRIPTEN_TINY__ >= 10)
#define IMGUI_IMPL_WEBGPU_BACKEND_DAWN
#else
#define IMGUI_IMPL_WEBGPU_BACKEND_WGPU
#endif
#else
#if (__EMSCRIPTEN_major__ >= 4) && (__EMSCRIPTEN_minor__ >= 0) && (__EMSCRIPTEN_tiny__ >= 10)
#define IMGUI_IMPL_WEBGPU_BACKEND_DAWN
#else
#define IMGUI_IMPL_WEBGPU_BACKEND_WGPU
#endif
#endif
#endif
#include <webgpu/webgpu.h>
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) && !defined(__EMSCRIPTEN__)
#include <webgpu/wgpu.h> // WGPULogLevel
#endif
// Initialization data, for ImGui_ImplWGPU_Init()
struct ImGui_ImplWGPU_InitInfo
{
WGPUDevice Device;
WGPUDevice Device = nullptr;
int NumFramesInFlight = 3;
WGPUTextureFormat RenderTargetFormat = WGPUTextureFormat_Undefined;
WGPUTextureFormat DepthStencilFormat = WGPUTextureFormat_Undefined;
@@ -56,7 +81,7 @@ IMGUI_IMPL_API void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURen
IMGUI_IMPL_API bool ImGui_ImplWGPU_CreateDeviceObjects();
IMGUI_IMPL_API void ImGui_ImplWGPU_InvalidateDeviceObjects();
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
// (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_ImplWGPU_UpdateTexture(ImTextureData* tex);
// [BETA] Selected render state data shared with callbacks.
@@ -68,4 +93,38 @@ struct ImGui_ImplWGPU_RenderState
WGPURenderPassEncoder RenderPassEncoder;
};
//-------------------------------------------------------------------------
// Internal Helpers
// Those are currently used by our example applications.
//-------------------------------------------------------------------------
// (Optional) Helper to wrap some of the Dawn/WGPU/Emscripten quirks
bool ImGui_ImplWGPU_IsSurfaceStatusError(WGPUSurfaceGetCurrentTextureStatus status);
bool ImGui_ImplWGPU_IsSurfaceStatusSubOptimal(WGPUSurfaceGetCurrentTextureStatus status); // Return whether the texture is suboptimal and may need to be recreated.
// (Optional) Helper for debugging/logging
void ImGui_ImplWGPU_DebugPrintAdapterInfo(const WGPUAdapter& adapter);
const char* ImGui_ImplWGPU_GetBackendTypeName(WGPUBackendType type);
const char* ImGui_ImplWGPU_GetAdapterTypeName(WGPUAdapterType type);
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
const char* ImGui_ImplWGPU_GetDeviceLostReasonName(WGPUDeviceLostReason type);
const char* ImGui_ImplWGPU_GetErrorTypeName(WGPUErrorType type);
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) && !defined(__EMSCRIPTEN__)
const char* ImGui_ImplWGPU_GetLogLevelName(WGPULogLevel level);
#endif
// (Optional) Helper to create a surface on macOS/Wayland/X11/Window
#ifndef __EMSCRIPTEN__
struct ImGui_ImplWGPU_CreateSurfaceInfo
{
WGPUInstance Instance;
const char* System; // "cocoa" | "wayland" | "x11" | "win32"
void* RawWindow; // NSWindow* | 0 | Window | HWND
void* RawDisplay; // 0 | wl_display* | Display* | 0
void* RawSurface; // | wl_surface* | 0 | 0
void* RawInstance; // 0 | 0 | 0 | HINSTANCE
};
WGPUSurface ImGui_ImplWGPU_CreateWGPUSurfaceHelper(ImGui_ImplWGPU_CreateSurfaceInfo* info);
#endif // #ifndef __EMSCRIPTEN__
#endif // #ifndef IMGUI_DISABLE

View File

@@ -21,6 +21,11 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 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.
// 2025-09-23: Inputs: Minor optimization not submitting gamepad input if packet number has not changed.
// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown.
// 2025-04-30: Inputs: Fixed an issue where externally losing mouse capture (due to e.g. focus loss) would fail to claim it again the next subsequent click. (#8594)
// 2025-03-10: When dealing with OEM keys, use scancodes instead of translated keycodes to choose ImGuiKey values. (#7136, #7201, #7206, #7306, #7670, #7672, #8468)
// 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support.
@@ -123,6 +128,7 @@ struct ImGui_ImplWin32_Data
HMODULE XInputDLL;
PFN_XInputGetCapabilities XInputGetCapabilities;
PFN_XInputGetState XInputGetState;
DWORD XInputPacketNumber;
#endif
ImGui_ImplWin32_Data() { memset((void*)this, 0, sizeof(*this)); }
@@ -177,7 +183,7 @@ static bool ImGui_ImplWin32_InitEx(void* hwnd, bool platform_has_own_dc)
bd->LastMouseCursor = ImGuiMouseCursor_COUNT;
ImGui_ImplWin32_UpdateKeyboardCodePage(io);
// Set platform dependent data in viewport
// Our mouse update function expect PlatformHandle to be filled for the main viewport
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
main_viewport->PlatformHandle = main_viewport->PlatformHandleRaw = (void*)bd->hWnd;
IM_UNUSED(platform_has_own_dc); // Used in 'docking' branch
@@ -193,7 +199,7 @@ static bool ImGui_ImplWin32_InitEx(void* hwnd, bool platform_has_own_dc)
"xinput1_2.dll", // DirectX SDK
"xinput1_1.dll" // DirectX SDK
};
for (int n = 0; n < IM_ARRAYSIZE(xinput_dll_names); n++)
for (int n = 0; n < IM_COUNTOF(xinput_dll_names); n++)
if (HMODULE dll = ::LoadLibraryA(xinput_dll_names[n]))
{
bd->XInputDLL = dll;
@@ -222,6 +228,7 @@ void ImGui_ImplWin32_Shutdown()
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
// Unload XInput library
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
@@ -232,6 +239,7 @@ void ImGui_ImplWin32_Shutdown()
io.BackendPlatformName = nullptr;
io.BackendPlatformUserData = nullptr;
io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad);
platform_io.ClearPlatformHandlers();
IM_DELETE(bd);
}
@@ -352,6 +360,9 @@ static void ImGui_ImplWin32_UpdateGamepads(ImGuiIO& io)
if (!bd->HasGamepad || bd->XInputGetState == nullptr || bd->XInputGetState(0, &xinput_state) != ERROR_SUCCESS)
return;
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
if (bd->XInputPacketNumber != 0 && bd->XInputPacketNumber == xinput_state.dwPacketNumber)
return;
bd->XInputPacketNumber = xinput_state.dwPacketNumber;
#define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V)
#define MAP_BUTTON(KEY_NO, BUTTON_ENUM) { io.AddKeyEvent(KEY_NO, (gamepad.wButtons & BUTTON_ENUM) != 0); }
@@ -644,8 +655,8 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandlerEx(HWND hwnd, UINT msg, WPA
bd->MouseTrackedArea = area;
}
POINT mouse_pos = { (LONG)GET_X_LPARAM(lParam), (LONG)GET_Y_LPARAM(lParam) };
if (msg == WM_NCMOUSEMOVE && ::ScreenToClient(hwnd, &mouse_pos) == FALSE) // WM_NCMOUSEMOVE are provided in absolute coordinates.
return 0;
if (msg == WM_NCMOUSEMOVE) // WM_NCMOUSEMOVE are absolute coordinates.
::ScreenToClient(hwnd, &mouse_pos);
io.AddMouseSourceEvent(mouse_source);
io.AddMousePosEvent((float)mouse_pos.x, (float)mouse_pos.y);
return 0;
@@ -765,6 +776,9 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandlerEx(HWND hwnd, UINT msg, WPA
case WM_SETFOCUS:
case WM_KILLFOCUS:
io.AddFocusEvent(msg == WM_SETFOCUS);
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
bd->XInputPacketNumber = 0; // FIXME: Technically, calling io.ClearInputKeys() directly would require this as well.
#endif
return 0;
case WM_INPUTLANGCHANGE:
ImGui_ImplWin32_UpdateKeyboardCodePage(io);
@@ -779,10 +793,28 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandlerEx(HWND hwnd, UINT msg, WPA
else
{
wchar_t wch = 0;
::MultiByteToWideChar(bd->KeyboardCodePage, MB_PRECOMPOSED, (char*)&wParam, 1, &wch, 1);
::MultiByteToWideChar(bd->KeyboardCodePage, MB_PRECOMPOSED, (char*)&wParam, 2, &wch, 1);
io.AddInputCharacter(wch);
}
return 0;
case WM_IME_COMPOSITION:
{
// Handling WM_IME_COMPOSITION ensure that WM_IME_CHAR value is correct even for MBCS apps.
// (see #9099, #3653 and https://stackoverflow.com/questions/77450354 topics)
LRESULT result = ::DefWindowProcW(hwnd, msg, wParam, lParam);
return (lParam & GCS_RESULTSTR) ? 1 : result;
}
case WM_IME_CHAR:
if (::IsWindowUnicode(hwnd) == FALSE)
{
if (::IsDBCSLeadByte(HIBYTE(wParam)))
wParam = (WPARAM)MAKEWORD(HIBYTE(wParam), LOBYTE(wParam));
wchar_t wch = 0;
::MultiByteToWideChar(bd->KeyboardCodePage, MB_PRECOMPOSED, (char*)&wParam, 2, &wch, 1);
io.AddInputCharacterUTF16(wch);
return 1;
}
return 0;
case WM_SETCURSOR:
// This is required to restore cursor when transitioning from e.g resize borders to client area.
if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor(io, bd->LastMouseCursor))
@@ -806,7 +838,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandlerEx(HWND hwnd, UINT msg, WPA
// - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps.
// - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc.
// but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime,
// neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies.
// neither of which we want to require the user to have. So we dynamically select and load those functions to avoid dependencies.
//---------------------------------------------------------------------------------------------------------
// This is the scheme successfully used by GLFW (from which we borrowed some of the code) and other apps aiming to be highly portable.
// ImGui_ImplWin32_EnableDpiAwareness() is just a helper called by main.cpp, we don't call it automatically.

View File

@@ -26,7 +26,7 @@ IMGUI_IMPL_API bool ImGui_ImplWin32_InitForOpenGL(void* hwnd);
IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown();
IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame();
// Win32 message handler your application need to call.
// Win32 message handler your application needs to call.
// - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on <windows.h> from this helper.
// - You should COPY the line below into your .cpp code to forward declare the function and then you can call it.
// - Call from your application's message handler. Keep calling your message handler unless this function returns TRUE.
@@ -40,7 +40,7 @@ extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg
// - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps.
// - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc.
// but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime,
// neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies.
// neither of which we want to require the user to have. So we dynamically select and load those functions to avoid dependencies.
IMGUI_IMPL_API void ImGui_ImplWin32_EnableDpiAwareness();
IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd); // HWND hwnd
IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); // HMONITOR monitor

View File

@@ -34,6 +34,8 @@ Instructions to rebuild imgui_impl_sdlgpu3_shaders.h
xcrun -sdk macosx metallib -o vertex.metallib -c vertex.ir
xcrun -sdk macosx metallib -o fragment.metallib -c fragment.ir
note: use .metal outputs for updating msl_vertex / msl_fragment variables, and use .metallib outputs for metallib_vertex / metallib_fragment variables
Proceed to step 4

View File

@@ -100,6 +100,7 @@ List of Renderer Backends:
List of high-level Frameworks Backends (combining Platform + Renderer):
imgui_impl_allegro5.cpp
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.
@@ -245,9 +246,8 @@ void MyImGuiBackend_RenderDrawData(ImDrawData* draw_data)
// Render command lists
ImVec2 clip_off = draw_data->DisplayPos;
ImVec2 clip_scale = draw_data->FramebufferScale;
for (int n = 0; n < draw_data->CmdListsCount; n++)
for (const ImDrawList* draw_list : draw_data->CmdLists)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data; // vertex buffer generated by Dear ImGui
const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data; // index buffer generated by Dear ImGui
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
@@ -337,7 +337,7 @@ void MyImGuiBackend_UpdateTexture(ImTextureData* tex)
{
// Create texture based on tex->Width, tex->Height.
// - Most backends only support tex->Format == ImTextureFormat_RGBA32.
// - Backends for particularly memory constrainted platforms may support tex->Format == ImTextureFormat_Alpha8.
// - Backends for particularly memory constrained platforms may support tex->Format == ImTextureFormat_Alpha8.
// Upload all texture pixels
// - Read from our CPU-side copy of the texture and copy to your graphics API.

View File

@@ -35,6 +35,705 @@ HOW TO UPDATE?
and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users.
- Please report any issue!
-----------------------------------------------------------------------
VERSION 1.92.6 (2026-02-17)
-----------------------------------------------------------------------
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.6
Breaking Changes:
- Fonts:
- `AddFontDefault()` now automatically selects an embedded font between:
- `AddFontDefaultBitmap()`: classic pixel-clean font. Recommended at Size 13px with no scaling.
- `AddFontDefaultVector()`: new scalable font. Recommended at any higher size.
- The default selection is based on (style.FontSizeBase * FontScaleMain * FontScaleDpi)
reaching a small threshold, but old codebases may not set any of them properly.
As as a result, it is likely that old codebase may still default to AddFontDefaultBitmap().
- Prefer explicitly calling either of them based on your own logic!
You can call `AddFontDefaultBitmap()` to ensure legacy behavior.
- Fixed handling of `ImFontConfig::FontDataOwnedByAtlas = false` which did
erroneously make a copy of the font data, essentially defeating the purpose
of this flag and wasting memory (undetected since July 2015 and now spotted
by @TellowKrinkle, this is perhaps the oldest bug in Dear ImGui history,
albeit for a rarely used feature!) (#9086, #8465)
HOWEVER, fixing this bug is likely to surface bugs in user/app code:
- Prior to 1.92, font data only needs to be available during the `atlas->AddFontXXX()` call.
Since 1.92, font data needs to available until `atlas->RemoveFont()`, or more typically
until a shutdown of the owning context or font atlas.
- The fact that handling of `FontDataOwnedByAtlas = false` was broken bypassed
the issue altogether.
- Removed `ImFontConfig::PixelSnapV` added in 1.92 which turns out is unnecessary
(and was mis-documented). Post-rescale `GlyphOffset` is always rounded.
- Popups: changed compile-time `ImGuiPopupFlags popup_flags = 1` default value to be `= 0` for
`BeginPopupContextItem()`, `BeginPopupContextWindow()`, `BeginPopupContextVoid()`, `OpenPopupOnItemClick()`.
The default value has same meaning before and after. (#9157, #9146)
- Before this version, those functions had a `ImGuiPopupFlags popup_flags = 1` default
value in their function signature. This was introduced by a change on 2020/06/23 (1.77)
while changing the signature from `int mouse_button` to `ImGuiPopupFlags popup_flags`
and trying to preserve then-legacy behavior.
- We have now changed this behavior to: cleanup a very old API quirk, facilitate use by
bindings, and to remove the last and error-prone non-zero default value. Also because we
deemed it extremely rare to use those helper functions with the Left mouse button!
As using the LMB would generally be triggered via another widget,
e.g. a Button() + a OpenPopup()/BeginPopup() call.
- Before: The default = 1 means `ImGuiPopupFlags_MouseButtonRight`.
Explicitly passing a literal 0 means `ImGuiPopupFlags_MouseButtonLeft`.
- After: The default = 0 means `ImGuiPopupFlags_MouseButtonRight`.
Explicitly passing a literal 1 also means `ImGuiPopupFlags_MouseButtonRight`.
(if legacy behavior are enabled) or will assert (if legacy behavior are disabled).
- TL;DR: if you don't want to use right mouse button for popups, always specify it
explicitly using a named `ImGuiPopupFlags_MouseButtonXXXX` value.
Recap:
- BeginPopupContextItem("foo"); // Behavior unchanged (use Right button)
- BeginPopupContextItem("foo", ImGuiPopupFlags_MouseButtonLeft); // Behavior unchanged (use Left button)
- BeginPopupContextItem("foo", ImGuiPopupFlags_MouseButtonLeft | xxx); // Behavior unchanged (use Left button + flags)
- BeginPopupContextItem("foo", ImGuiPopupFlags_MouseButtonRight | xxx); // Behavior unchanged (use Right button + flags)
- BeginPopupContextItem("foo", 1); // Behavior unchanged (as a courtesy we legacy interpret 1 as ImGuiPopupFlags_MouseButtonRight, will assert if disabling legacy behaviors.
- BeginPopupContextItem("foo", 0); // !! Behavior changed !! Was Left button. Now will defaults to Right button! --> Use ImGuiPopupFlags_MouseButtonLeft.
- BeginPopupContextItem("foo", ImGuiPopupFlags_NoReopen); // !! Behavior changed !! Was Left button + flags. Now will defaults to Right button! --> Use ImGuiPopupFlags_MouseButtonLeft | xxx.
- Commented out legacy names obsoleted in 1.90 (Sept 2023):
- `BeginChildFrame()` --> `BeginChild()` with `ImGuiChildFlags_FrameStyle` flag.
- `EndChildFrame()` --> `EndChild()`.
- `ShowStackToolWindow()` --> `ShowIDStackToolWindow()`.
- `IM_OFFSETOF()` --> `offsetof()`.
- `IM_FLOOR()` --> `IM_TRUNC()` [internal, for positive values only]
- Hashing: handling of "###" operator to reset to seed within a string identifier
doesn't include the "###" characters in the output hash anymore:
Before: `GetID("Hello###World") == GetID("###World") != GetID("World")`
After: `GetID("Hello###World") == GetID("###World") == GetID("World")`
- This has the property of facilitating concatenating and manipulating
identifiers using "###", and will allow fixing other dangling issues.
- This will invalidate hashes (stored in .ini data) for Tables and Windows
that are using the "###" operators. (#713, #1698)
- Renamed helper macro `IM_ARRAYSIZE()` -> `IM_COUNTOF()`. Kept redirection/legacy name.
- Backends:
- Vulkan: optional `ImGui_ImplVulkanH_DestroyWindow()` helper used by our example
code does not call `vkDestroySurfaceKHR()`: because surface is created by caller
of `ImGui_ImplVulkanH_CreateOrResizeWindow()`, it is more consistent. (#9163)
Other Changes:
- Fonts:
- Added `AddFontDefaultVector()`: a new embedded monospace scalable font: ProggyForever!
From https://github.com/ocornut/proggyforever:
"ProggyForever is an MIT-licensed partial reimplementation of the ProggyVector
font (originally by Tristan Grimmer), which itself is a vector-based
reinterpretation of the ProggyClean bitmap font that happily served as
Dear ImGui default font for over 10 years." [...]
"I commissioned Thiebault Courot to recreate this, applied various minor tweaks
and fixes, and reworked his editing pipeline toward shipping FontForge source
files so we can allow and track future changes."
- TL;DR; there was no strictly MIT-licensed matching font. We made it!
- The font data was carefully subsetted, trimmed and compressed so the embedded
data is ~14 KB. Embedding a scalable default font ensures that Dear ImGui can
be easily and readily used in all contexts, even without file system access.
- Expect minor fixes/improvements in following releases.
- As always you can opt-out of the embedded font data if desired.
- `AddFontDefault()` now automatically selects an embedded font between
the classic pixel-looking one and the new scalable one.
Prefer calling `AddFontDefaultVector()` or `AddFontDefaultBitmap()` explicitly.
- Fixed a crash when trying to use `AddFont()` with `MergeMode==true` on a font that
has already been rendered. (#9162) [@ocornut, @cyfewlp]
- Fixed an issue where using `PushFont()` from the implicit/fallback "Debug" window
when its recorded state is collapsed would incorrectly early out. This would break
e.g. using direct draw-list calls such as `GetForegroundDrawList()` with current font.
(#9210, #8865)
- Fixed an issue related to `EllipsisChar` handling, while changing
font loader or font loader flags dynamically in Style->Fonts menus.
- imgui_freetype: fixed overwriting `ImFontConfig::PixelSnapH` when hinting
is enabled, creating side-effects when later disabling hinting or
dynamically switching to stb_truetype rasterizer.
- Adding new fonts after removing all fonts mid-frame properly updates current state.
- Textures:
- Fixed a building issue when `ImTextureID` is defined as a struct.
- Fixed displaying texture # in Metrics/Debugger window.
- Menus:
- Fixed `MenuItem()` label position and `BeginMenu()` arrow/icon/popup positions,
when used inside a line with a baseline offset.
- Made navigation into menu-bar auto wrap on X axis. (#9178)
- TreeNode:
- Fixed highlight position when used inside a line with a large text baseline offset.
(it never quite worked in this situation; but then most of the time the text
baseline offset ends up being zero or `FramePadding.y` for a given line).
- Tables:
- Fixed an issue where a very thin scrolling table would advance parent layout
slightly differently depending on its visibility (caused by a mismatch
between hard minimum window size and table minimum size).
- Fixed an issue where submitting non-integer row heights would eventually
advance table parent layout by +0/+1 depending on its visibility.
- Fixed losing stored display order when reducing column count or when .ini
data has missing or duplicate values. (#9108, #4046)
- ColorEdit:
- Added R/G/B/A color markers next to each component (enabled by default).
- Added `ImGuiColorEditFlags_NoColorMarkers` to disable them.
- Added `style.ColorMarkerSize` to configure width of color component markers.
- Sliders, Drags:
- Added `ImGuiSliderFlags_ColorMarkers` to opt-in adding R/G/B/A color markers
next to each components, in multi-components functions.
- Added a way to select a specific marker color.
- InputText:
- InputTextMultiline(): fixed a minor bug where Shift+Wheel would allow a small
horizontal scroll offset when there should be none. (#9249)
- ImGuiInputTextCallbackData: `SelectAll()` also sets `CursorPos` to `SelectionEnd`.
- ImGuiInputTextCallbackData: Added `SetSelection()` helper.
- ImGuiInputTextCallbackData: Added `ID` and `EventActivated` members. (#9174)
- Text, InputText:
- Reworked word-wrapping logic:
- Try to not wrap in the middle of contiguous punctuation. (#8139, #8439, #9094)
- Try to not wrap between a punctuation and a digit. (#8503)
- Inside `InputTextMultiline()` with WordWrap enabled: prefer keeping blanks at
the end of a line rather than at the beginning of next line. (#8990, #3237)
- Fixed low-level word-wrapping function reading from `*text_end` when passed
a string range. (#9107) [@achabense]
- Changed `RenderTextEllipsis()` logic to not trim trailing blanks before
the ellipsis, making ellipsis position more consistent and not arbitrary
hiding the possibility of multiple blanks. (#9229)
- Nav:
- Fixed remote/shortcut InputText() not teleporting mouse cursor when
nav cursor is visible and `io.ConfigNavMoveSetMousePos` is enabled.
- Fixed a looping/wrapping issue when used in menu layer. (#9178)
- Fixed speed scale for resizing/moving with keyboard/gamepad. We incorrectly
used `io.DisplayFramebufferScale` as a scaling factor (very old code),
effectively making those actions faster on macOS/iOS retina screens.
(changed this to use a style scale factor that's not fully formalized yet)
- Fixed an UBSan warning when using in a `ImGuiListClipper` region . (#9160)
- Scrollbar: fixed a code-path leading to a divide-by-zero (which would not be
noticeable by user but detected by sanitizers). (#9089) [@judicaelclair]
- InvisibleButton: allow calling with size (0,0) to fit to available content
size. (#9166, #7623)
- Tooltips, Disabled: fixed `EndDisabledOverrideReenable()` assertion when
nesting a tooltip in a disabled block. (#9180, #7640) [@RegimantasSimkus]
- Added `GetItemFlags()` in public API for consistency and to expose generic
flags of last submitted item. (#9127)
- Misc: fixed build on ARM64/ARM64EC targets trying to use SSE/immintrin.h.
(#9209, #5943, #4091) [@navvyswethgraphics]
- Log/Capture:
- Fixed erroneously injecting extra carriage returns in output text buffer
when `ItemSpacing.y` > `FramePadding.y + 1` while emitting items.
- Images:
- Added `style.ImageRounding`, `ImGuiStyleVar_ImageRounding `to configure
rounding of `Image()` widgets. (#2942, #845)
- `ImageButton()` doesn't use a clamped `style.FrameRounding` value but instead
adjust inner image rounding when `FramePadding > `FrameRounding`. (#2942, #845)
- Shortcuts:
- IsItemHovered() without `ImGuiHoveredFlags_AllowWhenBlockedByActiveItem`
doesn't filter out the signal when activated item is a shortcut remote activation;
(which mimics what's done internally in the `ItemHoverable()` function). (#9138)
- Fixed tooltip placement being affected for a frame when located over an item
activated by `SetNextItemShortcut()`. (#9138)
- Error Handling:
- Improved error handling and recovery for `EndMenu()`/`EndCombo()`. (#1651, #9165, #8499)
- Improved error handling and recovery for `TableSetupColumn()`.
- Debug Tools:
- Debug Log: fixed incorrectly printing characters in IO log when submitting
non-ASCII values to `io.AddInputCharacter()`. (#9099)
- Debug Log: can output to debugger on Windows via Win32 `OutputDebugString()` (#5855)
- Demo:
- Slightly improve `Selectable()` demos. (#9193)
- Backends:
- DirectX10: added `SamplerNearest` in `ImGui_ImplDX10_RenderState`.
(+renamed `SamplerDefault` to `SamplerLinear`, which was tagged as beta API)
- DirectX11: added `SamplerNearest` in ImGui_ImplDX11_RenderState.
(+renamed `SamplerDefault` to `SamplerLinear`, which was tagged as beta API)
- GLFW: Avoid repeated `glfwSetCursor()` / `glfwSetInputMode()` unnecessary calls.
Lowers overhead for very high framerates (e.g. 10k+ FPS). [@maxliani]
- GLFW: Added `IMGUI_IMPL_GLFW_DISABLE_X11` / `IMGUI_IMPL_GLFW_DISABLE_WAYLAND` to
forcefully disable either. (#9109, #9116)
Try to set them automatically if headers are not accessible. (#9225)
- OpenGL3: Fixed embedded loader multiple init/shutdown cycles broken on some
platforms. (#8792, #9112)
- SDL2, SDL3: changed `GetClipboardText()` handler to return NULL on error aka
clipboard contents is not text. Consistent with other backends. (#9168)
- SDL2, SDL3: systems other than X11 are back to starting mouse capture on mouse down
(reverts 1.91.9 change). Only X11 requires waiting for a drag by default (not ideal,
but a better default for X11 users). Waiting for a drag to start mouse capture leads to
input drops when dragging after clicking on the edge of a window.
(#3650, #6410, #9235, #3956, #3835)
- SDL2, SDL3: added `ImGui_ImplSDL2_SetMouseCaptureMode()`/`ImGui_ImplSDL3_SetMouseCaptureMode()`
function for X11 users to disable mouse capturing/grabbing. (#3650, #6410, #9235, #3956, #3835)
- When attached to a debugger may want to call:
- `ImGui_ImplSDL3_SetMouseCaptureMode(ImGui_ImplSDL3_MouseCaptureMode_Disabled);`
- But you can also configure your system or debugger to automatically release
mouse grab when crashing/breaking in debugger, e.g.
- console: `setxkbmap -option grab:break_actions && xdotool key XF86Ungrab`
- or use a GDB script to call `SDL_CaptureMouse(false)`. See #3650.
- On platforms other than X11 this is unnecessary.
- SDL_GPU3: added `SamplerNearest` in `ImGui_ImplSDLGPU3_RenderState`.
- SDL_GPU3: macOS version can use MSL shaders in order to support macOS 10.14+
(vs Metallib shaders requiring macOS 14+). Requires application calling
`SDL_CreateGPUDevice()` with `SDL_GPU_SHADERFORMAT_MSL`. (#9076) [@Niminem]
- Vulkan: helper for creating a swapchain (used by examples and multi-viewports)
selects `VkSwapchainCreateInfoKHR`'s `compositeAlpha` value based on
`cap.supportedCompositeAlpha`, which seems to be required on some Android
devices. (#8784) [@FelixStach]
- WebGPU: fixes for Emscripten 5.0.0 (note: current examples do not build with 5.0.1).
- Win32: handle `WM_IME_CHAR`/`WM_IME_COMPOSITION` to support Unicode inputs on
MBCS (non-Unicode) Windows. (#9099, #3653, #5961) [@ulhc, @ocornut, @Othereum]
- Win32: minor optimization not submitting gamepad input if packet number has not
changed (reworked previous 1.92.4). (#9202, #8556) [@AhmedSamyMousa, @MidTerm-CN]
- Examples:
- Win32+DirectX12: ignore seemingly incorrect `D3D12_MESSAGE_ID_FENCE_ZERO_WAIT`
warning on startups on some setups. (#9084, #9093) [@RT2Code, @LeoGautheron]
-----------------------------------------------------------------------
VERSION 1.92.5 (Released 2025-11-20)
-----------------------------------------------------------------------
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.5
Breaking Changes:
- Keys: commented out legacy names which were obsoleted in 1.89.0 (August 2022).
- ImGuiKey_ModCtrl --> ImGuiMod_Ctrl
- ImGuiKey_ModShift --> ImGuiMod_Shift
- ImGuiKey_ModAlt --> ImGuiMod_Alt
- ImGuiKey_ModSuper --> ImGuiMod_Super
- IO: commented out legacy io.ClearInputCharacters() obsoleted in 1.89.8 (Aug 2023).
Using io.ClearInputKeys() is enough.
- BeginChild: commented out legacy names which were obsoleted in 1.90.0 (Nov 2023),
1.90.9 (July 2024), 1.91.1 (August 2024). (#462, #7687)
- ImGuiChildFlags_Border --> ImGuiChildFlags_Borders
- ImGuiWindowFlags_NavFlattened --> ImGuiChildFlags_NavFlattened (moved to ImGuiChildFlags).
- ImGuiWindowFlags_AlwaysUseWindowPadding --> ImGuiChildFlags_AlwaysUseWindowPadding (moved to ImGuiChildFlags).
So:
- BeginChild(name, size, 0, ImGuiWindowFlags_NavFlattened) --> BeginChild(name, size, ImGuiChildFlags_NavFlattened, 0)
- BeginChild(name, size, 0, ImGuiWindowFlags_AlwaysUseWindowPadding) --> BeginChild(name, size, ImGuiChildFlags_AlwaysUseWindowPadding, 0)
- Commented out legacy SetItemAllowOverlap() obsoleted in 1.89.7: this never worked right.
Use SetNextItemAllowOverlap() _before_ item instead.
Other Changes:
- Windows:
- Config flag io.ConfigWindowsMoveFromTitleBarOnly is now latched during
Begin(), effectively allowing to change the value on a per-window basis.
(although there is a better internal mechanism for it).
- Fixed single-axis auto-sizing (via double-clicking a border or passing
0.0f on one axis of SetNextWindowSize() call) to take account of remaining
scrollbar on the other axis. (#9060)
- Fixed an issue where repeated calls to SetNextWindowSize() using 0.0f
to auto-size on a given axis would keep marking ini settings as dirty.
- Tables:
- Fixed a bug where nesting BeginTable()->Begin()->BeginTable() would
result in temporarily incorrect state, which would lead to bugs to side effects
in various locations, e.g. GetContentRegionAvail() calls or using clipper. (#9005)
EndTable() was mistakenly restoring a wrong current table.
- Angled headers: fixed an auto-resize feedback loop that could
affect tables with empty non-resizing columns using angled headers, making
them typically flicker back and forth between +0 and +1 pixels.
- Disabled: fixed a bug when a previously enabled item that got nav focus
and then turns disabled could still be activated using keyboard. (#9036)
- InputText:
- When buffer is not resizable, trying to paste contents that cannot
fit will now truncate text to nearest UTF-8 codepoint boundaries,
instead of completely ignoring the paste. (#9029)
- Avoid continuously overwriting ownership of ImGuiKey_Enter/_KeypadEnter
keys in order to allow e.g. external Shortcut override behavior. (#9004)
- When using a callback to reduce/manipulate the value of BufTextLen,
we do not require anymore that CursorPos be clamped by user code. (#9029)
- Fixed an assert when using ImGuiInputTextFlags_ReadOnly and making
underlying contents shorter while text is selected. (#9069, #3237)
(regression from 1.92.3)
- InputTextMultiline: fixed a crash when using ImGuiInputTextFlags_WordWrap and
resizing the parent window while keeping the multi-line field active (which is
most typically achieved when resizing programmatically or via a docking layout
reacting to a platform window resize). (#3237, #9007) [@anton-kl, @ocornut]
- Nav:
- Reworked PageUp/PageDown logic to pick same-page top/bottom page based
on inner rectangle rather than clipping rectangle, ensuring consistent
(but occasionally less practical) navigation result when a window is
partially out of screen. (#787)
- Improved/clarified behavior when requesting PageUp/PageDown from a
focused item which is outside of visible boundaries: now ends up one
page away from focused item. (#9079)
- Clipper: fixed an issue when using up/down from an item outside of
visible bound and using the clipper. (#9079)
- Fonts:
- Calling ImFontAtlas::Clear() mid-frame without re-adding a font will
lead to a more explicit crash.
- Textures:
- Fixed an issue preventing multi-contexts from using each others' fonts
if context 2 runs after context 1's Render() function. (#9039)
- MultiSelect: added ImGuiMultiSelectFlags_NoSelectOnRightClick to disable default
right-click processing, which selects item on mouse down and is designed for
context-menus. (#8200, #9015)
- Groups: fixed an issue reporting IsItemEdited() signal after EndGroup() when
triggered by some widgets e.g. Checkbox(), Selectable() and many others, which
cleared ActiveId at the same time as editing. (#9028)
Note that IsItemDeactivatedAfterEdit() was not affected, only IsItemEdited().
- Misc: standardized casing of keyboard mods in comments and demo, showing
as e.g. "Ctrl" instead of "CTRL".
- CI: Added Dear ImGui Test Suite to CI builds. [@rokups]
- Drag and Drop:
- Added ImGuiDragDropFlags_AcceptDrawAsHovered to make accepting item render
as hovered, which can allow using e.g. Button() as drop target. (#8632)
- Pressing Escape while carrying a payload automatically cancel the
active drag and drop. (#9071)
- Style: added ImGuiCol_DragDropTargetBg, style.DragDropTargetRounding,
style.DragDropTargetBorderSize and style.DragDropTargetPadding to configure
the drop target highlight. (#9056) [@aaronkirkham]
- Demo: About Box: emit infos to convey when IM_ASSERT() macro is disabled,
- so users don't miss out on programming errors being reported.
- so it is included in config/build info submitted in new GitHub Issues.
- Debug Tools:
- Fixed DebugTextEncoding() potentially reading out of bounds when
provided a trailing truncated UTF-8 sequence.
- Metrics: fixed table and columns rect highlight from display when
debug/metrics window is not in the same viewport as the table.
- Backends:
- NULL: added imgui_impl_null platform/renderer backend.
This is designed if you need to run e.g. context with no input or no output.
- GLFW: fixed building on Linux platforms where Wayland headers
are not available. (#9024, #8969, #8921, #8920) [@jagot]
- GLFW: lower minimum requirement from GLFW 3.1 to GLFW 3.0. Though
a recent version e.g GLFW 3.4 is highly recommended! (#9055) [@Clownacy]
- GLFW: fixed last `ImGui_ImplGlfw_Shutdown()` not immediately clearing the context
map, which would be detected by leak trackers. (#9075, #8676, #8239, #8069) [@erincatto]
- SDL3: fixed Platform_OpenInShellFn() return value (the return value
was unused in core but might be used by a direct caller). (#9027) [@achabense]
- SDL3: fixed an issue with missing characters events when an already active text
field changes viewports. (#9054)
- Vulkan: added IMGUI_IMPL_VULKAN_VOLK_FILENAME to configure path to
Volk (default to "volk.h"). (#9008, #7722, #6582, #4854) [@mwlasiuk]
- WebGPU: update to compile with Dawn and Emscripten's 4.0.10+
'--use-port=emdawnwebgpu' ports. (#8381, #8898, #7435) [@brutpitt, @trbabb]
When using Emscripten 4.0.10+, backend now defaults to IMGUI_IMPL_WEBGPU_BACKEND_DAWN
instead of IMGUI_IMPL_WEBGPU_BACKEND_WGPU, if neither are specified.
- WebGPU: added various internal/optional helpers to wrap some of the
Dawn/WGPU/Emscripten debacle quirks: (#8381) [@brutpitt]
- ImGui_ImplWGPU_CreateWGPUSurfaceHelper().
- ImGui_ImplWGPU_IsSurfaceStatusError(), ImGui_ImplWGPU_IsSurfaceStatusSubOptimal().
- ImGui_ImplWGPU_DebugPrintAdapterInfo(),
- ImGui_ImplWGPU_GetBackendTypeName(), ImGui_ImplWGPU_GetAdapterTypeName(),
ImGui_ImplWGPU_GetDeviceLostReasonName(), ImGui_ImplWGPU_GetErrorTypeName(),
ImGui_ImplWGPU_GetLogLevelName().
- Win32: Revert 1.92.4 change of comparing dwPacketNumber, which prevents
refreshing accurate gamepad info after focus-out + io.ClearInputKeys(). (#8556)
- Examples:
- NULL: update examples_null to use imgui_impl_null (which is a bit overengineering
but somehow consistent).
- GLFW+WebGPU: update example for latest specs, to work on Emscripten 4.0.10+,
latest Dawn-Native and WGPU-Native. (#8381, #8567, #8191, #7435) [@brutpitt]
- GLFW+WebGPU: removed unnecessary ImGui_ImplWGPU_InvalidateDeviceObjects() call
during surface resize. (#8381)
- SDL2+WebGPU: added new example (Emscripten + native Dawn/WGPU). (#8381) [@brutpitt]
- SDL3+WebGPU: added new example (Emscripten + native Dawn/WGPU). (#8381) [@brutpitt]
- Win32+OpenGL3: enable DPI awareness. (#9083)
-----------------------------------------------------------------------
VERSION 1.92.4 (Released 2025-10-14)
-----------------------------------------------------------------------
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.4
Breaking Changes:
- Backends:
- TreeNode, Selectable, Clipper: commented out legacy names obsoleted in
1.89.7 (July 2023) and 1.89.9 (Sept 2023):
ImGuiTreeNodeFlags_AllowItemOverlap --> ImGuiTreeNodeFlags_AllowOverlap
ImGuiSelectableFlags_AllowItemOverlap --> ImGuiSelectableFlags_AllowOverlap
ImGuiListClipper::IncludeRangeByIndices() --> ImGuiListClipper::IncludeItemsByIndex()
- Vulkan: moved some fields in ImGui_ImplVulkan_InitInfo:
init_info.RenderPass --> init_info.PipelineInfoMain.RenderPass
init_info.Subpass --> init_info.PipelineInfoMain.Subpass
init_info.MSAASamples --> init_info.PipelineInfoMain.MSAASamples
init_info.PipelineRenderingCreateInfo --> init_info.PipelineInfoMain.PipelineRenderingCreateInfo
It makes things more consistent and was desirable to introduce new settings for
secondary viewports. (#8946, #8110, #8111, #8686) [@ocornut, @SuperRonan, @sylmroz]
- Vulkan: renamed ImGui_ImplVulkan_MainPipelineCreateInfo --> ImGui_ImplVulkan_PipelineInfo
(introduced very recently and only used by `ImGui_ImplVulkan_CreateMainPipeline()`
so it should not affect many users). (#8110, #8111)
- Vulkan: helper ImGui_ImplVulkanH_CreateOrResizeWindow() added a
`VkImageUsageFlags image_usage` argument.
It was previously hardcoded to `VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT` and defaults
to that when the value is 0. In theory the function is an internal helper but
since it's used by our examples some may have used it. (#8946, #8111, #8686)
Other Changes:
- Windows: added lower-right resize grip on child windows using both
ImGuiChildFlags_ResizeX and ImGuiChildFlags_ResizeY flags. (#8501) [@aleksijuvani]
The grip is not visible before hovering to reduce clutter.
- Style: added ImGuiCol_UnsavedMarker, color of the unsaved document marker when
using ImGuiWindowFlags_UnsavedDocument/ImGuiTabItemFlags_UnsavedDocument. (#8983)
- IO: added ImGuiPlatformIO::ClearPlatformHandlers(), ClearRendererHandlers()
helpers to null all handlers. (#8945, #2769)
- Tables: changed ImGuiTableFlags_NoBordersInBody behavior to not draw border in
body even when resizing. (#8893)
- Inputs:
- Shortcuts: added support for combining ImGuiInputFlags_RouteFocused
(which is the default route) with ImGuiInputFlags_RouteOverActive, allowing
to steal shortcuts from active item without using global routing. (#9004)
- InputText:
- Fixed single-line InputText() not applying fine character clipping
properly (regression in 1.92.3). (#8967) [@Cyphall]
- Fixed an infinite loop error happening if a custom input text
callback modifies/clear BufTextLen before calling InsertChars().
(regression from 1.92.3). Note that this never really worked correctly, but
previously it would only temporary wreck cursor position, and since 1.92.3 it
would go in an infinite loop. (#8994, #3237)
- Textures:
- Fixed a crash if texture status is set to ImTextureStatus_WantDestroy by a backend
after it had already been destroyed. This would typically happen when calling
ImGui_ImplXXXX_InvalidateDeviceObjects() helpers twice in a row. (#8977, #8811)
- Allowed backend to destroy texture while inside the NewFrame/EndFrame
scope. Basically if a backend decide to destroy a texture that we didn't request
to destroy (for e.g. freeing resources) the texture is immediately set to
a ImTextureStatus_WantCreate status again. (#8811)
- Fixed an issue preventing multi-contexts sharing a ImFontAtlas from
being possible to destroy in any order.
- Fixed not updating ImTextureData's RefCount when destroying a context
using a shared ImFontAtlas, leading standard backends to not properly
free texture resources. (#8975) [@icrashstuff]
- Demo: fixed layout issue in "Layout & Scrolling -> Scrolling" section.
- Misc: Relaxed internal assert in MarkItemEdited() to allow for more use cases. (#8997)
- Misc: Debuggers: added type formatters for the LLDB debuggers (e.g. Xcode,
Android Studio & more) to provide nicer display for ImVec2, ImVec4, ImVector etc.
See misc/debuggers/ for details. (#8950) [@mentlerd]
- CI: updated Windows CI scripts to generate/use VulkanSDK. (#8925, #8778) [@yaz0r]
- Docs: updated FAQ with new "What is the difference between Dear ImGui and
traditional UI toolkits?" entry. (#8862)
- Backends:
- All backends call ImGuiPlatformIO::ClearPlatformHandlers() and
ClearRendererHandlers() on shutdown, so as not to leave function pointers
which may be dangling when using backend in e.g. DLL. (#8945, #2769)
- DirectX12: reuse a command list and allocator for texture uploads instead
of recreating them each time. (#8963, #8465) [@RT2Code]
- DirectX12: Rework synchronization logic. (#8961) [@RT2Code]
(presumably fixes old hard-to-repro crash issues such as #3463, #5018)
- DirectX12: Reuse texture upload buffer and grow it only when
necessary. (#9002) [@RT2Code]
- DirectX12: Enable swapchain tearing if available. (#8965) [@RT2Code]
- OpenGL3: fixed GL loader to work on Haiku OS which does not support
`RTLD_NOLOAD`. (#8952) [@Xottab-DUTY, @threedeyes]
- GLFW: fixed build on platform that are neither Windows, macOS or
known Unixes (Regression in 1.92.3). (#8969, #8920, #8921) [@oktonion]
- SDL2,SDL3: avoid using the SDL_GetGlobalMouseState() path when one of our
window is hovered, as the event data is reliable and enough in this case.
- Fix mouse coordinates issue in fullscreen apps with macOS notch. (#7919, #7786)
- Essentially a workaround for SDL3 bug which will be fixed in SDL 3.3.0.
- Better perf on X11 as querying global position requires a round trip to X11 server.
- Win32: minor optimization not submitting gamepad io again if
XInput's dwPacketNumber has not changed. (#8556) [@MidTerm-CN]
- Vulkan: added a way to specify custom shaders by filling init fields
CustomShaderVertCreateInfo and CustomShaderFragCreateInfo. (#8585, #8271) [@johan0A]
- DX9,DX10,DX11,DX12,Metal,Vulkan,WGPU,SDLRenderer2,SDLRenderer3:
ensure that a texture in ImTextureStatus_WantDestroy state always turn to
ImTextureStatus_Destroyed even if your underlying graphics data was already
destroyed. (#8977)
- Examples:
- SDL2+DirectX11: Try WARP software driver if hardware driver is
not available. (#5924, #5562)
- SDL3+DirectX11: Added SDL3+DirectX11 example. (#8956, #8957) [@tomaz82]
- Win32+DirectX12: Rework synchronization logic. (#8961) [@RT2Code]
- Made examples's main.cpp consistent with returning 1 on error.
-----------------------------------------------------------------------
VERSION 1.92.3 (Released 2025-09-17)
-----------------------------------------------------------------------
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.3
Other Changes:
- Fonts: fixed merging a font and specifying a font target in DstFont
that's not the last added font (regression in 1.92). (#8912)
- Fonts: fixed an assertion failure when a rectangle entry has been reused
1024 times (e.g. due to constant change of font size). (#8906) [@cfillion]
- Clipper, Tables: added ImGuiListClipperFlags_NoSetTableRowCounters as a way to
disable the assumption that 1 clipper item == 1 table row, which breaks when
e.g. using clipper with ItemsHeight=1 in order to clip in pixel units. (#8886)
- Scrollbar, Style: added configurable style.ScrollbarPadding value and corresponding
ImGuiStyleVar_ScrollbarPadding enum, instead of an hard-coded computed default. (#8895)
- Nav: fixed Ctrl+Tab window appearing as empty when the sole active and focused
window has the ImGuiWindowFlags_NoNavFocus flag. (#8914)
- Nav: fixed a crash that could occur when opening a popup following the processing
of a global shortcut while no windows were focused.
- Bullet: fixed tessellation which looked out of place in very large sizes.
- InputText: added ImGuiInputTextFlags_WordWrap flag to word-wrap multi-line buffers.
(#3237, #952, #1062, #7363). Current caveats:
- This is marked as beta because not being tested enough.
Please report any incorrect cursor movement, selection behavior etc. bug to #3237.
- Wrapping style is not ideal. Wrapping of long words/sections (e.g. words
larger than total available width) may be particularly unpleasing.
- Wrapping width needs to always account for the possibility of a vertical scrollbar.
- It is currently much slower than regular text fields:
- Ballpark estimate of cost on my 2019 desktop PC:
For a 100 KB text buffer: +~0.3 ms/+~1.0 ms (Optimized vs Debug builds).
- The CPU cost is very roughly proportional to text length, so a 10 KB buffer
should cost about ten times less.
- InputText, InputInt, InputFloat: fixed an issue where using Escape to revert
would not write back the reverted value during the IsItemDeactivatedAfterEdit()
frame if the provided input buffer doesn't store temporary edits.
(regression in 1.91.7) (#8915, #8273)
- InputText: fixed an issue where using Escape with ImGuiInputTextFlags_EscapeClearsAll
would not write back the cleared value during the IsItemDeactivatedAfterEdit()
frame if the provided input buffer doesn't store temporary edits. (#8915, #8273)
- InputText: allow passing an empty string with buf_size==0. (#8907)
In theory the buffer size should always account for a zero-terminator, but idioms
such as using InputTextMultiline() with ImGuiInputTextFlags_ReadOnly to display
a text blob are facilitated by allowing this.
- InputText: refactored internals to simplify and optimizing rendering of selection.
Very large selection (e.g. 1 MB) now take less overhead.
- InputText: revert a change in 1.79 where pressing Down or PageDown on the last line
of a multi-line buffer without a trailing carriage return would keep the cursor
unmoved. We revert back to move to the end of line in this situation.
- InputText: fixed pressing End (without Shift) in a multi-line selection from
mistakenly moving cursor based on selection start.
- Focus, InputText: fixed an issue where SetKeyboardFocusHere() did not work
on InputTextMultiline() fields with ImGuiInputTextFlags_AllowTabInput, since
they normally inhibit activation to allow tabbing through multiple items. (#8928)
- Selectable: added ImGuiSelectableFlags_SelectOnNav to auto-select an item when
moved into, unless Ctrl is held. (automatic when in a BeginMultiSelect() block).
- TabBar: fixed an issue were forcefully selecting a tab using internal API would
be ignored on first/appearing frame before tabs are submitted (#8929, #6681)
- DrawList: fixed CloneOutput() unnecessarily taking a copy of the ImDrawListSharedData
pointer, which could to issue when deleting the cloned list. (#8894, #1860)
- DrawList: made AddCallback() assert when passing a null callback.
- Debug Tools: ID Stack Tool: fixed using fixed-size buffers preventing long identifiers
from being displayed in the tool. (#8905, #4631)
- Debug Tools: ID Stack Tool: when ### is used, uncontributing prefix before the ###
is now skipped. (#8904, #4631)
- Debug Tools: ID Stack Tool: added option to hex-encode non-ASCII characters in
output path. (#8904, #4631)
- Debug Tools: ID Stack Tool: fixed a crash when using PushOverrideID(0) during
a query. (#8937, #4631)
- Debug Tools: Fixed assertion failure when opening a combo box while using
io.ConfigDebugBeginReturnValueOnce/ConfigDebugBeginReturnValueLoop. (#8931) [@harrymander]
- Demo: tweaked ShowFontSelector() and ShowStyleSelector() to update selection
while navigating and to not close popup automatically.
- CI: Updates Windows CI to use a more recent VulkanSDK. (#8925, #8778) [@yaz0r]
- Examples: Android: Android+OpenGL3: update Gradle project (#8888, #8878) [@scribam]
- Examples: GLFW+OpenGL2, GLFW+Vulkan, GLFW+Metal, Win32+Vulkan: Fixed not applying
content scale consistently with other examples. (#8921, #8756)
- Backends: GLFW: distinguish X11 vs Wayland to fix various scaling issues.
(#8920, #8921) [@TheBrokenRail, @pthom, @ocornut]
- window/monitor content scales are always reported as 1.0 on Wayland.
- framebuffer scales are always reported as 1.0 on X11.
- Backends: SDL2: window/monitor content scales are always reported as 1.0 on Wayland.
(#8920, #8921) [@TheBrokenRail, @pthom, @ocornut]
- Backends: SDL3: use SDL_GetWindowDisplayScale() on Mac to obtain DisplayFrameBufferScale,
fixing incorrect values during resolution changes e.g. going fullscreen.
(#8703, #4414) [@jclounge]
- Backends: SDL_GPU: Added ImGui_ImplSDLGPU3_InitInfo::SwapchainComposition and
PresentMode to configure how secondary viewports are created. Currently only used
multi-viewport mode. (#8892) [@PTSVU]
- Backends: Vulkan: added ImGui_ImplVulkan_CreateMainPipeline() to recreate pipeline
without reinitializing backend. (#8110, #8111) [@SuperRonan]
-----------------------------------------------------------------------
VERSION 1.92.2b (Released 2025-08-13)
-----------------------------------------------------------------------
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.2b
Changes:
- Fixed IsItemHovered() failing on disabled items and items that have no
identifier (e.g. Text() calls) when holding mouse button. (#8877, #8883)
[Regression in 1.92.2].
- Made IsItemHovered() on holding mouse button down on disabled items not
leak between items when the window cannot be moved.
- Backends: Allegro5: Fixed texture format setup which didn't work on all
setups/drivers. (#8770, #8465)
- Backends: Allegro5: Added ImGui_ImplAllegro5_SetDisplay() function to
change current ALLEGRO_DISPLAY, as Allegro applications often need to do that.
- Backends: Allegro5: Fixed missing support for ImGuiKey_PrintScreen
under Windows, as raw Allegro 5 does not receive it.
-----------------------------------------------------------------------
VERSION 1.92.2 (Released 2025-08-11)
-----------------------------------------------------------------------
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.2
Breaking Changes:
- Tabs: Renamed ImGuiTabBarFlags_FittingPolicyResizeDown to ImGuiTabBarFlags_FittingPolicyShrink.
Kept inline redirection enum (will obsolete). (#261, #351)
- Backends: SDL_GPU3: changed ImTextureID type from SDL_GPUTextureSamplerBinding* to SDL_GPUTexture*,
which is more natural and easier for user to manage. If you need to change the current sampler,
you can access the ImGui_ImplSDLGPU3_RenderState struct. (#8866, #8163, #7998, #7988)
Other Changes:
- Fixed an old inconsistency between IsItemHovered() and internal hovering check,
where IsItemHovered() would return true to mouse was first clicked on the
background of a non-moveable window then moved over the item or button.
Note that while it is consistent with other logic, there is a possibility
that some third-party code may accidentally relied on this. One can always use
ImGuiHoveredFlags_AllowWhenBlockedByActiveItem to bypass the active id check.
(#8877) [@achabense, @ocornut]
- Fonts: fixed an issue when a font using MergeMode has a reference size
specified but the target font doesn't. Usually either all fonts should
have a reference size (only required when specifying e.g. GlyphOffset),
or none should have a reference size.
- Fonts: fixed a crash when changing texture format when using a legacy
backend. Most commonly would happen when calling GetTexDataAsRGBA32()
then immediately calling GetTexDataAsAlpha8(). (#8824)
- Windows: fixed an issue where resizable child windows would emit border
logic when hidden/non-visible (e.g. when in a docked window that is not
selected), impacting code not checking for BeginChild() return value. (#8815)
- Textures: Fixed support for `#define ImTextureID_Invalid` to non-zero value:
ImFontAtlas() was incorrectly cleared with zeroes. (#8860, #8745) [@cfillion]
- Tables: fixed TableGetRowIndex() which never correctly worked when using
a clipper (it exists for consistency but is almost never used, as it is
often more convenient to use index in caller-code, whereas TableGetRowIndex()
includes header rows).
- Tables: fixed imgui_internal.h's TableGetHoveredRow() the same way. (#7350, #6588, #6250)
- Tabs: added new fitting policy ImGuiTabBarFlags_FittingPolicyMixed
and made it the default. This policy shrink tab width down to a given amount,
and then beyond that it enable scrolling buttons. (#3421, #8800)
- Tabs: added style.TabMinWidthShrink, ImGuiStyleVar_TabMinWidthShrink to
control the width to shrink to in ImGuiTabBarFlags_FittingPolicyMixed mode.
(#3421, #8800).
- Tabs: when scrolling is enabled, track selected tabs when resizing down
parent container. This does not prevent to horizontally scroll it out of
view during normal operations. (#3421, #8800)
- Tabs: added style.TabMinWidthBase, ImGuiStyleVar_TabMinWidthBase to control
the base minimum width of a tab (default to 1.0f). This is the size before
any potential shrinking is applied.
- Tabs: fixed tab bar underline not drawing below scroll buttons, when
they are enabled (minor regression from 1.90). (#6820, #4859, #5022, #5239)
- Tabs: made scrolling buttons never keyboard/gamepad navigation candidates.
- Nav, Tables: fixed navigation within scrolling tables when item boundaries
goes beyond columns limits. The fix done in 1.89.6 didn't work correctly
on scrolling windows. (#8816, #2221)
- Nav: fixed a bug where ImGuiKey_NavGamepadMenu (==ImGuiKey_GamepadFaceLeft)
button couldn't toggle between main and menu layers while navigating a Modal
window. (#8834)
- Error Handling: minor improvements to error handling for TableGetSortSpecs()
and TableSetBgColor() calls. (#1651, #8499)
- Misc: fixed building with IMGUI_DISABLE_DEBUG_TOOLS only. (#8796)
- Misc: fixed building with IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION. (#8794)
- Misc: removed more redundant inline static linkage from imgui_internal.h to
facilitate using in C++ modules. (#8813, #8682, #8358) [@stripe2933]
- Misc: ImVector: skip memcpy in operator= if `Data` isn't initialized in order
to play nice with -fsanitize=undefined. (#8874) [@i25e]
- CI: Added SDL3 builds to MacOS and Windows. (#8819, #8778) [@scribam]
- CI: Updated Windows CI to use a more recent SDL2. (#8819, #8778) [@scribam]
- Examples: SDL3+Metal: added SDL3+Metal example. (#8827, #8825) [@shi-yan]
- Examples: SDL3+SDL_GPU: use SDL_WaitAndAcquireGPUSwapchainTexture() instead
of SDL_AcquireGPUSwapchainTexture(). (#8830) [@itsdanott]
- Examples: SDL3+SDL_GPU: use SDL_GPU_PRESENTMODE_VSYNC present mode.
- Backends: OpenGL3: add and call embedded loader shutdown in ImGui_ImplOpenGL3_Shutdown()
to facilitate multiple init/shutdown cycles in same process. (#8792) [@tim-rex]
- Backends: OpenGL2, OpenGL3: set GL_UNPACK_ALIGNMENT to 1 before updating
textures. (#8802) [@Daandelange]
- Backends: SDL_GPU3: expose current SDL_GPUSampler* in the ImGui_ImplSDLGPU3_RenderState
struct. (#8866, #8163, #7998, #7988)
- Backends: Vulkan: Fixed texture update corruption introduced in 1.92.0,
affecting some drivers/setups. (#8801, #8755, #8840) [@Retro52, @Miolith]
- Backends: Vulkan: Avoid calling vkCmdBindDescriptorSets() when texture
has not changed. (#8666) [@micb25]
-----------------------------------------------------------------------
VERSION 1.92.1 (Released 2025-07-09)
-----------------------------------------------------------------------
@@ -56,6 +755,8 @@ Changes:
to pass full range of information into e.g. FreeType's face_index, as higher
bits are used from FreeType 2.6.1. (#8775) [@Valakor]
(the field has been erroneously reduced from 32-bits to 8-bit in 1.92.0)
- Fonts, Tables: fixed PushFont() having no effect when called after submitting
a hidden column. (#8865)
- Textures: Fixed support for `#define ImTextureID_Invalid` to non-zero value:
ImTextureData() was incorrectly cleared with zeroes. (#8745) [@rachit7645]
- Demo: Added "Text -> Font Size" demo section. (#8738) [@Demonese]
@@ -64,13 +765,13 @@ Changes:
- Debug Tools: added IMGUI_DEBUG_HIGHLIGHT_ALL_ID_CONFLICTS to detect
id conflicts _before_ hovering. This is very slow and should only be used
temporarily. (#8651, #7961, #7669)
- Examples: GLFW+OpenGL3, GLFW+WGPU: Emscripten Makefiles uses GLFW port
- Examples: GLFW+OpenGL3, GLFW+WGPU: Emscripten Makefiles uses GLFW port
'contrib.glfw3' which offers better HiDPI support. (#8742) [@pthom]
- Backends: GLFW, SDL2 made ImGui_ImplGLFW_GetContentScaleXXX() and
ImGui_ImplSDL2_GetContentScaleXXXX() helpers return 1.0f on Emscripten
- Backends: GLFW, SDL2 made ImGui_ImplGLFW_GetContentScaleXXX() and
ImGui_ImplSDL2_GetContentScaleXXXX() helpers return 1.0f on Emscripten
and Android platforms, matching macOS logic. (#8742, #8733) [@pthom]
- Backends: SDL3: avoid calling SDL_StartTextInput() again if already active.
(fixes e.g.: an issue on iOS where the keyboard animation will popup every
(fixes e.g.: an issue on iOS where the keyboard animation will popup every
time the user types a key + probably other things) (#8727) [@morrazzzz]
- Backends: OSX: added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress
mouse cursor support. (#8739) [@cfillion]
@@ -162,6 +863,10 @@ Breaking changes:
- You can use `Metrics/Debugger->Fonts->Font->Input Glyphs Overlap Detection Tool` to
see list of glyphs available in multiple font sources. This can facilitate understanding
which font input is providing which glyph.
- Fonts: **IMPORTANT** on Thread Safety:
- A few functions such as font->CalcTextSizeA() were by sheer luck (== accidentally)
thread-safe even though we had never provided that guarantee before. They are
definitively not thread-safe anymore as new glyphs may be loaded.
- Textures:
- All API functions taking a 'ImTextureID' parameter are now taking a 'ImTextureRef':
@@ -198,7 +903,7 @@ Breaking changes:
to 4096 but that limit isn't necessary anymore, and Renderer_TextureMaxWidth covers this)
However you may set TexMinWidth = TexMaxWidth for the same effect.
- Fonts: if you create and manage ImFontAtlas instances yourself (instead of relying on
ImGuiContext to create one, you'll need to call ImFontAtlasUpdateNewFrame() yourself.
ImGuiContext to create one), you'll need to call ImFontAtlasUpdateNewFrame() yourself.
An assert will trigger if you don't.
- Fonts: obsoleted ImGui::SetWindowFontScale() which is not useful anymore. Prefer using
PushFont(NULL, style.FontSizeBase * factor) or to manipulate other scaling factors.
@@ -913,6 +1618,7 @@ Breaking changes:
- Commented out pre-1.87 IO system (equivalent to using IMGUI_DISABLE_OBSOLETE_KEYIO or IMGUI_DISABLE_OBSOLETE_FUNCTIONS before).
- io.KeyMap[] and io.KeysDown[] are removed (obsoleted February 2022). Use IsKeyDown() instead.
- io.NavInputs[] and ImGuiNavInput are removed (obsoleted July 2022).
- GetKeyIndex() is removed (obsoleted March 2022). The indirection is now unnecessary.
- Pre-1.87 backends are not supported:
- backends need to call io.AddKeyEvent(), io.AddMouseEvent() instead of writing to io.KeysDown[], io.MouseDown[] fields.
- backends need to call io.AddKeyAnalogEvent() for gamepad values instead of writing to io.NavInputs[] fields.
@@ -980,7 +1686,7 @@ Breaking changes:
allows casting any pointer/integer type without warning:
- May warn: ImGui::Image((void*)MyTextureData, ...);
- May warn: ImGui::Image((void*)(intptr_t)MyTextureData, ...);
- Won't warn: ImGui::Image((ImTextureID)(intptr_t)MyTextureData), ...);
- Won't warn: ImGui::Image((ImTextureID)(intptr_t)MyTextureData, ...);
- Note that you can always define ImTextureID to be your own high-level structures
(with dedicated constructors and extra render parameters) if you like.
- IO: moved ImGuiConfigFlags_NavEnableSetMousePos to standalone io.ConfigNavMoveSetMousePos bool.
@@ -4350,7 +5056,7 @@ Breaking Changes:
- ShowTestWindow() -> use ShowDemoWindow()
- IsRootWindowFocused() -> use IsWindowFocused(ImGuiFocusedFlags_RootWindow)
- IsRootWindowOrAnyChildFocused() -> use IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows)
- SetNextWindowContentWidth(w) -> use SetNextWindowContentSize(ImVec2(w, 0.0f)
- SetNextWindowContentWidth(w) -> use SetNextWindowContentSize(ImVec2(w, 0.0f))
- GetItemsLineHeightWithSpacing() -> use GetFrameHeightWithSpacing()
- ImGuiCol_ChildWindowBg -> use ImGuiCol_ChildBg
- ImGuiStyleVar_ChildWindowRounding -> use ImGuiStyleVar_ChildRounding

View File

@@ -72,7 +72,7 @@ OSX + OpenGL2 example. <BR>
You may prefer to use the GLFW Or SDL backends, which will also support Windows and Linux.)
[example_glfw_wgpu/](https://github.com/ocornut/imgui/blob/master/examples/example_glfw_wgpu/) <BR>
GLFW + WebGPU example. Supports Emscripten (web) or Dawn (desktop) <BR>
GLFW + WebGPU example. Supports Emscripten (web), Dawn (native), WGPU (native). <BR>
= main.cpp + imgui_impl_glfw.cpp + imgui_impl_wgpu.cpp
Note that the 'example_glfw_opengl3' and 'example_sdl2_opengl3' examples also supports Emscripten!
@@ -109,9 +109,11 @@ Note that GLUT/FreeGLUT is largely obsolete software, prefer using GLFW or SDL.
[example_null/](https://github.com/ocornut/imgui/blob/master/examples/example_null/) <BR>
Null example, compile and link imgui, create context, run headless with no inputs and no graphics output. <BR>
= main.cpp <BR>
= main.cpp + imgui_impl_null.cpp<BR>
This is used to quickly test compilation of core imgui files in as many setups as possible.
Because this application doesn't create a window nor a graphic context, there's no graphics output.
Please note that imgui_impl_null itself is a rather empty backend. We provide it for consistency but
it is similarly easy to create a skeleton application without the null backend.
[example_sdl2_directx11/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_directx11/) <BR>
SDL2 + DirectX11 example, Windows only. <BR>
@@ -149,6 +151,19 @@ SDL2 (Win32, Mac, Linux, etc.) + Vulkan example. <BR>
This is quite long and tedious, because: Vulkan. <BR>
For this example, the main.cpp file exceptionally use helpers function from imgui_impl_vulkan.h/cpp.
[example_sdl2_wgpu/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_wgpu/) <BR>
SDL2 + WebGPU example. Supports Emscripten (web), Dawn (native), WGPU (native). <BR>
= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_wgpu.cpp
(note that the 'example_sdl2_opengl3' example also supports Emscripten!)
[example_sdl3_directx11/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_directx11/) <BR>
SDL3 + DirectX11 examples, Windows only. <BR>
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_dx11.cpp <BR>
[example_sdl3_metal/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_metal/) <BR>
SDL3 + Metal example, Mac only. <BR>
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_metal.mm <BR>
[example_sdl3_opengl3/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_opengl3/) <BR>
SDL3 (Win32, Mac, Linux, etc.) + OpenGL3+/ES2/ES3 example. <BR>
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_opengl3.cpp <BR>
@@ -169,6 +184,11 @@ SDL3 (Win32, Mac, Linux, etc.) + Vulkan example. <BR>
This is quite long and tedious, because: Vulkan. <BR>
For this example, the main.cpp file exceptionally use helpers function from imgui_impl_vulkan.h/cpp.
[example_sdl3_wgpu/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_wgpu/) <BR>
SDL3 + WebGPU example. Supports Emscripten (web), Dawn (native), WGPU (native). <BR>
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_wgpu.cpp
(note that the 'example_sdl3_opengl3' example also supports Emscripten!)
[example_win32_directx9/](https://github.com/ocornut/imgui/blob/master/examples/example_win32_directx9/) <BR>
DirectX9 example, Windows only. <BR>
= main.cpp + imgui_impl_win32.cpp + imgui_impl_dx9.cpp

View File

@@ -13,13 +13,14 @@ or view this file with any Markdown viewer.
:---------------------------------------------------------- |
| [Where is the documentation?](#q-where-is-the-documentation) |
| [What is this library called?](#q-what-is-this-library-called) |
| [What is the difference between Dear ImGui and traditional UI toolkits?](#q-what-is-the-difference-between-dear-imgui-and-traditional-ui-toolkits) |
| [Which version should I get?](#q-which-version-should-i-get) |
| **Q&A: Integration** |
| **[How to get started?](#q-how-to-get-started)** |
| **[How can I tell whether to dispatch mouse/keyboard to Dear ImGui or my application?](#q-how-can-i-tell-whether-to-dispatch-mousekeyboard-to-dear-imgui-or-my-application)** |
| [How can I enable keyboard or gamepad controls?](#q-how-can-i-enable-keyboard-or-gamepad-controls) |
| [How can I use this on a machine without mouse, keyboard or screen? (input share, remote display)](#q-how-can-i-use-this-on-a-machine-without-mouse-keyboard-or-screen-input-share-remote-display) |
| [How can I create my own backend?](q-how-can-i-create-my-own-backend)
| [How can I create my own backend?](#q-how-can-i-create-my-own-backend)
| [I integrated Dear ImGui in my engine and little squares are showing instead of text...](#q-i-integrated-dear-imgui-in-my-engine-and-little-squares-are-showing-instead-of-text) |
| [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) |
@@ -75,6 +76,60 @@ or view this file with any Markdown viewer.
---
### Q: What is the difference between Dear ImGui and traditional UI toolkits?
Here's a very simplified comparison between the approach taken by Dear ImGui vs traditional toolkits:
| Dear ImGui | Qt/GTK/WPF... |
|--------------------------|--------------------------|
| UI fully issued on every update. | UI issued once then later modified. |
| UI layout is fully dynamic and can change at any time.<BR>UI is generally emitted programmatically, which empowers reflecting a dynamic set of data. | UI layout is mostly static.<BR>UI may be emitted programmatically or from data created by offline tools. UI need extra code to evolve, which is often tedious and error-prone if it needs to be reflecting dynamic data and systems. |
| Application can submit UI based on arbitrary logic and then forget about it. | Application needs more bookkeeping of UI elements. |
| UI library stores minimal amounts of data. At one point in time, it typically doesn't know or remember which other widgets are displayed and which widgets are coming next. As a result, certain layout features (alignment, resizing) are not as easy to implement or require ad-hoc code. | UI library stores entire widgets tree and state. UI library can use this retained data to easily layout things. |
| UI code may be added anywhere.<BR>You can even create UI to edit a local variable! | UI code needs to be added in dedicated spots. |
| UI layout/logic/action/data bindings are all nearby in the code. | UI layout/logic/action/data bindings in distinct functions, files or formats. |
| Data is naturally always synchronized. | Use callback/signal/slot for synchronizing data (error-prone). |
| API is simple and easy to learn. In particular, doing basic things is very easy. | API is more complex and specialized. |
| API is low-level (raw language types). | API are higher-level (more abstractions, advanced language features). |
| Less fancy look and feel. | Standard look and feel. |
| Compile yourself. Easy to debug, hack, modify, study. | Mostly use precompiled libraries. Compiling, modifying or studying is daunting if not impossible. |
| Run on every platform. | Run on limited desktop platforms. |
Idiomatic Dear ImGui code:
```cpp
if (ImGui::Button("Save"))
MySaveFunction();
ImGui::SliderFloat("Slider", &m_MyValue, 0.0f, 1.0f);
```
Idiomatic code with traditional toolkit:
```cpp
UiButton* button = new UiButton("Save");
button->OnClick = &MySaveFunction;
parent->Add(button);
UiSlider* slider = new UiSlider("Slider");
slider->SetRange(0.0f, 1.0f);
slider->BindData<float>(&m_MyValue);
parent->Add(slider);
```
This is only meant to give you a intuitive feeling of the main differences, but pros & cons go deeper than that.
Some of those properties are typically associated to the umbrella term "IMGUI", but the term has no simple and well-agreed definition. There are many erroneous statements and misunderstandings with what IMGUI means. It is partly caused by the fact that most popular IMGUI implementations (including Dear ImGui) have originated from game industry needs and have targeted specific use cases, causing people to conflate IMGUI properties with what a specific library does. However, it is perfectly possible to implement an IMGUI library that would have very different properties than e.g. Dear ImGui. My take on defining what an IMGUI is:
**IMGUI refers to the API: literally the interface between the application and the UI system.**
- An IMGUI API favors the application code owning its data and being the single source of truth for it.
- An IMGUI API tries to minimize the application having to retain/manage data related to the UI system.
- An IMGUI API tries to minimize the UI system having to retain/manage data related to the application.
- Synchronization between application data and UI data is natural and less error-prone.
**IMGUI does NOT refer to the implementation. Whatever happens inside the UI library code doesn't matter.**
<BR>Also see: [Links to many articles about the IMGUI paradigm](https://github.com/ocornut/imgui/wiki/#about-the-imgui-paradigm).
##### [Return to Index](#index)
---
### Q: Which version should I get?
I occasionally tag [Releases](https://github.com/ocornut/imgui/releases) but it is generally safe and recommended to sync to master/latest. The library is fairly stable and regressions tend to be fixed fast when reported.
@@ -389,8 +444,8 @@ node open/closed state differently. See what makes more sense in your situation!
### Q: What are ImTextureID/ImTextureRef?
**Short explanation:**
- Refer to [Image Loading and Displaying Examples](https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples) on the [Wiki](https://github.com/ocornut/imgui/wiki).
- You may use functions such as `ImGui::Image()`, `ImGui::ImageButton()` or lower-level `ImDrawList::AddImage()` to emit draw calls that will use your own textures.
- To load and display your own textures, refer to [Image Loading and Displaying Examples](https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples) on the [Wiki](https://github.com/ocornut/imgui/wiki).
- Actual textures are identified in a way that is up to the user/engine. Those identifiers are stored and passed as an opaque ImTextureID value.
- By default ImTextureID can store up to 64-bits. You may `#define` it to a custom type/structure if you need.
- Loading image files from the disk and turning them into a texture is not within the scope of Dear ImGui (for a good reason), but the examples linked above may be useful references.
@@ -398,12 +453,20 @@ node open/closed state differently. See what makes more sense in your situation!
**Details:**
1.92 introduced `ImTextureRef` in June 2025.
- Most drawing functions using ImTextureID were changed to use ImTextureRef.
- We intentionally do not provide an implicit ImTextureRef -> ImTextureID cast operator because it is technically lossy to convert ImTextureRef to ImTextureID before rendering.
- All drawing functions using `ImTextureID` were changed to use `ImTextureRef`.
- You can trivially create a `ImTextureRef` from a `ImTextureID`.
- **If you use Image functions with textures that you have loaded/created yourself, you will mostly likely only ever store/manipulate `ImTextureID` and then pass them as `ImTextureRef`.**
- You only NEED to manipulate `ImTextureRef` when dealing with textures managed by the backend itself, aka mainly the atlas texture for now.
- We intentionally do not provide an implicit `ImTextureRef` -> `ImTextureID` cast operator because it is technically lossy to convert ImTextureRef to ImTextureID before rendering.
**ImTextureID = backend specific, low-level identifier for a texture uploaded in GPU/graphics system.**
```cpp
#ifndef ImTextureID
typedef ImU64 ImTextureID; // Default: store up to 64-bits (any pointer or integer). A majority of backends are ok with that.
#endif
```
- When a Rendered Backend creates a texture, it store its native identifier into a ImTextureID value (e.g. Used by DX11 backend to a `ID3D11ShaderResourceView*`; Used by OpenGL backends to store `GLuint`; Used by SDLGPU backend to store a `SDL_GPUTextureSamplerBinding*`, etc.).
- User may submit their own textures to e.g. ImGui::Image() function by passing the same type.
- User may submit their own textures to e.g. `ImGui::Image()` function by passing this value.
- During the rendering loop, the Renderer Backend retrieve the ImTextureID, which stored inside a ImTextureRef, which is stored inside ImDrawCmd.
- Compile-time type configuration:
- To use something other than a 64-bit value: add '#define ImTextureID MyTextureType*' in your imconfig.h file.
@@ -411,13 +474,29 @@ node open/closed state differently. See what makes more sense in your situation!
- You may decide to store a higher-level structure containing texture, sampler, shader etc. with various constructors if you like. You will need to implement ==/!= operators.
**ImTextureRef = higher-level identifier for a texture.**
```cpp
// Store a ImTextureID _or_ a ImTextureData*.
struct ImTextureRef
{
ImTextureRef() { _TexData = NULL; _TexID = ImTextureID_Invalid; }
ImTextureRef(ImTextureID tex_id) { _TexData = NULL; _TexID = tex_id; }
inline ImTextureID GetTexID() const { return _TexData ? _TexData->TexID : _TexID; }
// Members (either are set, never both!)
ImTextureData* _TexData; // A texture, generally owned by a ImFontAtlas. Will convert to ImTextureID during render loop, after texture has been uploaded.
ImTextureID _TexID; // _OR_ Low-level backend texture identifier, if already uploaded or created by user/app. Generally provided to e.g. ImGui::Image() calls.
};
```
- The identifier is valid even before the texture has been uploaded to the GPU/graphics system.
- This is what gets passed to functions such as `ImGui::Image()`, `ImDrawList::AddImage()`.
- This is what gets stored in draw commands (`ImDrawCmd`) to identify a texture during rendering.
- When a texture is created by user code (e.g. custom images), we directly stores the low-level `ImTextureID`.
- When a texture is created by the backend, we stores a `ImTextureData*` which becomes an indirection to extract the `ImTextureID` value during rendering, after texture upload has happened.
- There is no constructor to create a `ImTextureID` from a `ImTextureData*` as we don't expect this to be useful to the end-user, and it would be erroneously called by many legacy code.
- If you want to bind the current atlas when using custom rectangle, you can use `io.Fonts->TexRef`.
- When a texture is created by user code (e.g. custom images), we directly store the low-level `ImTextureID`.
- Because of this, when displaying your own texture you are likely to ever only manage ImTextureID values on your side.
- When a texture is created by the backend, we store a `ImTextureData*` which becomes an indirection to extract the `ImTextureID` value during rendering, after texture upload has happened.
- To create a `ImTextureRef` from a `ImTextureData*` you can use `ImTextureData::GetTexRef()`.
We intentionally do not provide an `ImTextureRef` constructor for this: we don't expect this to be frequently useful to the end-user, and it would be erroneously called by many legacy code.
- There is no constructor to create a `ImTextureRef` from a `ImTextureData*` as we don't expect this to be useful to the end-user, and it would be erroneously called by many legacy code.
- If you want to bind the current atlas when using custom rectangles, you can use `io.Fonts->TexRef`.
- Binding generators for languages such as C (which don't have constructors), should provide a helper, e.g. `inline ImTextureRef ImTextureRefFromID(ImTextureID tex_id) { ImTextureRef tex_ref = { ._TexData = NULL, .TexID = tex_id }; return tex_ref; }`
**Please read documentations or tutorials on your graphics API to understand how to display textures on the screen before moving onward.**
@@ -579,22 +658,28 @@ Since 1.92 (June 2025) fonts may be dynamically used at any size.
**Scaling fonts**
Select default size:
```cpp
style.FontSizeBase = 20.0f;
```
Scale all fonts:
```cpp
style.FontScaleDpi = 2.0f;
```
To change font size:
```cpp
ImGui::PushFont(NULL, 42.0f);
ImGui::PushFont(NULL, 42.0f); // This will be multiplied by style.FontScaleDpi
```
To change font and font size:
```cpp
ImGui::PushFont(new_font, 42.0f);
```
To scale all fonts:
```cpp
style.FontScaleDpi = 2.0f;
```
In `docking` branch or with multi-viewports:
```cpp
io.ConfigDpiScaleFonts = true; // [Experimental] Automatically overwrite style.FontScaleDpi in Begin() when Monitor DPI changes. This will scale fonts but _NOT_ scale sizes/padding for now.
io.ConfigDpiScaleViewports = true; // [Experimental] Scale Dear ImGui and Platform Windows when Monitor DPI changes.
io.ConfigDpiScaleFonts = true; // (Docking branch only) Automatically overwrite style.FontScaleDpi in Begin() when Monitor DPI changes. This will scale fonts but _NOT_ scale sizes/padding for now.
io.ConfigDpiScaleViewports = true; // (Docking branch only) Scale Dear ImGui and Platform Windows when Monitor DPI changes.
```
**Scaling style** (paddings, spacings, thicknesses)

View File

@@ -2,10 +2,20 @@ _(You may browse this at https://github.com/ocornut/imgui/blob/master/docs/FONTS
## Dear ImGui: Using Fonts
The code in imgui.cpp embeds a copy of [ProggyClean.ttf](http://proggyfonts.net) (by Tristan Grimmer),
a 13 pixels high, pixel-perfect font used by default. We embed it in the source code so you can use Dear ImGui without any file system access. ProggyClean does not scale smoothly, therefore it is recommended that you load your own file when using Dear ImGui in an application aiming to look nice and wanting to support multiple resolutions.
The code in Dear ImGui embeds a copy of [ProggyClean.ttf](https://github.com/bluescan/proggyfonts) by Tristan Grimmer,
a 13 pixels high, pixel-perfect font used by default. ProggyClean does not scale very nicely.
You may also load external .TTF/.OTF files.
The code in Dear ImGui embeds a partial copy of [ProggyForever.ttf](https://github.com/ocornut/proggyforever) by Disco Hello & Tristan Grimmer,
a new font mimicking ProggyClean which does scale nicely.
We embed fonts in the code so you can use Dear ImGui without any file system access.
If you don't use them you can set `IMGUI_DISABLE_DEFAULT_FONT` in your [imconfig.h](https://github.com/ocornut/imgui/blob/master/imconfig.h) file to ship binaries without the fonts and save about ~26 KB.
Calling io.Fonts->AddFontDefaultVector() loads ProggyForever.
Calling io.Fonts->AddFontDefaultBitmap() loads ProggyClean.
Calling io.Fonts->AddFontDefault() selects one based on the expected default font size (when `style.FontSizeBase * style.FontScaleMain * style.FontSizeDpi >= 15` we use ProggyForever).
You may also load external .TTF/.OTF files, see instructions on this page.
In the [misc/fonts/](https://github.com/ocornut/imgui/tree/master/misc/fonts) folder you can find a few suggested fonts, provided as a convenience.
**Also read the FAQ:** https://www.dearimgui.com/faq (there is a Fonts section!)
@@ -89,7 +99,10 @@ See [#8465](https://github.com/ocornut/imgui/issues/8465) for more details.
## How should I handle DPI in my application?
See [FAQ entry](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#q-how-should-i-handle-dpi-in-my-application).
Since 1.92, with an updated backend, you can set `style.FontScaleDpi = your_content_scale;` to scale all fonts.
<BR>You can call `style.ScaleAllSizes(xxx)` at init time or every frame at the beginning of your main loop to scale sizes/paddings.
<BR>Since 1.92, with an updated backend, macOS style pixel/backing style scale is automatically handled.
<BR>See [FAQ entry](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#q-how-should-i-handle-dpi-in-my-application) for more details.
##### [Return to Index](#index)
@@ -97,10 +110,22 @@ See [FAQ entry](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#q-how-s
## Fonts Loading Instructions
**Select base size**
```cpp
ImGuiStyle& style = ImGui::GetStyle();
style.FontSizeBase = 20.0f;
```
**Load default font:**
```cpp
ImGuiIO& io = ImGui::GetIO();
io.Fonts->AddFontDefault();
io.Fonts->AddFontDefaultVector(); // Load embedded scalable font.
```
```cpp
io.Fonts->AddFontDefaultBitmap(); // Load embedded bitmap font (legacy).
```
```cpp
io.Fonts->AddFontDefault(); // Load embedded font (legacy: auto-selected between the two above).
```
**Load .TTF/.OTF file with:**
@@ -145,12 +170,11 @@ ImFont* font = io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, &config);
🆕 **Since 1.92, with an up to date backend: specifying glyph ranges is unnecessary.**
```cpp
// Load a first font
ImFont* font = io.Fonts->AddFontDefault();
ImFont* font = io.Fonts->AddFontDefaultVector();
ImFontConfig config;
config.MergeMode = true;
io.Fonts->AddFontFromFileTTF("DroidSans.ttf", 0.0f, &config); // Merge into first font to add e.g. Asian characters
io.Fonts->AddFontFromFileTTF("fontawesome-webfont.ttf", 0.0f, &config); // Merge into first font to add Icons
io.Fonts->Build();
```
:rewind: **Before 1.92, or without an up to date backend:**
```cpp
@@ -203,7 +227,7 @@ if (ImGui::Button(u8"ロード"))
{
// do stuff
}
ImGui::InputText("string", buf, IM_ARRAYSIZE(buf));
ImGui::InputText("string", buf, IM_COUNTOF(buf));
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
```
@@ -229,6 +253,7 @@ ImFontConfig font_cfg;
font_cfg.FontDataOwnedByAtlas = false;
ImFont* font = io.Fonts->AddFontFromMemoryTTF(data, data_size, size_pixels, &font_cfg);
```
IMPORTANT: Since 1.92, when using `FontDataOwnedByAtlas = false`, font data needs to available until `atlas->RemoveFont()`, or more typically until a shutdown of the owning context or font atlas. It was not immediately noticeable in 1.92.0 due to a bug in handling `FontDataOwnedByAtlas = false`, which was fixed in 1.92.6.
##### [Return to Index](#index)
@@ -269,7 +294,7 @@ Example Setup:
// Merge icons into default tool font
#include "IconsFontAwesome.h"
ImGuiIO& io = ImGui::GetIO();
io.Fonts->AddFontDefault();
io.Fonts->AddFontDefaultVector();
ImFontConfig config;
config.MergeMode = true;
config.GlyphMinAdvanceX = 13.0f; // Use if you want to make the icon monospaced
@@ -426,7 +451,7 @@ As an alternative to rendering colorful glyphs using imgui_freetype with `ImGuiF
#### Pseudo-code:
```cpp
// Add font, then register two custom 13x13 rectangles mapped to glyph 'a' and 'b' of this font
ImFont* font = io.Fonts->AddFontDefault();
ImFont* font = io.Fonts->AddFontDefaultVector();
int rect_ids[2];
rect_ids[0] = io.Fonts->AddCustomRectFontGlyph(font, 'a', 13, 13, 13+1);
rect_ids[1] = io.Fonts->AddCustomRectFontGlyph(font, 'b', 13, 13, 13+1);
@@ -439,7 +464,7 @@ unsigned char* tex_pixels = nullptr;
int tex_width, tex_height;
io.Fonts->GetTexDataAsRGBA32(&tex_pixels, &tex_width, &tex_height);
for (int rect_n = 0; rect_n < IM_ARRAYSIZE(rect_ids); rect_n++)
for (int rect_n = 0; rect_n < IM_COUNTOF(rect_ids); rect_n++)
if (const ImTextureRect* rect = io.Fonts->GetCustomRect(rect_ids[rect_n]))
{
// Fill the custom rectangle with red pixels (in reality you would draw/copy your bitmap data here!)
@@ -539,7 +564,20 @@ You can use the `UTF-8 Encoding viewer` in `Metrics/Debugger` to verify the cont
## Credits/Licenses For Fonts Included In Repository
Some fonts files are available in the `misc/fonts/` folder:
Embedded in source code:
**ProggyClean.ttf**, by Tristan Grimmer
<br>MIT License
<br>(recommended loading setting: Size = 13.0, GlyphOffset.y = +1, PixelSnapH = true)
<br>https://github.com/bluescan/proggyfonts
**ProggyForever.ttf**, by Disco Hello, Tristan Grimmer
<BR>MIT License
<BR>https://github.com/ocornut/proggyforever
Extra fonts files are available in the `misc/fonts/` folder.
Compared to 2014 when they were first introduced, we now have better font support and we embed ProggyForever.
I believe all the files here are unnecessary nowadays. You can find font yourself. They might eventually be removed.
**Roboto-Medium.ttf**, by Christian Robetson
<br>Apache License 2.0
@@ -554,15 +592,10 @@ Some fonts files are available in the `misc/fonts/` folder:
<br>Apache License 2.0
<br>https://www.fontsquirrel.com/fonts/droid-sans
**ProggyClean.ttf**, by Tristan Grimmer
<br>MIT License
<br>(recommended loading setting: Size = 13.0, GlyphOffset.y = +1)
<br>http://www.proggyfonts.net/
**ProggyTiny.ttf**, by Tristan Grimmer
<br>MIT License
<br>(recommended loading setting: Size = 10.0, GlyphOffset.y = +1)
<br>http://www.proggyfonts.net/
<br>https://github.com/bluescan/proggyfonts
**Karla-Regular.ttf**, by Jonathan Pinhorn
<br>SIL OPEN FONT LICENSE Version 1.1
@@ -588,15 +621,14 @@ Some fonts files are available in the `misc/fonts/` folder:
#### MONOSPACE FONTS
Pixel Perfect:
- Proggy Fonts, by Tristan Grimmer http://www.proggyfonts.net or http://upperboundsinteractive.com/fonts.php
- Sweet16, Sweet16 Mono, by Martin Sedlak (Latin + Supplemental + Extended A) https://github.com/kmar/Sweet16Font (also include an .inl file to use directly in dear imgui.)
<img width="1172" height="715" alt="image" src="https://github.com/user-attachments/assets/c9702534-4877-41c9-ae0d-252933c26ced" />
Regular:
- Google Noto Mono Fonts https://www.google.com/get/noto/
- Typefaces for source code beautification https://github.com/chrissimpkins/codeface
- Programmation fonts http://s9w.github.io/font_compare/
- Inconsolata http://www.levien.com/type/myfonts/inconsolata.html
- Proggy Fonts, by Tristan Grimmer https://github.com/bluescan/proggyfonts
- Sweet16, Sweet16 Mono, by Martin Sedlak (Latin + Supplemental + Extended A) https://github.com/kmar/Sweet16Font
- Google Noto Mono Fonts: https://www.google.com/get/noto/
- Typefaces for source code beautification: https://github.com/chrissimpkins/codeface
- Programmation fonts: http://s9w.github.io/font_compare/
- Inconsolata: http://www.levien.com/type/myfonts/inconsolata.html
- Adobe Source Code Pro: Monospaced font family for ui & coding environments https://github.com/adobe-fonts/source-code-pro
- Monospace/Fixed Width Programmer's Fonts http://www.lowing.org/fonts/

View File

@@ -16,7 +16,7 @@ Businesses: support continued development and maintenance via invoiced sponsorin
| [The Pitch](#the-pitch) - [Usage](#usage) - [How it works](#how-it-works) - [Releases & Changelogs](#releases--changelogs) - [Demo](#demo) - [Getting Started & Integration](#getting-started--integration) |
:----------------------------------------------------------: |
| [Gallery](#gallery) - [Support, FAQ](#support-frequently-asked-questions-faq) - [How to help](#how-to-help) - **[Funding & Sponsors](https://github.com/ocornut/imgui/wiki/Funding)** - [Credits](#credits) - [License](#license) |
| [Wiki](https://github.com/ocornut/imgui/wiki) - [Extensions](https://github.com/ocornut/imgui/wiki/Useful-Extensions) - [Languages bindings & frameworks backends](https://github.com/ocornut/imgui/wiki/Bindings) - [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) - [User quotes](https://github.com/ocornut/imgui/wiki/Quotes) |
| [Wiki](https://github.com/ocornut/imgui/wiki) - [Extensions](https://github.com/ocornut/imgui/wiki/Useful-Extensions) - [Language bindings & framework backends](https://github.com/ocornut/imgui/wiki/Bindings) - [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) - [User quotes](https://github.com/ocornut/imgui/wiki/Quotes) |
### The Pitch
@@ -39,10 +39,12 @@ Dear ImGui is particularly suited to integration in game engines (for tooling),
### Usage
**The core of Dear ImGui is self-contained within a few platform-agnostic files** which you can easily compile in your application/engine. They are all the files in the root folder of the repository (imgui*.cpp, imgui*.h). **No specific build process is required**. You can add the .cpp files into your existing project.
**The core of Dear ImGui is self-contained within a few platform-agnostic files** which you can easily compile in your application/engine. They are all the files in the root folder of the repository (`imgui*.cpp`, `imgui*.h`). **No specific build process is required**: you can add all files into your existing project.
**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.
See the [Getting Started & Integration](#getting-started--integration) section of this document for more details.
After Dear ImGui is set up in your application, you can use it from \_anywhere\_ in your program loop:
@@ -50,7 +52,7 @@ After Dear ImGui is set up in your application, you can use it from \_anywhere\_
ImGui::Text("Hello, world %d", 123);
if (ImGui::Button("Save"))
MySaveFunction();
ImGui::InputText("string", buf, IM_ARRAYSIZE(buf));
ImGui::InputText("string", buf, IM_COUNTOF(buf));
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
```
![sample code output (dark, segoeui font, freetype)](https://user-images.githubusercontent.com/8225057/191050833-b7ecf528-bfae-4a9f-ac1b-f3d83437a2f4.png)
@@ -107,22 +109,26 @@ Reading the changelogs is a good way to keep up to date with the things Dear ImG
### Demo
Calling the `ImGui::ShowDemoWindow()` function will create a demo window showcasing a variety of features and examples. The code is always available for reference in `imgui_demo.cpp`. [Here's how the demo looks](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v167/v167-misc.png).
Calling the `ImGui::ShowDemoWindow()` function will create a demo window showcasing a variety of features and examples. The code is always available for reference in `imgui_demo.cpp`.
- [Web version of the demo](https://pthom.github.io/imgui_manual_online/manual/imgui_manual.html) courtesy of [@pthom](https://github.com/pthom).
- [Screenshot of the demo](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v167/v167-misc.png).
You should be able to build the examples from sources. If you don't, let us know! If you want to have a quick look at some Dear ImGui features, you can download Windows binaries of the demo app here:
- [imgui-demo-binaries-20250625.zip](https://www.dearimgui.com/binaries/imgui-demo-binaries-20250625.zip) (Windows, 1.92.0, built 2025/06/25, master) or [older binaries](https://www.dearimgui.com/binaries).
The demo applications are not DPI aware so expect some blurriness on a 4K screen. For DPI awareness in your application, you can load/reload your font at a different scale and scale your style with `style.ScaleAllSizes()` (see [FAQ](https://www.dearimgui.com/faq)).
### Getting Started & Integration
See the [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) guide for details.
On most platforms and when using C++, **you should be able to use a combination of the [imgui_impl_xxxx](https://github.com/ocornut/imgui/tree/master/backends) backends without modification** (e.g. `imgui_impl_win32.cpp` + `imgui_impl_dx11.cpp`). If your engine supports multiple platforms, consider using more imgui_impl_xxxx files instead of rewriting them: this will be less work for you, and you can get Dear ImGui running immediately. You can _later_ decide to rewrite a custom backend using your custom engine functions if you wish so.
Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/keyboard/gamepad inputs 2) uploading a texture to your GPU/render engine 3) providing a render function that can bind textures and render textured triangles, which is essentially what Backends are doing. The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications doing just that: setting up a window and using backends. If you follow the [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) guide it should in theory take you less than an hour to integrate Dear ImGui. **Make sure to spend time reading the [FAQ](https://www.dearimgui.com/faq), comments, and the examples applications!**
Integrating Dear ImGui within your custom engine is a matter of mainly 1) wiring mouse/keyboard/gamepad inputs 2) uploading a texture to your GPU/render engine 3) providing a render function that can create/update textures and render textured triangles. This is exactly what backends are doing.
- The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications setting up a window and using standard backends.
- The [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) guide has instructions to integrate imgui into an existing application using standard backends. It should in theory take you less than an hour to integrate Dear ImGui into your existing codebase where support libraries are linked. Less if you read carefully.
- The [Backends](https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md) guide explains what backends are doing, and has instructions to implement a custom backend. You can also refer to the source code of our ~20 backends to understand how they work.
- Generally, **make sure to spend time reading the [FAQ](https://www.dearimgui.com/faq), comments, and the examples applications!**
Officially maintained backends/bindings (in repository):
Officially maintained backends (in repository):
- Renderers: DirectX9, DirectX10, DirectX11, DirectX12, Metal, OpenGL/ES/ES2, SDL_GPU, SDL_Renderer2/3, Vulkan, WebGPU.
- Platforms: GLFW, SDL2/SDL3, Win32, Glut, OSX, Android.
- Frameworks: Allegro5, Emscripten.
@@ -130,7 +136,7 @@ Officially maintained backends/bindings (in repository):
[Third-party backends/bindings](https://github.com/ocornut/imgui/wiki/Bindings) wiki page:
- Languages: C, C# and: Beef, ChaiScript, CovScript, Crystal, D, Go, Haskell, Haxe/hxcpp, Java, JavaScript, Julia, Kotlin, Lobster, Lua, Nim, Odin, Pascal, PureBasic, Python, ReaScript, Ruby, Rust, Swift, Zig...
- Frameworks: AGS/Adventure Game Studio, Amethyst, Blender, bsf, Cinder, Cocos2d-x, Defold, Diligent Engine, Ebiten, Flexium, GML/Game Maker Studio, GLEQ, Godot, GTK3, Irrlicht Engine, JUCE, LÖVE+LUA, Mach Engine, Magnum, Marmalade, Monogame, NanoRT, nCine, Nim Game Lib, Nintendo 3DS/Switch/WiiU (homebrew), Ogre, openFrameworks, OSG/OpenSceneGraph, Orx, Photoshop, px_render, Qt/QtDirect3D, raylib, SFML, Sokol, Unity, Unreal Engine 4/5, UWP, vtk, VulkanHpp, VulkanSceneGraph, Win32 GDI, WxWidgets.
- Many bindings are auto-generated (by good old [cimgui](https://github.com/cimgui/cimgui) or newer/experimental [dear_bindings](https://github.com/dearimgui/dear_bindings)), you can use their metadata output to generate bindings for other languages.
- Many bindings are auto-generated (by good old [cimgui](https://github.com/cimgui/cimgui) or our newer [dear_bindings](https://github.com/dearimgui/dear_bindings)), you can use their metadata output to generate bindings for other languages.
[Useful Extensions/Widgets](https://github.com/ocornut/imgui/wiki/Useful-Extensions) wiki page:
- 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).
@@ -184,7 +190,7 @@ How to help
- See [GitHub Forum/Issues](https://github.com/ocornut/imgui/issues).
- You may help with development and submit pull requests! Please understand that by submitting a PR you are also submitting a request for the maintainer to review your code and then take over its maintenance forever. PR should be crafted both in the interest of the end-users and also to ease the maintainer into understanding and accepting it.
- See [Help wanted](https://github.com/ocornut/imgui/wiki/Help-Wanted) on the [Wiki](https://github.com/ocornut/imgui/wiki/) for some more ideas.
- Be a [Funding Supporter](https://github.com/ocornut/imgui/wiki/Funding)! Have your company financially support this project via invoiced sponsors/maintenance or by buying a license for [Dear ImGui Test Engine](https://github.com/ocornut/imgui_test_engine) (please reach out: omar AT dearimgui DOT com).
- Be a [Funding Supporter](https://github.com/ocornut/imgui/wiki/Funding)! Have your company financially support this project via invoiced sponsors/maintenance or by buying a license for [Dear ImGui Test Engine](https://github.com/ocornut/imgui_test_engine) (please reach out: contact AT dearimgui DOT com).
Sponsors
--------
@@ -203,7 +209,7 @@ Dear ImGui is using software and services provided free of charge for open sourc
Credits
-------
Developed by [Omar Cornut](https://www.miracleworld.net) and every direct or indirect [contributors](https://github.com/ocornut/imgui/graphs/contributors) to the GitHub. The early version of this library was developed with the support of [Media Molecule](https://www.mediamolecule.com) and first used internally on the game [Tearaway](https://tearaway.mediamolecule.com) (PS Vita).
Developed by [Omar Cornut](https://www.miracleworld.net) and every direct or indirect [contributors](https://github.com/ocornut/imgui/graphs/contributors) to the GitHub. The early version of this library was developed with the support of [Media Molecule](https://www.mediamolecule.com) and first used internally on the game [Tearaway](https://youtu.be/w0oxBviRGlU) (PS Vita).
Recurring contributors include Rokas Kupstys [@rokups](https://github.com/rokups) (2020-2022): a good portion of work on automation system and regression tests now available in [Dear ImGui Test Engine](https://github.com/ocornut/imgui_test_engine).
@@ -211,10 +217,11 @@ Maintenance/support contracts, sponsoring invoices and other B2B transactions ar
Omar: "I first discovered the IMGUI paradigm at [Q-Games](https://www.q-games.com) where Atman Binstock had dropped his own simple implementation in the codebase, which I spent quite some time improving and thinking about. It turned out that Atman was exposed to the concept directly by working with Casey. When I moved to Media Molecule I rewrote a new library trying to overcome the flaws and limitations of the first one I've worked with. It became this library and since then I have spent an unreasonable amount of time iterating and improving it."
Embeds [ProggyClean.ttf](https://www.proggyfonts.net) font by Tristan Grimmer (MIT license).
Embeds [ProggyClean](https://www.proggyfonts.net) font by Tristan Grimmer (MIT license).
<br>Embeds [ProggyForever](https://github.com/ocornut/proggyforever) fonts by Disco Hello, Tristan Grimmer (MIT license).
<br>Embeds [stb_textedit.h, stb_truetype.h, stb_rect_pack.h](https://github.com/nothings/stb/) by Sean Barrett (public domain).
Inspiration, feedback, and testing for early versions: Casey Muratori, Atman Binstock, Mikko Mononen, Emmanuel Briney, Stefan Kamoda, Anton Mikhailov, Matt Willis. Also thank you to everyone posting feedback, questions and patches on GitHub.
Inspiration, feedback, and testing for early versions: Casey Muratori, Atman Binstock, Mikko Mononen, Emmanuel Briney, Stefan Kamoda, Anton Mikhailov, Matt Willis. Special thanks to Alex Evans, Patrick Doane, Marco Koegler for kindly helping. Also thank you to everyone posting feedback, questions and patches on GitHub.
License
-------

View File

@@ -87,7 +87,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- 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)
- input text multi-line: better horizontal scrolling support (#383, #1224)
- input text multi-line: single call to AddText() should be coarse clipped on InputTextEx() end.
- input number: optional range min/max for Input*() functions
- input number: holding [-]/[+] buttons could increase the step speed non-linearly (or user-controlled)
- input number: use mouse wheel to step up/down
@@ -309,7 +308,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- examples: window minimize, maximize (#583)
- examples: provide a zero frame-rate/idle example.
- examples: dx11/dx12: try to use new swapchain blit models (#2970)
- examples: dx11/dx12: try to use new swapchain blit models (#2970, #9031)
- backends: report it better when not able to create texture?
- backends: glfw: could go idle when minimized? if (glfwGetWindowAttrib(window, GLFW_ICONIFIED)) { glfwWaitEvents(); continue; } // issue: DeltaTime will be super high on resume, perhaps provide a way to let impl know (#440)
- backends: opengl: rename imgui_impl_opengl2 to impl_opengl_legacy and imgui_impl_opengl3 to imgui_impl_opengl? (#1900)

View File

@@ -1,9 +1,12 @@
See BACKENDS and EXAMPLES files in the docs/ folder, or on the web at: https://github.com/ocornut/imgui/tree/master/docs
New to Dear ImGui?
- Check out the Getting Started guide: https://github.com/ocornut/imgui/wiki/Getting-Started
- About Backends: docs/BACKENDS.md file, or on the web: https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md
- About Examples: docs/EXAMPLES.md file, or on the web: https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md
Backends = Helper code to facilitate integration with platforms/graphics api (used by Examples + should be used by your app).
Examples = Standalone applications showcasing integration with platforms/graphics api.
Some Examples have extra README files in their respective directory, please check them too!
A few Examples have extra README files in their respective directory, please check them too!
Once Dear ImGui is running (in either examples or your own application/game/engine),
run and refer to ImGui::ShowDemoWindow() in imgui_demo.cpp for the end-user API.

View File

@@ -28,7 +28,7 @@ int main(int, char**)
al_install_mouse();
al_init_primitives_addon();
al_set_new_display_flags(ALLEGRO_RESIZABLE);
ALLEGRO_DISPLAY* display = al_create_display(1280, 720);
ALLEGRO_DISPLAY* display = al_create_display(1280, 800);
al_set_window_title(display, "Dear ImGui Allegro 5 example");
ALLEGRO_EVENT_QUEUE* queue = al_create_event_queue();
al_register_event_source(queue, al_get_display_event_source(display));
@@ -49,14 +49,16 @@ int main(int, char**)
ImGui_ImplAllegro5_Init(display);
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
// - Read 'docs/FONTS.md' for more instructions and details.
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
//style.FontSizeBase = 20.0f;
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontDefaultVector();
//io.Fonts->AddFontDefaultBitmap();
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");

View File

@@ -1,12 +1,14 @@
.cxx
.externalNativeBuild
build/
*.iml
.idea
.gradle
.idea
.DS_Store
/captures
.externalNativeBuild
.cxx
local.properties
# Android Studio puts a Gradle wrapper here, that we don't want:
gradle/
!gradle/libs.versions.toml
gradlew*

View File

@@ -1,16 +1,16 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
}
android {
compileSdkVersion 33
buildToolsVersion "33.0.2"
ndkVersion "25.2.9519653"
namespace 'imgui.example.android'
compileSdk 36
defaultConfig {
applicationId "imgui.example.android"
namespace "imgui.example.android"
minSdkVersion 24
targetSdkVersion 33
minSdk 24
targetSdk 36
versionCode 1
versionName "1.0"
}
@@ -21,26 +21,17 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget="11"
jvmTarget = '11'
}
externalNativeBuild {
cmake {
path "../../CMakeLists.txt"
path file('../../CMakeLists.txt')
version '3.22.1'
}
}
}
repositories {
mavenCentral()
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:label="ImGuiExample"

View File

@@ -1,24 +1,5 @@
buildscript {
ext.kotlin_version = '1.8.0'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.4.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.kotlin.android) apply false
}

View File

@@ -0,0 +1,8 @@
[versions]
agp = "8.12.0"
kotlin = "2.0.21"
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }

View File

@@ -1 +1,22 @@
pluginManagement {
repositories {
google {
content {
includeGroupByRegex("com\\.android.*")
includeGroupByRegex("com\\.google.*")
includeGroupByRegex("androidx.*")
}
}
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
include ':app'

View File

@@ -151,42 +151,45 @@ void Init(struct android_app* app)
ImGui_ImplAndroid_Init(g_App->window);
ImGui_ImplOpenGL3_Init("#version 300 es");
// Setup scaling
float main_scale = 2.0f;
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
style.FontScaleDpi = main_scale; // Set initial font scale.
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
// - Read 'docs/FONTS.md' for more instructions and details.
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
// - Android: The TTF files have to be placed into the assets/ directory (android/app/src/main/assets), we use our GetAssetData() helper to retrieve them.
//style.FontSizeBase = 20.0f;
//io.Fonts->AddFontDefaultVector();
//io.Fonts->AddFontDefaultBitmap();
// We load the default font with increased size to improve readability on many devices with "high" DPI.
// FIXME: Put some effort into DPI awareness.
// Important: when calling AddFontFromMemoryTTF(), ownership of font_data is transferred by Dear ImGui by default (deleted is handled by Dear ImGui), unless we set FontDataOwnedByAtlas=false in ImFontConfig
ImFontConfig font_cfg;
font_cfg.SizePixels = 22.0f;
io.Fonts->AddFontDefault(&font_cfg);
//void* font_data;
//int font_data_size;
//void* font_data;
//int font_data_size;
//ImFont* font;
//font_data_size = GetAssetData("segoeui.ttf", &font_data);
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 16.0f);
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size);
//IM_ASSERT(font != nullptr);
//font_data_size = GetAssetData("DroidSans.ttf", &font_data);
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 16.0f);
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size);
//IM_ASSERT(font != nullptr);
//font_data_size = GetAssetData("Roboto-Medium.ttf", &font_data);
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 16.0f);
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size);
//IM_ASSERT(font != nullptr);
//font_data_size = GetAssetData("Cousine-Regular.ttf", &font_data);
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 15.0f);
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size);
//IM_ASSERT(font != nullptr);
//font_data_size = GetAssetData("ArialUni.ttf", &font_data);
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 18.0f);
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size);
//IM_ASSERT(font != nullptr);
// Arbitrary scale-up
// FIXME: Put some effort into DPI awareness
ImGui::GetStyle().ScaleAllSizes(3.0f);
g_Initialized = true;
}

View File

@@ -69,14 +69,16 @@
ImGui_ImplMetal_Init(_device);
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
// - Read 'docs/FONTS.md' for more instructions and details.
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
//style.FontSizeBase = 20.0f;
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontDefaultVector();
//io.Fonts->AddFontDefaultBitmap();
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
@@ -94,7 +96,7 @@
-(void)loadView
{
self.view = [[MTKView alloc] initWithFrame:CGRectMake(0, 0, 1200, 720)];
self.view = [[MTKView alloc] initWithFrame:CGRectMake(0, 0, 1200, 800)];
}
-(void)viewDidLoad

View File

@@ -57,14 +57,16 @@
ImGui_ImplOpenGL2_Init();
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
// - Read 'docs/FONTS.md' for more instructions and details.
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
//style.FontSizeBase = 20.0f;
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontDefaultVector();
//io.Fonts->AddFontDefaultBitmap();
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
@@ -169,9 +171,9 @@
-(NSWindow*)window
{
if (_window != nil)
return (_window);
return _window;
NSRect viewRect = NSMakeRect(100.0, 100.0, 100.0 + 1280.0, 100 + 720.0);
NSRect viewRect = NSMakeRect(100.0, 100.0, 100.0 + 1280.0, 100 + 800.0);
_window = [[NSWindow alloc] initWithContentRect:viewRect styleMask:NSWindowStyleMaskTitled|NSWindowStyleMaskMiniaturizable|NSWindowStyleMaskResizable|NSWindowStyleMaskClosable backing:NSBackingStoreBuffered defer:YES];
[_window setTitle:@"Dear ImGui OSX+OpenGL2 Example"];
@@ -179,7 +181,7 @@
[_window setOpaque:YES];
[_window makeKeyAndOrderFront:NSApp];
return (_window);
return _window;
}
-(void)setupMenu

View File

@@ -27,44 +27,33 @@ static void glfw_error_callback(int error, const char* description)
int main(int, char**)
{
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
// Setup style
ImGui::StyleColorsDark();
//ImGui::StyleColorsLight();
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
// - Read 'docs/FONTS.md' for more instructions and details.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
//style.FontSizeBase = 20.0f;
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf");
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf");
//IM_ASSERT(font != nullptr);
// Setup window
glfwSetErrorCallback(glfw_error_callback);
if (!glfwInit())
return 1;
// Create window with graphics context
float main_scale = ImGui_ImplGlfw_GetContentScaleForMonitor(glfwGetPrimaryMonitor()); // Valid on GLFW 3.3+ only
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+Metal example", nullptr, nullptr);
GLFWwindow* window = glfwCreateWindow((int)(1280 * main_scale), (int)(800 * main_scale), "Dear ImGui GLFW+Metal example", nullptr, nullptr);
if (window == nullptr)
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
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsLight();
// Setup scaling
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
id <MTLDevice> device = MTLCreateSystemDefaultDevice();
id <MTLCommandQueue> commandQueue = [device newCommandQueue];
@@ -72,6 +61,24 @@ int main(int, char**)
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplMetal_Init(device);
// Load Fonts
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
// - Read 'docs/FONTS.md' for more instructions and details.
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
//style.FontSizeBase = 20.0f;
//io.Fonts->AddFontDefaultVector();
//io.Fonts->AddFontDefaultBitmap();
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf");
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf");
//IM_ASSERT(font != nullptr);
NSWindow *nswin = glfwGetCocoaWindow(window);
CAMetalLayer *layer = [CAMetalLayer layer];
layer.device = device;

View File

@@ -21,6 +21,7 @@ SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_glfw.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl2.cpp
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
UNAME_S := $(shell uname -s)
LINUX_GL_LIBS = -lGL
CXXFLAGS = -std=c++11 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
CXXFLAGS += -g -Wall -Wformat
@@ -32,7 +33,7 @@ LIBS =
ifeq ($(UNAME_S), Linux) #LINUX
ECHO_MESSAGE = "Linux"
LIBS += -lGL `pkg-config --static --libs glfw3`
LIBS += $(LINUX_GL_LIBS) `pkg-config --static --libs glfw3`
CXXFLAGS += `pkg-config --cflags glfw3`
CFLAGS = $(CXXFLAGS)

View File

@@ -40,7 +40,8 @@ int main(int, char**)
return 1;
// Create window with graphics context
GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+OpenGL2 example", nullptr, nullptr);
float main_scale = ImGui_ImplGlfw_GetContentScaleForMonitor(glfwGetPrimaryMonitor()); // Valid on GLFW 3.3+ only
GLFWwindow* window = glfwCreateWindow((int)(1280 * main_scale), (int)(800 * main_scale), "Dear ImGui GLFW+OpenGL2 example", nullptr, nullptr);
if (window == nullptr)
return 1;
glfwMakeContextCurrent(window);
@@ -57,19 +58,26 @@ int main(int, char**)
ImGui::StyleColorsDark();
//ImGui::StyleColorsLight();
// Setup scaling
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
// Setup Platform/Renderer backends
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL2_Init();
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
// - Read 'docs/FONTS.md' for more instructions and details.
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
//style.FontSizeBase = 20.0f;
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontDefaultVector();
//io.Fonts->AddFontDefaultBitmap();
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");

View File

@@ -92,7 +92,7 @@ int main(int, char**)
// Setup scaling
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
style.FontScaleDpi = main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose)
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
// Setup Platform/Renderer backends
ImGui_ImplGlfw_InitForOpenGL(window, true);
@@ -102,15 +102,17 @@ int main(int, char**)
ImGui_ImplOpenGL3_Init(glsl_version);
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
// - Read 'docs/FONTS.md' for more instructions and details.
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
// - Our Emscripten build process allows embedding fonts to be accessible at runtime from the "fonts/" folder. See Makefile.emscripten for details.
//style.FontSizeBase = 20.0f;
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontDefaultVector();
//io.Fonts->AddFontDefaultBitmap();
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");

View File

@@ -201,7 +201,7 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
pool_info.maxSets = 0;
for (VkDescriptorPoolSize& pool_size : pool_sizes)
pool_info.maxSets += pool_size.descriptorCount;
pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes);
pool_info.poolSizeCount = (uint32_t)IM_COUNTOF(pool_sizes);
pool_info.pPoolSizes = pool_sizes;
err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool);
check_vk_result(err);
@@ -212,11 +212,9 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
// Your real engine/app may not use them.
static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface, int width, int height)
{
wd->Surface = surface;
// Check for WSI support
VkBool32 res;
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, wd->Surface, &res);
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, surface, &res);
if (res != VK_TRUE)
{
fprintf(stderr, "Error no WSI support on physical device 0\n");
@@ -226,7 +224,8 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface
// Select Surface Format
const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
wd->Surface = surface;
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_COUNTOF(requestSurfaceImageFormat), requestSurfaceColorSpace);
// Select Present Mode
#ifdef APP_USE_UNLIMITED_FRAME_RATE
@@ -234,12 +233,12 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface
#else
VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_FIFO_KHR };
#endif
wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_modes[0], IM_ARRAYSIZE(present_modes));
wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_modes[0], IM_COUNTOF(present_modes));
//printf("[vulkan] Selected PresentMode = %d\n", wd->PresentMode);
// Create SwapChain, RenderPass, Framebuffer, etc.
IM_ASSERT(g_MinImageCount >= 2);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, 0);
}
static void CleanupVulkan()
@@ -256,9 +255,10 @@ static void CleanupVulkan()
vkDestroyInstance(g_Instance, g_Allocator);
}
static void CleanupVulkanWindow()
static void CleanupVulkanWindow(ImGui_ImplVulkanH_Window* wd)
{
ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, &g_MainWindowData, g_Allocator);
ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, wd, g_Allocator);
vkDestroySurfaceKHR(g_Instance, wd->Surface, g_Allocator);
}
static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
@@ -357,7 +357,8 @@ int main(int, char**)
// Create window with Vulkan context
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+Vulkan example", nullptr, nullptr);
float main_scale = ImGui_ImplGlfw_GetContentScaleForMonitor(glfwGetPrimaryMonitor()); // Valid on GLFW 3.3+ only
GLFWwindow* window = glfwCreateWindow((int)(1280 * main_scale), (int)(800 * main_scale), "Dear ImGui GLFW+Vulkan example", nullptr, nullptr);
if (!glfwVulkanSupported())
{
printf("GLFW: Vulkan Not Supported\n");
@@ -393,6 +394,11 @@ int main(int, char**)
ImGui::StyleColorsDark();
//ImGui::StyleColorsLight();
// Setup scaling
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
// Setup Platform/Renderer backends
ImGui_ImplGlfw_InitForVulkan(window, true);
ImGui_ImplVulkan_InitInfo init_info = {};
@@ -404,24 +410,26 @@ int main(int, char**)
init_info.Queue = g_Queue;
init_info.PipelineCache = g_PipelineCache;
init_info.DescriptorPool = g_DescriptorPool;
init_info.RenderPass = wd->RenderPass;
init_info.Subpass = 0;
init_info.MinImageCount = g_MinImageCount;
init_info.ImageCount = wd->ImageCount;
init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
init_info.Allocator = g_Allocator;
init_info.PipelineInfoMain.RenderPass = wd->RenderPass;
init_info.PipelineInfoMain.Subpass = 0;
init_info.PipelineInfoMain.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
init_info.CheckVkResultFn = check_vk_result;
ImGui_ImplVulkan_Init(&init_info);
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
// - Read 'docs/FONTS.md' for more instructions and details.
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
//style.FontSizeBase = 20.0f;
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontDefaultVector();
//io.Fonts->AddFontDefaultBitmap();
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
@@ -450,7 +458,7 @@ int main(int, char**)
if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height))
{
ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, 0);
g_MainWindowData.FrameIndex = 0;
g_SwapChainRebuild = false;
}
@@ -524,7 +532,7 @@ int main(int, char**)
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
CleanupVulkanWindow();
CleanupVulkanWindow(&g_MainWindowData);
CleanupVulkan();
glfwDestroyWindow(window);

View File

@@ -6,18 +6,30 @@
# * build/Debug/example_glfw_wgpu[.exe]
# * build/example_glfw_wgpu[.exe]
# Building for desktop (WGPU-Native) 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]
# Building for Emscripten:
# 1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html
# 2. Install Ninja build system
# 3. emcmake cmake -G Ninja -B build
# (optional) -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path/to/emdawnwebgpu_package/emdawnwebgpu.port.py", see ReadMe.md
# 3. cmake --build build
# 4. emrun build/index.html
cmake_minimum_required(VERSION 3.10.2)
cmake_minimum_required(VERSION 3.22) # Dawn requires CMake >= 3.22
project(imgui_example_glfw_wgpu C CXX)
set(IMGUI_EXECUTABLE example_glfw_wgpu)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
endif()
set(CMAKE_CXX_STANDARD 17) # Dawn requires C++17
@@ -25,93 +37,179 @@ set(CMAKE_CXX_STANDARD 17) # Dawn requires C++17
# Dear ImGui
set(IMGUI_DIR ../../)
# Libraries
set(IMGUI_EXAMPLE_SOURCE_FILES
# Example code
main.cpp
# Dear ImGui Backend files
${IMGUI_DIR}/backends/imgui_impl_glfw.cpp
${IMGUI_DIR}/backends/imgui_impl_wgpu.cpp
# Dear ImGui files
${IMGUI_DIR}/imgui.cpp
${IMGUI_DIR}/imgui_draw.cpp
${IMGUI_DIR}/imgui_demo.cpp
${IMGUI_DIR}/imgui_tables.cpp
${IMGUI_DIR}/imgui_widgets.cpp
)
if(EMSCRIPTEN)
if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "3.1.57")
set(IMGUI_EMSCRIPTEN_GLFW3 "--use-port=contrib.glfw3" CACHE STRING "Choose between --use-port=contrib.glfw3 and -sUSE_GLFW=3 for GLFW implementation (default to --use-port=contrib.glfw3)")
else()
# cannot use contrib.glfw3 prior to 3.1.57
set(IMGUI_EMSCRIPTEN_GLFW3 "-sUSE_GLFW=3" CACHE STRING "Use -sUSE_GLFW=3 for GLFW implementation" FORCE)
endif()
set(LIBRARIES glfw)
add_compile_options(-sDISABLE_EXCEPTION_CATCHING=1 -DIMGUI_DISABLE_FILE_FUNCTIONS=1)
if(NOT IMGUI_EMSCRIPTEN_WEBGPU_FLAG) # if IMGUI_EMSCRIPTEN_WEBGPU_FLAG not used, set by current EMSCRIPTEN version
if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "4.0.10")
set(IMGUI_EMSCRIPTEN_WEBGPU_FLAG "--use-port=emdawnwebgpu" CACHE STRING "Choose between --use-port=emdawnwebgpu (Dawn implementation of EMSCRIPTEN) and -sUSE_WEBGPU=1 (WGPU implementation of EMSCRIPTEN, deprecated in 4.0.10): default to --use-port=emdawnwebgpu for EMSCRIPTEN >= 4.0.10")
else()
set(IMGUI_EMSCRIPTEN_WEBGPU_FLAG "-sUSE_WEBGPU=1" CACHE STRING "Use -sUSE_WEBGPU=1 for EMSCRIPTEN WGPU implementation")
endif()
else() # if IMGUI_EMSCRIPTEN_WEBGPU_FLAG used, check correct version
if(EMSCRIPTEN_VERSION VERSION_LESS "4.0.10" AND "${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}" MATCHES "emdawnwebgpu")
# it's necessary EMSCRIPTEN >= v4.0.10 (although "--use-port=path/to/emdawnwebgpu.port.py" is supported/tested from v4.0.8)
message(FATAL_ERROR "emdawnwebgpu needs EMSCRIPTEN version >= 4.0.10")
endif()
endif()
if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "3.1.57")
set(IMGUI_EMSCRIPTEN_GLFW3 "--use-port=contrib.glfw3" CACHE STRING "Choose between --use-port=contrib.glfw3 and -sUSE_GLFW=3 for GLFW implementation (default to --use-port=contrib.glfw3)")
else() # cannot use contrib.glfw3 prior to 3.1.57
set(IMGUI_EMSCRIPTEN_GLFW3 "-sUSE_GLFW=3" CACHE STRING "Use -sUSE_GLFW=3 for GLFW implementation" FORCE)
endif()
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")
endif()
if(APPLE) # Add SDL2 module to get Surface, with libs and file property for MacOS build
set_source_files_properties(${IMGUI_DIR}/backends/imgui_impl_wgpu.cpp PROPERTIES COMPILE_FLAGS "-x objective-c++")
set(OS_LIBRARIES "-framework CoreFoundation -framework QuartzCore -framework Metal -framework MetalKit -framework Cocoa")
endif()
find_package(glfw3 REQUIRED)
if(IMGUI_DAWN_DIR) # DAWN-Native build options
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)
message("Dawn Installation has been found!")
set(LIBRARIES dawn::webgpu_dawn glfw ${OS_LIBRARIES})
else()
set(IMGUI_DAWN_DIR CACHE PATH "Path to Dawn repository")
option(DAWN_FETCH_DEPENDENCIES "Use fetch_dawn_dependencies.py as an alternative to using depot_tools" ON)
set(DAWN_BUILD_MONOLITHIC_LIBRARY "STATIC" CACHE STRING "Build monolithic library: SHARED, STATIC, or OFF.")
option(DAWN_USE_GLFW OFF) # disable builtin GLFW in DAWN when we use SDL2 / SDL3
# Dawn builds many things by default - disable things we don't need
option(DAWN_BUILD_SAMPLES "Enables building Dawn's samples" OFF)
option(TINT_BUILD_CMD_TOOLS "Build the Tint command line tools" OFF)
option(TINT_BUILD_DOCS "Build documentation" OFF)
option(TINT_BUILD_TESTS "Build tests" OFF)
if(NOT APPLE)
option(TINT_BUILD_MSL_WRITER "Build the MSL output writer" OFF)
endif()
if(WIN32)
option(DAWN_FORCE_SYSTEM_COMPONENT_LOAD "Allow system component fallback" ON)
option(TINT_BUILD_SPV_READER "Build the SPIR-V input reader" OFF)
option(TINT_BUILD_WGSL_READER "Build the WGSL input reader" ON)
option(TINT_BUILD_GLSL_WRITER "Build the GLSL output writer" OFF)
option(TINT_BUILD_GLSL_VALIDATOR "Build the GLSL output validator" OFF)
option(TINT_BUILD_SPV_WRITER "Build the SPIR-V output writer" ON)
option(TINT_BUILD_WGSL_WRITER "Build the WGSL output writer" ON)
endif()
# check if WAYLAND is the current Session Type and enable DAWN_USE_WAYLAND Wayland option @compile time
# You can override this using: cmake -DDAWN_USE_WAYLAND=X (X = ON | OFF)
if(LINUX)
if($ENV{XDG_SESSION_TYPE} MATCHES wayland)
option(DAWN_USE_WAYLAND "Enable support for Wayland surface" ON)
endif()
endif()
add_subdirectory("${IMGUI_DAWN_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/dawn" EXCLUDE_FROM_ALL)
set(LIBRARIES webgpu_dawn glfw)
endif()
else() # WGPU-Native build options
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)
set(OS_LIBRARIES d3dcompiler ws2_32 userenv bcrypt ntdll opengl32 Propsys RuntimeObject)
elseif(UNIX AND NOT APPLE)
set(OS_LIBRARIES "-lm -ldl")
endif()
set(LIBRARIES glfw ${WGPU_LIBRARY} ${OS_LIBRARIES})
endif()
endif()
add_executable(${IMGUI_EXECUTABLE} ${IMGUI_EXAMPLE_SOURCE_FILES})
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC
${IMGUI_DIR}
${IMGUI_DIR}/backends
)
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_EXAMPLE_GLFW_WGPU")
# compiler option only for IMGUI_EXAMPLE_SOURCE_FILES
if (MSVC)
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC /W4) # warning level 4
else()
# Dawn wgpu desktop
set(DAWN_FETCH_DEPENDENCIES ON)
set(IMGUI_DAWN_DIR CACHE PATH "Path to Dawn repository")
if (NOT IMGUI_DAWN_DIR)
message(FATAL_ERROR "Please specify the Dawn repository by setting IMGUI_DAWN_DIR")
endif()
option(DAWN_FETCH_DEPENDENCIES "Use fetch_dawn_dependencies.py as an alternative to using depot_tools" ON)
# Dawn builds many things by default - disable things we don't need
option(DAWN_BUILD_SAMPLES "Enables building Dawn's samples" OFF)
option(TINT_BUILD_CMD_TOOLS "Build the Tint command line tools" OFF)
option(TINT_BUILD_DOCS "Build documentation" OFF)
option(TINT_BUILD_TESTS "Build tests" OFF)
if (NOT APPLE)
option(TINT_BUILD_MSL_WRITER "Build the MSL output writer" OFF)
endif()
if(WIN32)
option(TINT_BUILD_SPV_READER "Build the SPIR-V input reader" OFF)
option(TINT_BUILD_WGSL_READER "Build the WGSL input reader" ON)
option(TINT_BUILD_GLSL_WRITER "Build the GLSL output writer" OFF)
option(TINT_BUILD_GLSL_VALIDATOR "Build the GLSL output validator" OFF)
option(TINT_BUILD_SPV_WRITER "Build the SPIR-V output writer" OFF)
option(TINT_BUILD_WGSL_WRITER "Build the WGSL output writer" ON)
endif()
add_subdirectory("${IMGUI_DAWN_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/dawn" EXCLUDE_FROM_ALL)
set(LIBRARIES webgpu_dawn webgpu_cpp webgpu_glfw glfw)
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC -Wall) # -Wextra -Wpedantic
endif()
add_executable(example_glfw_wgpu
main.cpp
# backend files
${IMGUI_DIR}/backends/imgui_impl_glfw.cpp
${IMGUI_DIR}/backends/imgui_impl_wgpu.cpp
# Dear ImGui files
${IMGUI_DIR}/imgui.cpp
${IMGUI_DIR}/imgui_draw.cpp
${IMGUI_DIR}/imgui_demo.cpp
${IMGUI_DIR}/imgui_tables.cpp
${IMGUI_DIR}/imgui_widgets.cpp
)
IF(NOT EMSCRIPTEN)
target_compile_definitions(example_glfw_wgpu PUBLIC
"IMGUI_IMPL_WEBGPU_BACKEND_DAWN"
)
endif()
target_include_directories(example_glfw_wgpu PUBLIC
${IMGUI_DIR}
${IMGUI_DIR}/backends
)
# In this example IMGUI_IMPL_WEBGPU_BACKEND_DAWN / IMGUI_IMPL_WEBGPU_BACKEND_WGPU internal define is set according to:
# EMSCRIPTEN: by used FLAG
# --use-port=emdawnwebgpu --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN defined
# -sUSE_WEBGPU=1 --> IMGUI_IMPL_WEBGPU_BACKEND_WGPU defined
# NATIVE: by used SDK installation directory
# if IMGUI_DAWN_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN defined
# if IMGUI_WGPU_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_WGPU defined
target_link_libraries(example_glfw_wgpu PUBLIC ${LIBRARIES})
if(NOT EMSCRIPTEN) # WegGPU-Native settings
# Set IMGUI_IMPL_WEBGPU_BACKEND_XXXX based on the SDK (directory) used
if(IMGUI_DAWN_DIR)
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_DAWN")
if(NOT Dawn_FOUND)
target_link_libraries(${IMGUI_EXECUTABLE} INTERFACE webgpu_cpp)
endif()
else()
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGPU_DIR}/include)
endif()
target_link_libraries(${IMGUI_EXECUTABLE} PUBLIC ${LIBRARIES})
# Emscripten settings
if(EMSCRIPTEN)
if("${IMGUI_EMSCRIPTEN_GLFW3}" STREQUAL "--use-port=contrib.glfw3")
target_compile_options(example_glfw_wgpu PUBLIC
"${IMGUI_EMSCRIPTEN_GLFW3}"
else() # Emscripten settings
set(CMAKE_EXECUTABLE_SUFFIX ".html")
if("${IMGUI_EMSCRIPTEN_GLFW3}" STREQUAL "--use-port=contrib.glfw3")
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "${IMGUI_EMSCRIPTEN_GLFW3}")
endif()
message(STATUS "Using ${IMGUI_EMSCRIPTEN_GLFW3} GLFW implementation")
if("${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}" MATCHES "emdawnwebgpu")
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}")
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_DAWN")
else()
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
endif()
message(STATUS "Using ${IMGUI_EMSCRIPTEN_WEBGPU_FLAG} WebGPU implementation")
target_link_options(${IMGUI_EXECUTABLE} PRIVATE
"${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}"
"${IMGUI_EMSCRIPTEN_GLFW3}"
"-sWASM=1"
"-sASYNCIFY=1"
"-sALLOW_MEMORY_GROWTH=1"
"-sNO_EXIT_RUNTIME=0"
"-sASSERTIONS=1"
"-sDISABLE_EXCEPTION_CATCHING=1"
"-sNO_FILESYSTEM=1"
"--shell-file=${CMAKE_CURRENT_LIST_DIR}/../libs/emscripten/shell_minimal.html"
)
endif()
message(STATUS "Using ${IMGUI_EMSCRIPTEN_GLFW3} GLFW implementation")
target_link_options(example_glfw_wgpu PRIVATE
"-sUSE_WEBGPU=1"
"${IMGUI_EMSCRIPTEN_GLFW3}"
"-sWASM=1"
"-sALLOW_MEMORY_GROWTH=1"
"-sNO_EXIT_RUNTIME=0"
"-sASSERTIONS=1"
"-sDISABLE_EXCEPTION_CATCHING=1"
"-sNO_FILESYSTEM=1"
)
set_target_properties(example_glfw_wgpu PROPERTIES OUTPUT_NAME "index")
# copy our custom index.html to build directory
add_custom_command(TARGET example_glfw_wgpu POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_LIST_DIR}/web/index.html" $<TARGET_FILE_DIR:example_glfw_wgpu>
)
set_target_properties(${IMGUI_EXECUTABLE} PROPERTIES OUTPUT_NAME "index")
endif()

View File

@@ -6,8 +6,8 @@
# This Makefile assumes you have loaded emscripten's environment.
# (On Windows, you may need to execute emsdk_env.bat or encmdprompt.bat ahead)
#
# Running `make` will produce three files:
# - web/index.html (current stored in the repository)
# Running `make -f Makefile.emscripten` will produce three files:
# - web/index.html
# - web/index.js
# - web/index.wasm
#
@@ -16,7 +16,7 @@
CC = emcc
CXX = em++
WEB_DIR = web
EXE = $(WEB_DIR)/index.js
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
@@ -34,8 +34,19 @@ EMS =
# ("EMS" options gets added to both CPPFLAGS and LDFLAGS, whereas some options are for linker only)
# Note: For glfw, we use emscripten-glfw port (contrib.glfw3) instead of (-s USE_GLFW=3) to get a better support for High DPI displays.
EMS += -s DISABLE_EXCEPTION_CATCHING=1 --use-port=contrib.glfw3
LDFLAGS += -s USE_WEBGPU=1
LDFLAGS += -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s ASSERTIONS=1
LDFLAGS += -s WASM=1
LDFLAGS += -s ALLOW_MEMORY_GROWTH=1
LDFLAGS += -s ASYNCIFY=1
LDFLAGS += -s NO_EXIT_RUNTIME=0
LDFLAGS += -s ASSERTIONS=1
# (1) Using legacy WebGPU implementation (Emscripten < 4.0.10)
#EMS += -DIMGUI_IMPL_WEBGPU_BACKEND_WGPU
#LDFLAGS += -s USE_WEBGPU=1
# or (2) Using newer Dawn-based WebGPU port (Emscripten >= 4.0.10)
EMS += --use-port=emdawnwebgpu
LDFLAGS += --use-port=emdawnwebgpu
# Build as single file (binary text encoded in .html file)
#LDFLAGS += -sSINGLE_FILE
@@ -60,7 +71,7 @@ endif
CPPFLAGS += -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
#CPPFLAGS += -g
CPPFLAGS += -Wall -Wformat -Os $(EMS)
#LDFLAGS += --shell-file shell_minimal.html
LDFLAGS += --shell-file ../libs/emscripten/shell_minimal.html
LDFLAGS += $(EMS)
##---------------------------------------------------------------------

View File

@@ -1,4 +1,145 @@
## How to Build
## How to Build
---
### Using CMake
#### Building for desktop (WebGPU-native) with Google 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]
#### Building for desktop (WebGPU-Native) with WGPU:
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]
#### Building for Emscripten:
1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html
2. Install Ninja build system
3. `emcmake cmake -G Ninja -B build`
- (optional) `-DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path/to/emdawnwebgpu_package/emdawnwebgpu.port.py"`, see below
4. `cmake --build build`
#### Sync Emscripten with latest Google Dawn:
If you want to sync Emscripten with latest DAWN release it's necessary to download the `port-emdawnwgpu-package` (released daily by Google) here:
https://github.com/google/dawn/releases
Unpack it in your preferred folder and to replace the step 3 with:
3. `emcmake cmake -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path/to/emdawnwebgpu_package/emdawnwebgpu.port.py" -G Ninja -B build`
**N.B.**
For the WASM code produced by Emscripten to work correctly, it will also be necessary to have the "corresponding" (or newer) version of Google Canary (nightly build for developers) that includes the latest changes
---
### CMake by step
#### Generate Dawn Native:
- `cmake -G Ninja -DIMGUI_DAWN_DIR=path_to_sdk_dir -B where_to_build_dir`
- Using `IMGUI_DAWN_DIR` set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
#### Generate WGPU Native:
- `cmake -G Ninja -DIMGUI_WGPU_DIR=path_to_sdk_dir -B where_to_build_dir`
- Using `IMGUI_WGPU_DIR` set `IMGUI_IMPL_WEBGPU_BACKEND_WGPU` compiler define
#### Generate Emscripten:
- `emcmake cmake -G Ninja -B where_to_build_dir`\
CMake checks the EMSCRIPEN version then:
- if EMS >= 4.0.10 uses `--use-port=emdawnwebgpu` flag to build
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
- if EMS < 4.0.10 uses `-sUSE_WEBGPU=1` flag to build
- it set `IMGUI_IMPL_WEBGPU_BACKEND_WGPU` compiler define
#### Generate Emscripten forcing `-sUSE_WEBGPU=1` deprecated flag even with EMS >= 4.0.10
- `emcmake cmake -G Ninja -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="-sUSE_WEBGPU=1" -B where_to_build_dir`
- it set `IMGUI_IMPL_WEBGPU_BACKEND_WGPU` compiler define
#### Generate Emscripten using external WebGPU library (emdawnwebgpu_pkg)
- `emcmake cmake -G Ninja -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path_to_emdawnwebgpu_pkg" -B where_to_build_dir`
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
- *To use external WebGPU library it's necessary to have EMS >= 4.0.10 or the minimum requirements specified by the package:*
- https://github.com/google/dawn/releases
#### Build time
Once the procedure for the specific builder is generated, the build command is **always the same**:
- Build using CMake
- `cmake --build where_to_build_dir`
- It will use selected builder to build the example.
- Build explicitly:
- `cd where_to_build_dir`
- `ninja`
- This is the builder chosen during the generation phase
---
### CMake useful options
#### Generator types (alternative to **ninja** builder):
- `-G Ninja` to build with __ninja__ builder
- `-G "Unix Makefiles"` to build with __make__ builder
- `-G "Visual Studio 17 2022" -A x64` to create a VS 2022 solution (.sln) file, Windows only
- **Native build only**
- Not **officially** supported to build Google Dawn
Example:
- using **make** instead **ninja**:
- `cmake -G "Unix Makefiles" -DIMGUI_DAWN_DIR=path_to_sdk_dir -B where_to_build_dir`
**Syntax is case sensitive and the "" are necessary in case of spaces between words*
#### Directories
- The directory path can be absolute or relative (starting from the current directory)
- It's necessary to use different `where_to_build_dir` for different CMake generations
#### Build type
The default build type is **Debug**
It is possible to use a different build type using:
- `-DCMAKE_BUILD_TYPE=Release`
- `-DCMAKE_BUILD_TYPE=MinSizeRel`
- `-DCMAKE_BUILD_TYPE=RelWithDebInfo`
Example:
- building **Release**:
- `cmake -G ninja -DIMGUI_WGPU_DIR=path_to_sdk_dir -DCMAKE_BUILD_TYPE=Release -B where_to_build_dir `
#### GLFW / SDL2 / SDL3 includes, libraries, search paths and package manager
Includes and libraries, by default, are searched in system/compiler paths (environment variables): you can add the path to your development tools to the environment variables without having to modify the `CMakeLists.txt` file.
- e.g. CLang search in path specified from the following environment variables:
- include files: CPATH, C_INCLUDE_PATH, CPLUS_INCLUDE_PATH
- library files: LIBRARY_PATH
If you are using a package manager (**vcpkg** / **conan** / ... ) you need/can to specify it, adding to cmake command:
- `-DCMAKE_TOOLCHAIN_FILE=path/to/package_manager.cmake`
Examples:
- using **vcpkg** package manager it's necessary adding:
- `-DCMAKE_TOOLCHAIN_FILE=<vcpkg_root_dir>/scripts/buildsystems/vcpkg.cmake`
- full cmake command using **vcpkg** package manager:
- `cmake -G Ninja -DIMGUI_DAWN_DIR=path_to_sdk_dir -DCMAKE_TOOLCHAIN_FILE=<vcpkg_root_dir>/scripts/buildsystems/vcpkg.cmake -B where_to_build_dir`
---
### Using makefile
- You need to install Emscripten from https://emscripten.org/docs/getting_started/downloads.html, and have the environment variables set, as described in https://emscripten.org/docs/getting_started/downloads.html#installation-instructions
@@ -10,6 +151,8 @@
- Requires recent Emscripten as WGPU is still a work-in-progress API.
---
## How to Run
To run on a local machine:

View File

@@ -1,4 +1,4 @@
// Dear ImGui: standalone example application for using GLFW + WebGPU
// Dear ImGui: standalone example application for GLFW + WebGPU
// - Emscripten is supported for publishing on web. See https://emscripten.org.
// - Dawn is used as a WebGPU implementation on desktop.
@@ -12,54 +12,47 @@
#include "imgui_impl_glfw.h"
#include "imgui_impl_wgpu.h"
#include <stdio.h>
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#include <emscripten/html5.h>
#include <emscripten/html5_webgpu.h>
#else
#include <webgpu/webgpu_glfw.h>
#endif
#include <stdlib.h>
#include <GLFW/glfw3.h>
#include <webgpu/webgpu.h>
#include <webgpu/webgpu_cpp.h>
// This example can also compile and run with Emscripten! See 'Makefile.emscripten' for details.
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#include <emscripten/html5.h>
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#include <emscripten/html5_webgpu.h>
#endif
#include "../libs/emscripten/emscripten_mainloop_stub.h"
#endif
// Global WebGPU required states
static WGPUInstance wgpu_instance = nullptr;
static WGPUDevice wgpu_device = nullptr;
static WGPUSurface wgpu_surface = nullptr;
static WGPUTextureFormat wgpu_preferred_fmt = WGPUTextureFormat_RGBA8Unorm;
static WGPUSwapChain wgpu_swap_chain = nullptr;
static int wgpu_swap_chain_width = 1280;
static int wgpu_swap_chain_height = 720;
#include <webgpu/webgpu.h>
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
#include <webgpu/webgpu_cpp.h>
#endif
// Data
static WGPUInstance wgpu_instance = nullptr;
static WGPUDevice wgpu_device = nullptr;
static WGPUSurface wgpu_surface = nullptr;
static WGPUQueue wgpu_queue = nullptr;
static WGPUSurfaceConfiguration wgpu_surface_configuration = {};
static int wgpu_surface_width = 1280;
static int wgpu_surface_height = 800;
// Forward declarations
static bool InitWGPU(GLFWwindow* window);
static void CreateSwapChain(int width, int height);
WGPUSurface CreateWGPUSurface(const WGPUInstance& instance, GLFWwindow* window);
static void glfw_error_callback(int error, const char* description)
{
printf("GLFW Error %d: %s\n", error, description);
}
static void wgpu_error_callback(WGPUErrorType error_type, const char* message, void*)
static void ResizeSurface(int width, int height)
{
const char* error_type_lbl = "";
switch (error_type)
{
case WGPUErrorType_Validation: error_type_lbl = "Validation"; break;
case WGPUErrorType_OutOfMemory: error_type_lbl = "Out of memory"; break;
case WGPUErrorType_Unknown: error_type_lbl = "Unknown"; break;
case WGPUErrorType_DeviceLost: error_type_lbl = "Device lost"; break;
default: error_type_lbl = "Unknown";
}
printf("%s error: %s\n", error_type_lbl, message);
wgpu_surface_configuration.width = wgpu_surface_width = width;
wgpu_surface_configuration.height = wgpu_surface_height = height;
wgpuSurfaceConfigure(wgpu_surface, &wgpu_surface_configuration);
}
// Main code
@@ -72,19 +65,23 @@ int main(int, char**)
// Make sure GLFW does not initialize any graphics context.
// This needs to be done explicitly later.
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow* window = glfwCreateWindow(wgpu_swap_chain_width, wgpu_swap_chain_height, "Dear ImGui GLFW+WebGPU example", nullptr, nullptr);
// 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;
GLFWwindow* window = glfwCreateWindow(wgpu_surface_width, wgpu_surface_height, "Dear ImGui GLFW+WebGPU example", nullptr, nullptr);
if (window == nullptr)
return 1;
// Initialize the WebGPU environment
if (!InitWGPU(window))
{
if (window)
glfwDestroyWindow(window);
glfwDestroyWindow(window);
glfwTerminate();
return 1;
}
CreateSwapChain(wgpu_swap_chain_width, wgpu_swap_chain_height);
glfwShowWindow(window);
// Setup Dear ImGui context
@@ -98,6 +95,11 @@ int main(int, char**)
ImGui::StyleColorsDark();
//ImGui::StyleColorsLight();
// Setup scaling
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
// Setup Platform/Renderer backends
ImGui_ImplGlfw_InitForOther(window, true);
#ifdef __EMSCRIPTEN__
@@ -106,26 +108,27 @@ int main(int, char**)
ImGui_ImplWGPU_InitInfo init_info;
init_info.Device = wgpu_device;
init_info.NumFramesInFlight = 3;
init_info.RenderTargetFormat = wgpu_preferred_fmt;
init_info.RenderTargetFormat = wgpu_surface_configuration.format;
init_info.DepthStencilFormat = WGPUTextureFormat_Undefined;
ImGui_ImplWGPU_Init(&init_info);
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
// - Read 'docs/FONTS.md' for more instructions and details.
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
// - Emscripten allows preloading a file or folder to be accessible at runtime. See Makefile for details.
//io.Fonts->AddFontDefault();
// - Our Emscripten build process allows embedding fonts to be accessible at runtime from the "fonts/" folder. See Makefile.emscripten for details.
//style.FontSizeBase = 20.0f;
//io.Fonts->AddFontDefaultVector();
//io.Fonts->AddFontDefaultBitmap();
#ifndef IMGUI_DISABLE_FILE_FUNCTIONS
//io.Fonts->AddFontFromFileTTF("fonts/segoeui.ttf");
//io.Fonts->AddFontFromFileTTF("fonts/DroidSans.ttf");
//io.Fonts->AddFontFromFileTTF("fonts/Roboto-Medium.ttf");
//io.Fonts->AddFontFromFileTTF("fonts/Cousine-Regular.ttf");
//io.Fonts->AddFontFromFileTTF("fonts/ProggyTiny.ttf");
//ImFont* font = io.Fonts->AddFontFromFileTTF("fonts/ArialUni.ttf");
//IM_ASSERT(font != nullptr);
#endif
@@ -160,11 +163,24 @@ int main(int, char**)
// React to changes in screen size
int width, height;
glfwGetFramebufferSize((GLFWwindow*)window, &width, &height);
if (width != wgpu_swap_chain_width || height != wgpu_swap_chain_height)
if (width != wgpu_surface_width || height != wgpu_surface_height)
ResizeSurface(width, height);
// Check surface status for error. If texture is not optimal, try to reconfigure the surface.
WGPUSurfaceTexture surface_texture;
wgpuSurfaceGetCurrentTexture(wgpu_surface, &surface_texture);
if (ImGui_ImplWGPU_IsSurfaceStatusError(surface_texture.status))
{
ImGui_ImplWGPU_InvalidateDeviceObjects();
CreateSwapChain(width, height);
ImGui_ImplWGPU_CreateDeviceObjects();
fprintf(stderr, "Unrecoverable Surface Texture status=%#.8x\n", surface_texture.status);
abort();
}
if (ImGui_ImplWGPU_IsSurfaceStatusSubOptimal(surface_texture.status))
{
if (surface_texture.texture)
wgpuTextureRelease(surface_texture.texture);
if (width > 0 && height > 0)
ResizeSurface(width, height);
continue;
}
// Start the Dear ImGui frame
@@ -212,17 +228,21 @@ int main(int, char**)
// Rendering
ImGui::Render();
#ifndef __EMSCRIPTEN__
// Tick needs to be called in Dawn to display validation errors
wgpuDeviceTick(wgpu_device);
#endif
WGPUTextureViewDescriptor view_desc = {};
view_desc.format = wgpu_surface_configuration.format;
view_desc.dimension = WGPUTextureViewDimension_2D ;
view_desc.mipLevelCount = WGPU_MIP_LEVEL_COUNT_UNDEFINED;
view_desc.arrayLayerCount = WGPU_ARRAY_LAYER_COUNT_UNDEFINED;
view_desc.aspect = WGPUTextureAspect_All;
WGPUTextureView texture_view = wgpuTextureCreateView(surface_texture.texture, &view_desc);
WGPURenderPassColorAttachment color_attachments = {};
color_attachments.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED;
color_attachments.loadOp = WGPULoadOp_Clear;
color_attachments.storeOp = WGPUStoreOp_Store;
color_attachments.clearValue = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w };
color_attachments.view = wgpuSwapChainGetCurrentTextureView(wgpu_swap_chain);
color_attachments.view = texture_view;
WGPURenderPassDescriptor render_pass_desc = {};
render_pass_desc.colorAttachmentCount = 1;
@@ -238,14 +258,16 @@ int main(int, char**)
WGPUCommandBufferDescriptor cmd_buffer_desc = {};
WGPUCommandBuffer cmd_buffer = wgpuCommandEncoderFinish(encoder, &cmd_buffer_desc);
WGPUQueue queue = wgpuDeviceGetQueue(wgpu_device);
wgpuQueueSubmit(queue, 1, &cmd_buffer);
wgpuQueueSubmit(wgpu_queue, 1, &cmd_buffer);
#ifndef __EMSCRIPTEN__
wgpuSwapChainPresent(wgpu_swap_chain);
wgpuSurfacePresent(wgpu_surface);
// Tick needs to be called in Dawn to display validation errors
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
wgpuDeviceTick(wgpu_device);
#endif
wgpuTextureViewRelease(color_attachments.view);
#endif
wgpuTextureViewRelease(texture_view);
wgpuRenderPassEncoderRelease(pass);
wgpuCommandEncoderRelease(encoder);
wgpuCommandBufferRelease(cmd_buffer);
@@ -259,92 +281,298 @@ int main(int, char**)
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
wgpuSurfaceUnconfigure(wgpu_surface);
wgpuSurfaceRelease(wgpu_surface);
wgpuQueueRelease(wgpu_queue);
wgpuDeviceRelease(wgpu_device);
wgpuInstanceRelease(wgpu_instance);
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
#ifndef __EMSCRIPTEN__
static WGPUAdapter RequestAdapter(WGPUInstance instance)
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
static WGPUAdapter RequestAdapter(wgpu::Instance& instance)
{
auto onAdapterRequestEnded = [](WGPURequestAdapterStatus status, WGPUAdapter adapter, const char* message, void* pUserData)
wgpu::Adapter acquired_adapter;
wgpu::RequestAdapterOptions adapter_options;
auto onRequestAdapter = [&](wgpu::RequestAdapterStatus status, wgpu::Adapter adapter, wgpu::StringView message)
{
if (status == WGPURequestAdapterStatus_Success)
*(WGPUAdapter*)(pUserData) = adapter;
else
printf("Could not get WebGPU adapter: %s\n", message);
};
WGPUAdapter adapter;
wgpuInstanceRequestAdapter(instance, nullptr, onAdapterRequestEnded, (void*)&adapter);
return adapter;
if (status != wgpu::RequestAdapterStatus::Success)
{
printf("Failed to get an adapter: %s\n", message.data);
return;
}
acquired_adapter = std::move(adapter);
};
// Synchronously (wait until) acquire Adapter
wgpu::Future waitAdapterFunc { instance.RequestAdapter(&adapter_options, wgpu::CallbackMode::WaitAnyOnly, onRequestAdapter) };
wgpu::WaitStatus waitStatusAdapter = instance.WaitAny(waitAdapterFunc, UINT64_MAX);
IM_ASSERT(acquired_adapter != nullptr && waitStatusAdapter == wgpu::WaitStatus::Success && "Error on Adapter request");
return acquired_adapter.MoveToCHandle();
}
static WGPUDevice RequestDevice(wgpu::Instance& instance, wgpu::Adapter& adapter)
{
// Set device callback functions
wgpu::DeviceDescriptor device_desc;
device_desc.SetDeviceLostCallback(wgpu::CallbackMode::AllowSpontaneous,
[](const wgpu::Device&, wgpu::DeviceLostReason type, wgpu::StringView msg) { fprintf(stderr, "%s error: %s\n", ImGui_ImplWGPU_GetDeviceLostReasonName((WGPUDeviceLostReason)type), msg.data); }
);
device_desc.SetUncapturedErrorCallback(
[](const wgpu::Device&, wgpu::ErrorType type, wgpu::StringView msg) { fprintf(stderr, "%s error: %s\n", ImGui_ImplWGPU_GetErrorTypeName((WGPUErrorType)type), msg.data); }
);
wgpu::Device acquired_device;
auto onRequestDevice = [&](wgpu::RequestDeviceStatus status, wgpu::Device local_device, wgpu::StringView message)
{
if (status != wgpu::RequestDeviceStatus::Success)
{
printf("Failed to get an device: %s\n", message.data);
return;
}
acquired_device = std::move(local_device);
};
// Synchronously (wait until) get Device
wgpu::Future waitDeviceFunc { adapter.RequestDevice(&device_desc, wgpu::CallbackMode::WaitAnyOnly, onRequestDevice) };
wgpu::WaitStatus waitStatusDevice = instance.WaitAny(waitDeviceFunc, UINT64_MAX);
IM_ASSERT(acquired_device != nullptr && waitStatusDevice == wgpu::WaitStatus::Success && "Error on Device request");
return acquired_device.MoveToCHandle();
}
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#ifdef __EMSCRIPTEN__
// Adapter and device initialization via JS
EM_ASYNC_JS( void, getAdapterAndDeviceViaJS, (),
{
if (!navigator.gpu)
throw Error("WebGPU not supported.");
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
Module.preinitializedWebGPUDevice = device;
} );
#else // __EMSCRIPTEN__
static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void* userdata1, void* userdata2)
{
if (status == WGPURequestAdapterStatus_Success)
{
WGPUAdapter* extAdapter = (WGPUAdapter*)userdata1;
*extAdapter = adapter;
}
else
{
printf("Request_adapter status=%#.8x message=%.*s\n", status, (int) message.length, message.data);
}
}
static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void* userdata1, void* userdata2)
{
if (status == WGPURequestDeviceStatus_Success)
{
WGPUDevice* extDevice = (WGPUDevice*)userdata1;
*extDevice = device;
}
else
{
printf("Request_device status=%#.8x message=%.*s\n", status, (int) message.length, message.data);
}
}
static WGPUAdapter RequestAdapter(WGPUInstance& instance)
{
WGPURequestAdapterOptions adapter_options = {};
WGPUAdapter local_adapter;
WGPURequestAdapterCallbackInfo adapterCallbackInfo = {};
adapterCallbackInfo.callback = handle_request_adapter;
adapterCallbackInfo.userdata1 = &local_adapter;
wgpuInstanceRequestAdapter(instance, &adapter_options, adapterCallbackInfo);
IM_ASSERT(local_adapter && "Error on Adapter request");
return local_adapter;
}
static WGPUDevice RequestDevice(WGPUAdapter& adapter)
{
auto onDeviceRequestEnded = [](WGPURequestDeviceStatus status, WGPUDevice device, const char* message, void* pUserData)
{
if (status == WGPURequestDeviceStatus_Success)
*(WGPUDevice*)(pUserData) = device;
else
printf("Could not get WebGPU device: %s\n", message);
};
WGPUDevice device;
wgpuAdapterRequestDevice(adapter, nullptr, onDeviceRequestEnded, (void*)&device);
return device;
WGPUDevice local_device;
WGPURequestDeviceCallbackInfo deviceCallbackInfo = {};
deviceCallbackInfo.callback = handle_request_device;
deviceCallbackInfo.userdata1 = &local_device;
wgpuAdapterRequestDevice(adapter, nullptr, deviceCallbackInfo);
IM_ASSERT(local_device && "Error on Device request");
return local_device;
}
#endif
#endif // __EMSCRIPTEN__
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
static bool InitWGPU(GLFWwindow* window)
bool InitWGPU(GLFWwindow* window)
{
wgpu::Instance instance = wgpuCreateInstance(nullptr);
WGPUTextureFormat preferred_fmt = WGPUTextureFormat_Undefined; // acquired from SurfaceCapabilities
#ifdef __EMSCRIPTEN__
wgpu_device = emscripten_webgpu_get_device();
if (!wgpu_device)
return false;
#else
WGPUAdapter adapter = RequestAdapter(instance.Get());
if (!adapter)
return false;
wgpu_device = RequestDevice(adapter);
#endif
// Google DAWN backend: Adapter and Device acquisition, Surface creation
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
wgpu::InstanceDescriptor instance_desc = {};
static constexpr wgpu::InstanceFeatureName timedWaitAny = wgpu::InstanceFeatureName::TimedWaitAny;
instance_desc.requiredFeatureCount = 1;
instance_desc.requiredFeatures = &timedWaitAny;
wgpu::Instance instance = wgpu::CreateInstance(&instance_desc);
wgpu::Adapter adapter = RequestAdapter(instance);
ImGui_ImplWGPU_DebugPrintAdapterInfo(adapter.Get());
wgpu_device = RequestDevice(instance, adapter);
// Create the surface.
#ifdef __EMSCRIPTEN__
wgpu::SurfaceDescriptorFromCanvasHTMLSelector html_surface_desc = {};
html_surface_desc.selector = "#canvas";
wgpu::EmscriptenSurfaceSourceCanvasHTMLSelector canvas_desc = {};
canvas_desc.selector = "#canvas";
wgpu::SurfaceDescriptor surface_desc = {};
surface_desc.nextInChain = &html_surface_desc;
wgpu::Surface surface = instance.CreateSurface(&surface_desc);
wgpu::Adapter adapter = {};
wgpu_preferred_fmt = (WGPUTextureFormat)surface.GetPreferredFormat(adapter);
surface_desc.nextInChain = &canvas_desc;
wgpu_surface = instance.CreateSurface(&surface_desc).MoveToCHandle();
#else
wgpu::Surface surface = wgpu::glfw::CreateSurfaceForWindow(instance, window);
if (!surface)
return false;
wgpu_preferred_fmt = WGPUTextureFormat_BGRA8Unorm;
wgpu_surface = CreateWGPUSurface(instance.Get(), window);
#endif
if (!wgpu_surface)
return false;
// Moving Dawn objects into WGPU handles
wgpu_instance = instance.MoveToCHandle();
wgpu_surface = surface.MoveToCHandle();
wgpuDeviceSetUncapturedErrorCallback(wgpu_device, wgpu_error_callback, nullptr);
WGPUSurfaceCapabilities surface_capabilities = {};
wgpuSurfaceGetCapabilities(wgpu_surface, adapter.Get(), &surface_capabilities);
preferred_fmt = surface_capabilities.formats[0];
// WGPU backend: Adapter and Device acquisition, Surface creation
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
wgpu_instance = wgpuCreateInstance(nullptr);
#ifdef __EMSCRIPTEN__
getAdapterAndDeviceViaJS();
wgpu_device = emscripten_webgpu_get_device();
IM_ASSERT(wgpu_device != nullptr && "Error creating the Device");
WGPUSurfaceDescriptorFromCanvasHTMLSelector html_surface_desc = {};
html_surface_desc.chain.sType = WGPUSType_SurfaceDescriptorFromCanvasHTMLSelector;
html_surface_desc.selector = "#canvas";
WGPUSurfaceDescriptor surface_desc = {};
surface_desc.nextInChain = &html_surface_desc.chain;
// Create the surface.
wgpu_surface = wgpuInstanceCreateSurface(wgpu_instance, &surface_desc);
preferred_fmt = wgpuSurfaceGetPreferredFormat(wgpu_surface, {} /* adapter */);
#else // __EMSCRIPTEN__
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);
WGPUAdapter adapter = RequestAdapter(wgpu_instance);
ImGui_ImplWGPU_DebugPrintAdapterInfo(adapter);
wgpu_device = RequestDevice(adapter);
// Create the surface.
wgpu_surface = CreateWGPUSurface(wgpu_instance, window);
if (!wgpu_surface)
return false;
WGPUSurfaceCapabilities surface_capabilities = {};
wgpuSurfaceGetCapabilities(wgpu_surface, adapter, &surface_capabilities);
preferred_fmt = surface_capabilities.formats[0];
#endif // __EMSCRIPTEN__
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
wgpu_surface_configuration.presentMode = WGPUPresentMode_Fifo;
wgpu_surface_configuration.alphaMode = WGPUCompositeAlphaMode_Auto;
wgpu_surface_configuration.usage = WGPUTextureUsage_RenderAttachment;
wgpu_surface_configuration.width = wgpu_surface_width;
wgpu_surface_configuration.height = wgpu_surface_height;
wgpu_surface_configuration.device = wgpu_device;
wgpu_surface_configuration.format = preferred_fmt;
wgpuSurfaceConfigure(wgpu_surface, &wgpu_surface_configuration);
wgpu_queue = wgpuDeviceGetQueue(wgpu_device);
return true;
}
static void CreateSwapChain(int width, int height)
// GLFW helper to create a WebGPU surface, used only in WGPU-Native. DAWN-Native already has a built-in function
// As of today (2025/10) there is no "official" support in GLFW to create a surface for WebGPU backend
// This stub uses "low level" GLFW calls to acquire information from a specific Window Manager.
// Currently supported platforms: Windows / Linux (X11 and Wayland) / MacOS. Not necessary nor available with EMSCRIPTEN.
#ifndef __EMSCRIPTEN__
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
#define GLFW_HAS_X11_OR_WAYLAND 1
#else
#define GLFW_HAS_X11_OR_WAYLAND 0
#endif
#ifdef _WIN32
#undef APIENTRY
#ifndef GLFW_EXPOSE_NATIVE_WIN32 // for glfwGetWin32Window()
#define GLFW_EXPOSE_NATIVE_WIN32
#endif
#elif defined(__APPLE__)
#ifndef GLFW_EXPOSE_NATIVE_COCOA // for glfwGetCocoaWindow()
#define GLFW_EXPOSE_NATIVE_COCOA
#endif
#elif GLFW_HAS_X11_OR_WAYLAND
#ifndef GLFW_EXPOSE_NATIVE_X11 // for glfwGetX11Display(), glfwGetX11Window() on Freedesktop (Linux, BSD, etc.)
#define GLFW_EXPOSE_NATIVE_X11
#endif
#ifndef GLFW_EXPOSE_NATIVE_WAYLAND
#if defined(__has_include) && __has_include(<wayland-client.h>)
#define GLFW_EXPOSE_NATIVE_WAYLAND
#endif
#endif
#endif
#include <GLFW/glfw3native.h>
#undef Status // X11 headers are leaking this and also 'Success', 'Always', 'None', all used in DAWN api. Add #undef if necessary.
WGPUSurface CreateWGPUSurface(const WGPUInstance& instance, GLFWwindow* window)
{
if (wgpu_swap_chain)
wgpuSwapChainRelease(wgpu_swap_chain);
wgpu_swap_chain_width = width;
wgpu_swap_chain_height = height;
WGPUSwapChainDescriptor swap_chain_desc = {};
swap_chain_desc.usage = WGPUTextureUsage_RenderAttachment;
swap_chain_desc.format = wgpu_preferred_fmt;
swap_chain_desc.width = width;
swap_chain_desc.height = height;
swap_chain_desc.presentMode = WGPUPresentMode_Fifo;
wgpu_swap_chain = wgpuDeviceCreateSwapChain(wgpu_device, wgpu_surface, &swap_chain_desc);
ImGui_ImplWGPU_CreateSurfaceInfo create_info = {};
create_info.Instance = instance;
#if defined(GLFW_EXPOSE_NATIVE_COCOA)
{
create_info.System = "cocoa";
create_info.RawWindow = (void*)glfwGetCocoaWindow(window);
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
}
#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND)
if (glfwGetPlatform() == GLFW_PLATFORM_WAYLAND)
{
create_info.System = "wayland";
create_info.RawDisplay = (void*)glfwGetWaylandDisplay();
create_info.RawSurface = (void*)glfwGetWaylandWindow(window);
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
}
#elif defined(GLFW_EXPOSE_NATIVE_X11)
if (glfwGetPlatform() == GLFW_PLATFORM_X11)
{
create_info.System = "x11";
create_info.RawWindow = (void*)glfwGetX11Window(window);
create_info.RawDisplay = (void*)glfwGetX11Display();
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
}
#elif defined(GLFW_EXPOSE_NATIVE_WIN32)
{
create_info.System = "win32";
create_info.RawWindow = (void*)glfwGetWin32Window(window);
create_info.RawInstance = (void*)::GetModuleHandle(NULL);
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
}
#else
#error "Unsupported WebGPU native platform!"
#endif
return nullptr;
}
#endif // #ifndef __EMSCRIPTEN__

View File

@@ -1,84 +0,0 @@
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"/>
<title>Dear ImGui Emscripten+GLFW+WebGPU example</title>
<style>
body { margin: 0; background-color: black }
.emscripten {
position: absolute;
top: 0px;
left: 0px;
margin: 0px;
border: 0;
width: 100%;
height: 100%;
overflow: hidden;
display: block;
image-rendering: optimizeSpeed;
image-rendering: -moz-crisp-edges;
image-rendering: -o-crisp-edges;
image-rendering: -webkit-optimize-contrast;
image-rendering: optimize-contrast;
image-rendering: crisp-edges;
image-rendering: pixelated;
-ms-interpolation-mode: nearest-neighbor;
}
</style>
</head>
<body>
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
<script type='text/javascript'>
var Module;
(async () => {
Module = {
preRun: [],
postRun: [],
print: (function() {
return function(text) {
text = Array.prototype.slice.call(arguments).join(' ');
console.log(text);
};
})(),
printErr: function(text) {
text = Array.prototype.slice.call(arguments).join(' ');
console.error(text);
},
canvas: (function() {
var canvas = document.getElementById('canvas');
//canvas.addEventListener("webglcontextlost", function(e) { alert('FIXME: WebGL context lost, please reload the page'); e.preventDefault(); }, false);
return canvas;
})(),
setStatus: function(text) {
console.log("status: " + text);
},
monitorRunDependencies: function(left) {
// no run dependencies to log
}
};
window.onerror = function() {
console.log("onerror: " + event);
};
// Initialize the graphics adapter
{
if (!navigator.gpu) {
throw Error("WebGPU not supported.");
}
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
Module.preinitializedWebGPUDevice = device;
}
{
const js = document.createElement('script');
js.async = true;
js.src = "index.js";
document.body.appendChild(js);
}
})();
</script>
</body>
</html>

View File

@@ -48,7 +48,7 @@ int main(int argc, char** argv)
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
#endif
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_MULTISAMPLE);
glutInitWindowSize(1280, 720);
glutInitWindowSize(1280, 800);
glutCreateWindow("Dear ImGui GLUT+OpenGL2 Example");
// Setup GLUT display function
@@ -78,16 +78,17 @@ int main(int argc, char** argv)
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
ImGui_ImplGLUT_InstallFuncs();
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
// - Read 'docs/FONTS.md' for more instructions and details.
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
//style.FontSizeBase = 20.0f;
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontDefaultVector();
//io.Fonts->AddFontDefaultBitmap();
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");

View File

@@ -0,0 +1,178 @@
<?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>{1A0BF63C-18EF-4BAE-A8DA-055481B11F5D}</ProjectGuid>
<RootNamespace>example_win32_directx11</RootNamespace>
</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>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</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>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</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>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\backends\imgui_impl_null.h" />
<ClInclude Include="..\..\imconfig.h" />
<ClInclude Include="..\..\imgui.h" />
<ClInclude Include="..\..\imgui_internal.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\backends\imgui_impl_null.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<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="main.cpp" />
</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>

View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="imgui">
<UniqueIdentifier>{0587d7a3-f2ce-4d56-b84f-a0005d3bfce6}</UniqueIdentifier>
</Filter>
<Filter Include="sources">
<UniqueIdentifier>{08e36723-ce4f-4cff-9662-c40801cf1acf}</UniqueIdentifier>
</Filter>
</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_null.h">
<Filter>sources</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\imgui.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="main.cpp">
<Filter>sources</Filter>
</ClCompile>
<ClCompile Include="..\..\imgui_demo.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="..\..\imgui_draw.cpp">
<Filter>imgui</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_null.cpp">
<Filter>sources</Filter>
</ClCompile>
</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>

View File

@@ -4,23 +4,26 @@
#include "imgui.h"
#include <stdio.h>
// For imgui_impl_null: use relative filename + embed implementation directly by including the .cpp file.
// This is to simplify casual building of this example from all sorts of test scripts.
#include "../../backends/imgui_impl_null.h"
#include "../../backends/imgui_impl_null.cpp"
int main(int, char**)
{
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
// Build atlas
//unsigned char* tex_pixels = nullptr;
//int tex_w, tex_h;
//io.Fonts->GetTexDataAsRGBA32(&tex_pixels, &tex_w, &tex_h);
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures;
ImGui_ImplNullPlatform_Init();
ImGui_ImplNullRender_Init();
for (int n = 0; n < 20; n++)
{
printf("NewFrame() %d\n", n);
io.DisplaySize = ImVec2(1920, 1080);
io.DeltaTime = 1.0f / 60.0f;
ImGui_ImplNullPlatform_NewFrame();
ImGui_ImplNullRender_NewFrame();
ImGui::NewFrame();
static float f = 0.0f;
@@ -33,6 +36,8 @@ int main(int, char**)
}
printf("DestroyContext()\n");
ImGui_ImplNullRender_Shutdown();
ImGui_ImplNullPlatform_Shutdown();
ImGui::DestroyContext();
return 0;
}

View File

@@ -39,7 +39,7 @@ int main(int, char**)
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
{
printf("Error: %s\n", SDL_GetError());
return -1;
return 1;
}
// From 2.0.18: Enable native IME.
@@ -50,11 +50,11 @@ int main(int, char**)
// Setup window
float main_scale = ImGui_ImplSDL2_GetContentScaleForDisplay(0);
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+DirectX11 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (int)(1280 * main_scale), (int)(720 * main_scale), window_flags);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+DirectX11 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (int)(1280 * main_scale), (int)(800 * main_scale), window_flags);
if (window == nullptr)
{
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return -1;
return 1;
}
SDL_SysWMinfo wmInfo;
@@ -83,21 +83,23 @@ int main(int, char**)
// Setup scaling
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
style.FontScaleDpi = main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose)
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
// Setup Platform/Renderer backends
ImGui_ImplSDL2_InitForD3D(window);
ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext);
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
// - Read 'docs/FONTS.md' for more instructions and details.
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
//style.FontSizeBase = 20.0f;
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontDefaultVector();
//io.Fonts->AddFontDefaultBitmap();
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
@@ -210,6 +212,7 @@ int main(int, char**)
bool CreateDeviceD3D(HWND hWnd)
{
// Setup swap chain
// This is a basic setup. Optimally could use e.g. DXGI_SWAP_EFFECT_FLIP_DISCARD and handle fullscreen mode differently. See #8979 for suggestions.
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 2;
@@ -230,7 +233,10 @@ bool CreateDeviceD3D(HWND hWnd)
//createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
D3D_FEATURE_LEVEL featureLevel;
const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, };
if (D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext) != S_OK)
HRESULT res = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext);
if (res == DXGI_ERROR_UNSUPPORTED) // Try high-performance WARP software driver if hardware is not available.
res = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_WARP, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext);
if (res != S_OK)
return false;
CreateRenderTarget();

View File

@@ -30,14 +30,16 @@ int main(int, char**)
//ImGui::StyleColorsLight();
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
// - Read 'docs/FONTS.md' for more instructions and details.
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
//style.FontSizeBase = 20.0f;
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontDefaultVector();
//io.Fonts->AddFontDefaultBitmap();
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
@@ -51,7 +53,7 @@ int main(int, char**)
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
{
printf("Error: %s\n", SDL_GetError());
return -1;
return 1;
}
// Inform SDL that we will be using metal for rendering. Without this hint initialization of metal renderer may fail.
@@ -60,7 +62,7 @@ int main(int, char**)
// Enable native IME.
SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL+Metal example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL+Metal example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 800, SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
if (window == nullptr)
{
printf("Error creating window: %s\n", SDL_GetError());

View File

@@ -31,7 +31,7 @@ int main(int, char**)
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
{
printf("Error: %s\n", SDL_GetError());
return -1;
return 1;
}
// From 2.0.18: Enable native IME.
@@ -47,11 +47,11 @@ int main(int, char**)
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
float main_scale = ImGui_ImplSDL2_GetContentScaleForDisplay(0);
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (int)(1280 * main_scale), (int)(720 * main_scale), window_flags);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (int)(1280 * main_scale), (int)(800 * main_scale), window_flags);
if (window == nullptr)
{
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return -1;
return 1;
}
SDL_GLContext gl_context = SDL_GL_CreateContext(window);
@@ -72,21 +72,23 @@ int main(int, char**)
// Setup scaling
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
style.FontScaleDpi = main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose)
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
// Setup Platform/Renderer backends
ImGui_ImplSDL2_InitForOpenGL(window, gl_context);
ImGui_ImplOpenGL2_Init();
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
// - Read 'docs/FONTS.md' for more instructions and details.
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
//style.FontSizeBase = 20.0f;
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontDefaultVector();
//io.Fonts->AddFontDefaultBitmap();
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");

View File

@@ -36,7 +36,7 @@ int main(int, char**)
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
{
printf("Error: %s\n", SDL_GetError());
return -1;
return 1;
}
// Decide GL+GLSL versions
@@ -81,18 +81,18 @@ int main(int, char**)
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
float main_scale = ImGui_ImplSDL2_GetContentScaleForDisplay(0);
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL3 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (int)(1280 * main_scale), (int)(720 * main_scale), window_flags);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL3 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (int)(1280 * main_scale), (int)(800 * main_scale), window_flags);
if (window == nullptr)
{
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return -1;
return 1;
}
SDL_GLContext gl_context = SDL_GL_CreateContext(window);
if (gl_context == nullptr)
{
printf("Error: SDL_GL_CreateContext(): %s\n", SDL_GetError());
return -1;
return 1;
}
SDL_GL_MakeCurrent(window, gl_context);
@@ -112,22 +112,24 @@ int main(int, char**)
// Setup scaling
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
style.FontScaleDpi = main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose)
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
// Setup Platform/Renderer backends
ImGui_ImplSDL2_InitForOpenGL(window, gl_context);
ImGui_ImplOpenGL3_Init(glsl_version);
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
// - Read 'docs/FONTS.md' for more instructions and details.
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
// - Our Emscripten build process allows embedding fonts to be accessible at runtime from the "fonts/" folder. See Makefile.emscripten for details.
//style.FontSizeBase = 20.0f;
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontDefaultVector();
//io.Fonts->AddFontDefaultBitmap();
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");

View File

@@ -33,7 +33,7 @@ int main(int, char**)
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
{
printf("Error: %s\n", SDL_GetError());
return -1;
return 1;
}
// From 2.0.18: Enable native IME.
@@ -44,17 +44,17 @@ int main(int, char**)
// Create window with SDL_Renderer graphics context
float main_scale = ImGui_ImplSDL2_GetContentScaleForDisplay(0);
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+SDL_Renderer example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (int)(1280 * main_scale), (int)(720 * main_scale), window_flags);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+SDL_Renderer example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (int)(1280 * main_scale), (int)(800 * main_scale), window_flags);
if (window == nullptr)
{
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return -1;
return 1;
}
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
if (renderer == nullptr)
{
SDL_Log("Error creating SDL_Renderer!");
return -1;
return 1;
}
//SDL_RendererInfo info;
//SDL_GetRendererInfo(renderer, &info);
@@ -74,21 +74,23 @@ int main(int, char**)
// Setup scaling
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
style.FontScaleDpi = main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose)
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
// Setup Platform/Renderer backends
ImGui_ImplSDL2_InitForSDLRenderer(window, renderer);
ImGui_ImplSDLRenderer2_Init(renderer);
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
// - Read 'docs/FONTS.md' for more instructions and details.
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
//style.FontSizeBase = 20.0f;
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontDefaultVector();
//io.Fonts->AddFontDefaultBitmap();
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");

View File

@@ -192,7 +192,7 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
pool_info.maxSets = 0;
for (VkDescriptorPoolSize& pool_size : pool_sizes)
pool_info.maxSets += pool_size.descriptorCount;
pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes);
pool_info.poolSizeCount = (uint32_t)IM_COUNTOF(pool_sizes);
pool_info.pPoolSizes = pool_sizes;
err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool);
check_vk_result(err);
@@ -203,11 +203,9 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
// Your real engine/app may not use them.
static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface, int width, int height)
{
wd->Surface = surface;
// Check for WSI support
VkBool32 res;
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, wd->Surface, &res);
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, surface, &res);
if (res != VK_TRUE)
{
fprintf(stderr, "Error no WSI support on physical device 0\n");
@@ -217,7 +215,8 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface
// Select Surface Format
const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
wd->Surface = surface;
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_COUNTOF(requestSurfaceImageFormat), requestSurfaceColorSpace);
// Select Present Mode
#ifdef APP_USE_UNLIMITED_FRAME_RATE
@@ -225,12 +224,12 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface
#else
VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_FIFO_KHR };
#endif
wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_modes[0], IM_ARRAYSIZE(present_modes));
wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_modes[0], IM_COUNTOF(present_modes));
//printf("[vulkan] Selected PresentMode = %d\n", wd->PresentMode);
// Create SwapChain, RenderPass, Framebuffer, etc.
IM_ASSERT(g_MinImageCount >= 2);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, 0);
}
static void CleanupVulkan()
@@ -247,9 +246,10 @@ static void CleanupVulkan()
vkDestroyInstance(g_Instance, g_Allocator);
}
static void CleanupVulkanWindow()
static void CleanupVulkanWindow(ImGui_ImplVulkanH_Window* wd)
{
ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, &g_MainWindowData, g_Allocator);
ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, wd, g_Allocator);
vkDestroySurfaceKHR(g_Instance, wd->Surface, g_Allocator);
}
static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
@@ -349,7 +349,7 @@ int main(int, char**)
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
{
printf("Error: %s\n", SDL_GetError());
return -1;
return 1;
}
// From 2.0.18: Enable native IME.
@@ -360,11 +360,11 @@ int main(int, char**)
// Create window with Vulkan graphics context
float main_scale = ImGui_ImplSDL2_GetContentScaleForDisplay(0);
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+Vulkan example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (int)(1280 * main_scale), (int)(720 * main_scale), window_flags);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+Vulkan example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (int)(1280 * main_scale), (int)(800 * main_scale), window_flags);
if (window == nullptr)
{
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return -1;
return 1;
}
ImVector<const char*> extensions;
@@ -403,7 +403,7 @@ int main(int, char**)
// Setup scaling
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
style.FontScaleDpi = main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose)
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
// Setup Platform/Renderer backends
ImGui_ImplSDL2_InitForVulkan(window);
@@ -416,24 +416,26 @@ int main(int, char**)
init_info.Queue = g_Queue;
init_info.PipelineCache = g_PipelineCache;
init_info.DescriptorPool = g_DescriptorPool;
init_info.RenderPass = wd->RenderPass;
init_info.Subpass = 0;
init_info.MinImageCount = g_MinImageCount;
init_info.ImageCount = wd->ImageCount;
init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
init_info.Allocator = g_Allocator;
init_info.PipelineInfoMain.RenderPass = wd->RenderPass;
init_info.PipelineInfoMain.Subpass = 0;
init_info.PipelineInfoMain.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
init_info.CheckVkResultFn = check_vk_result;
ImGui_ImplVulkan_Init(&init_info);
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
// - Read 'docs/FONTS.md' for more instructions and details.
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
//style.FontSizeBase = 20.0f;
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontDefaultVector();
//io.Fonts->AddFontDefaultBitmap();
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
@@ -476,7 +478,7 @@ int main(int, char**)
if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height))
{
ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, 0);
g_MainWindowData.FrameIndex = 0;
g_SwapChainRebuild = false;
}
@@ -545,7 +547,7 @@ int main(int, char**)
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();
CleanupVulkanWindow();
CleanupVulkanWindow(&g_MainWindowData);
CleanupVulkan();
SDL_DestroyWindow(window);

View File

@@ -0,0 +1,205 @@
# Building for desktop (WebGPU-native) 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]
# Building for desktop (WGPU-Native) 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]
# Building for Emscripten:
# 1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html
# 2. Install Ninja build system
# 3. emcmake cmake -G Ninja -B build
# (optional) -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path/to/emdawnwebgpu_package/emdawnwebgpu.port.py", see ReadMe.md
# 3. cmake --build build
# 4. emrun build/index.html
cmake_minimum_required(VERSION 3.22) # Dawn requires CMake >= 3.22
project(imgui_example_sdl2_wgpu C CXX)
set(IMGUI_EXECUTABLE example_sdl2_wgpu)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
endif()
set(CMAKE_CXX_STANDARD 17) # Dawn requires C++17
# Dear ImGui
set(IMGUI_DIR ../../)
# ImGui example commons source files
set(IMGUI_EXAMPLE_SOURCE_FILES
main.cpp
# backend files
${IMGUI_DIR}/backends/imgui_impl_sdl2.cpp
${IMGUI_DIR}/backends/imgui_impl_wgpu.cpp
# Dear ImGui files
${IMGUI_DIR}/imgui.cpp
${IMGUI_DIR}/imgui_draw.cpp
${IMGUI_DIR}/imgui_demo.cpp
${IMGUI_DIR}/imgui_tables.cpp
${IMGUI_DIR}/imgui_widgets.cpp
)
if(EMSCRIPTEN)
if(NOT IMGUI_EMSCRIPTEN_WEBGPU_FLAG) # if IMGUI_EMSCRIPTEN_WEBGPU_FLAG not used, set by current EMSCRIPTEN version
if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "4.0.10")
set(IMGUI_EMSCRIPTEN_WEBGPU_FLAG "--use-port=emdawnwebgpu" CACHE STRING "Choose between --use-port=emdawnwebgpu (Dawn implementation of EMSCRIPTEN) and -sUSE_WEBGPU=1 (WGPU implementation of EMSCRIPTEN, deprecated in 4.0.10): default to --use-port=emdawnwebgpu for EMSCRIPTEN >= 4.0.10")
else()
set(IMGUI_EMSCRIPTEN_WEBGPU_FLAG "-sUSE_WEBGPU=1" CACHE STRING "Use -sUSE_WEBGPU=1 for EMSCRIPTEN WGPU implementation")
endif()
else() # if IMGUI_EMSCRIPTEN_WEBGPU_FLAG used, check correct version
if(EMSCRIPTEN_VERSION VERSION_LESS "4.0.10" AND "${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}" MATCHES "emdawnwebgpu")
# it's necessary EMSCRIPTEN >= v4.0.10 (although "--use-port=path/to/emdawnwebgpu.port.py" is supported/tested from v4.0.8)
message(FATAL_ERROR "emdawnwebgpu needs EMSCRIPTEN version >= 4.0.10")
endif()
endif()
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")
endif()
if(APPLE) # Add SDL2 module to get Surface, with libs and file property for MacOS build
set_source_files_properties(${IMGUI_DIR}/backends/imgui_impl_wgpu.cpp PROPERTIES COMPILE_FLAGS "-x objective-c++")
set(OS_LIBRARIES "-framework CoreFoundation -framework QuartzCore -framework Metal -framework MetalKit -framework Cocoa")
endif()
find_package(SDL2 REQUIRED) # SDL_MAIN_HANDLED
if(IMGUI_DAWN_DIR) # DAWN-Native build options
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
if(Dawn_FOUND)
message("Dawn Installation has been found!")
set(LIBRARIES dawn::webgpu_dawn ${OS_LIBRARIES})
else()
set(IMGUI_DAWN_DIR CACHE PATH "Path to Dawn repository")
option(DAWN_USE_GLFW OFF) # disable builtin GLFW in DAWN when we use SDL2 / SDL3
option(DAWN_FETCH_DEPENDENCIES "Use fetch_dawn_dependencies.py as an alternative to using depot_tools" ON)
set(DAWN_BUILD_MONOLITHIC_LIBRARY "STATIC" CACHE STRING "Build monolithic library: SHARED, STATIC, or OFF.")
# Dawn builds many things by default - disable things we don't need
option(DAWN_BUILD_SAMPLES "Enables building Dawn's samples" OFF)
option(TINT_BUILD_CMD_TOOLS "Build the Tint command line tools" OFF)
option(TINT_BUILD_DOCS "Build documentation" OFF)
option(TINT_BUILD_TESTS "Build tests" OFF)
if(NOT APPLE)
option(TINT_BUILD_MSL_WRITER "Build the MSL output writer" OFF)
endif()
if(WIN32)
option(DAWN_FORCE_SYSTEM_COMPONENT_LOAD "Allow system component fallback" ON)
option(TINT_BUILD_SPV_READER "Build the SPIR-V input reader" OFF)
option(TINT_BUILD_WGSL_READER "Build the WGSL input reader" ON)
option(TINT_BUILD_GLSL_WRITER "Build the GLSL output writer" OFF)
option(TINT_BUILD_GLSL_VALIDATOR "Build the GLSL output validator" OFF)
option(TINT_BUILD_SPV_WRITER "Build the SPIR-V output writer" ON)
option(TINT_BUILD_WGSL_WRITER "Build the WGSL output writer" ON)
endif()
# check if WAYLAND is the current Session Type and enable DAWN_USE_WAYLAND Wayland option @compile time
# You can override this using: cmake -DDAWN_USE_WAYLAND=X (X = ON | OFF)
if(LINUX)
if($ENV{XDG_SESSION_TYPE} MATCHES wayland)
option(DAWN_USE_WAYLAND "Enable support for Wayland surface" ON)
endif()
endif()
add_subdirectory("${IMGUI_DAWN_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/dawn" EXCLUDE_FROM_ALL)
set(LIBRARIES webgpu_dawn ${OS_LIBRARIES})
endif()
else() # WGPU-Native build options
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)
set(OS_LIBRARIES d3dcompiler ws2_32 userenv bcrypt ntdll opengl32 Propsys RuntimeObject)
elseif(UNIX AND NOT APPLE)
set(OS_LIBRARIES "-lm -ldl")
endif()
set(LIBRARIES ${WGPU_LIBRARY} ${OS_LIBRARIES})
endif()
endif()
add_executable(${IMGUI_EXECUTABLE} ${IMGUI_EXAMPLE_SOURCE_FILES})
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC
${IMGUI_DIR}
${IMGUI_DIR}/backends
${SDL2_INCLUDE_DIRS}
)
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_EXAMPLE_SDL2_WGPU")
# compiler option only for IMGUI_EXAMPLE_SOURCE_FILES
if (MSVC)
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC /W4) # warning level 4
else()
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC -Wall) # -Wextra -Wpedantic
endif()
# IMGUI_IMPL_WEBGPU_BACKEND_DAWN/WGPU internal define is set according to:
# EMSCRIPTEN: by used FLAG
# --use-port=emdawnwebgpu --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN enabled (+EMSCRIPTEN)
# -sUSE_WEBGPU=1 --> IMGUI_IMPL_WEBGPU_BACKEND_WGPU enabled (+EMSCRIPTEN)
# NATIVE: by used SDK installation directory
# if IMGUI_DAWN_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN enabled
# if IMGUI_WGPU_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_WGPU enabled
if(NOT EMSCRIPTEN) # WegGPU-Native settings
if(IMGUI_DAWN_DIR)
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_DAWN")
if(NOT Dawn_FOUND)
target_link_libraries(${IMGUI_EXECUTABLE} INTERFACE webgpu_cpp)
endif()
else()
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGPU_DIR}/include)
endif()
target_link_libraries(${IMGUI_EXECUTABLE} PUBLIC ${LIBRARIES} ${SDL2_LIBRARIES})
else() # Emscripten settings
set(CMAKE_EXECUTABLE_SUFFIX ".html")
if("${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}" MATCHES "emdawnwebgpu")
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}")
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_DAWN")
else()
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
endif()
message(STATUS "Using ${IMGUI_EMSCRIPTEN_WEBGPU_FLAG} WebGPU implementation")
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "-sUSE_SDL=2")
target_link_options(${IMGUI_EXECUTABLE} PRIVATE
"${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}"
"-sUSE_SDL=2"
"-sWASM=1"
"-sASYNCIFY=1"
"-sALLOW_MEMORY_GROWTH=1"
"-sNO_EXIT_RUNTIME=0"
"-sASSERTIONS=1"
"-sDISABLE_EXCEPTION_CATCHING=1"
"-sNO_FILESYSTEM=1"
"--shell-file=${CMAKE_CURRENT_LIST_DIR}/../libs/emscripten/shell_minimal.html"
)
set_target_properties(${IMGUI_EXECUTABLE} PROPERTIES OUTPUT_NAME "index")
endif()

View File

@@ -0,0 +1,103 @@
#
# Makefile to use with emscripten
# See https://emscripten.org/docs/getting_started/downloads.html
# for installation instructions.
#
# This Makefile assumes you have loaded emscripten's environment.
# (On Windows, you may need to execute emsdk_env.bat or encmdprompt.bat ahead)
#
# Running `make -f Makefile.emscripten` will produce three files:
# - web/index.html
# - web/index.js
# - web/index.wasm
#
# All three are needed to run the demo.
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_wgpu.cpp
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
UNAME_S := $(shell uname -s)
CPPFLAGS =
LDFLAGS =
EMS =
##---------------------------------------------------------------------
## EMSCRIPTEN OPTIONS
##---------------------------------------------------------------------
# ("EMS" options gets added to both CPPFLAGS and LDFLAGS, whereas some options are for linker only)
EMS += -s USE_SDL=2
EMS += -s DISABLE_EXCEPTION_CATCHING=1
LDFLAGS += -s WASM=1
LDFLAGS += -s ALLOW_MEMORY_GROWTH=1
LDFLAGS += -s ASYNCIFY=1
LDFLAGS += -s NO_EXIT_RUNTIME=0
LDFLAGS += -s ASSERTIONS=1
# (1) Using legacy WebGPU implementation (Emscripten < 4.0.10)
#EMS += -DIMGUI_IMPL_WEBGPU_BACKEND_WGPU
#LDFLAGS += -s USE_WEBGPU=1
# or (2) Using newer Dawn-based WebGPU port (Emscripten >= 4.0.10)
EMS += --use-port=emdawnwebgpu
LDFLAGS += --use-port=emdawnwebgpu
# Build as single file (binary text encoded in .html file)
#LDFLAGS += -sSINGLE_FILE
# Emscripten allows preloading a file or folder to be accessible at runtime.
# The Makefile for this example project suggests embedding the misc/fonts/ folder into our application, it will then be accessible as "/fonts"
# See documentation for more details: https://emscripten.org/docs/porting/files/packaging_files.html
# (Default value is 0. Set to 1 to enable file-system and include the misc/fonts/ folder as part of the build.)
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
##---------------------------------------------------------------------
## FINAL BUILD FLAGS
##---------------------------------------------------------------------
CPPFLAGS += -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
#CPPFLAGS += -g
CPPFLAGS += -Wall -Wformat -Os $(EMS)
LDFLAGS += --shell-file ../libs/emscripten/shell_minimal.html
LDFLAGS += $(EMS)
##---------------------------------------------------------------------
## BUILD RULES
##---------------------------------------------------------------------
%.o:%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
%.o:$(IMGUI_DIR)/%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
%.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 -f $(EXE) $(OBJS) $(WEB_DIR)/*.js $(WEB_DIR)/*.wasm $(WEB_DIR)/*.wasm.pre

View File

@@ -0,0 +1,167 @@
## How to Build
---
### Using CMake
#### Building for desktop (WebGPU-native) with Google 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]
#### Building for desktop (WebGPU-Native) with WGPU:
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]
#### Building for Emscripten:
1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html
2. Install Ninja build system
3. `emcmake cmake -G Ninja -B build`
- (optional) `-DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path/to/emdawnwebgpu_package/emdawnwebgpu.port.py"`, see below
4. `cmake --build build`
#### Sync Emscripten with latest Google Dawn:
If you want to sync Emscripten with latest DAWN release it's necessary to download the `port-emdawnwgpu-package` (released daily by Google) here:
https://github.com/google/dawn/releases
Unpack it in your preferred folder and to replace the step 3 with:
3. `emcmake cmake -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path/to/emdawnwebgpu_package/emdawnwebgpu.port.py" -G Ninja -B build`
**N.B.**
For the WASM code produced by Emscripten to work correctly, it will also be necessary to have the "corresponding" (or newer) version of Google Canary (nightly build for developers) that includes the latest changes
---
### CMake by step
#### Generate Dawn Native:
- `cmake -G Ninja -DIMGUI_DAWN_DIR=path_to_sdk_dir -B where_to_build_dir`
- Using `IMGUI_DAWN_DIR` set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
#### Generate WGPU Native:
- `cmake -G Ninja -DIMGUI_WGPU_DIR=path_to_sdk_dir -B where_to_build_dir`
- Using `IMGUI_WGPU_DIR` set `IMGUI_IMPL_WEBGPU_BACKEND_WGPU` compiler define
#### Generate Emscripten:
- `emcmake cmake -G Ninja -B where_to_build_dir`\
CMake checks the EMSCRIPEN version then:
- if EMS >= 4.0.10 uses `--use-port=emdawnwebgpu` flag to build
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
- if EMS < 4.0.10 uses `-sUSE_WEBGPU=1` flag to build
- it set `IMGUI_IMPL_WEBGPU_BACKEND_WGPU` compiler define
#### Generate Emscripten forcing `-sUSE_WEBGPU=1` deprecated flag even with EMS >= 4.0.10
- `emcmake cmake -G Ninja -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="-sUSE_WEBGPU=1" -B where_to_build_dir`
- it set `IMGUI_IMPL_WEBGPU_BACKEND_WGPU` compiler define
#### Generate Emscripten using external WebGPU library (emdawnwebgpu_pkg)
- `emcmake cmake -G Ninja -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path_to_emdawnwebgpu_pkg" -B where_to_build_dir`
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
- *To use external WebGPU library it's necessary to have EMS >= 4.0.10 or the minimum requirements specified by the package:*
- https://github.com/google/dawn/releases
#### Build time
Once the procedure for the specific builder is generated, the build command is **always the same**:
- Build using CMake
- `cmake --build where_to_build_dir`
- It will use selected builder to build the example.
- Build explicitly:
- `cd where_to_build_dir`
- `ninja`
- This is the builder chosen during the generation phase
---
### CMake useful options
#### Generator types (alternative to **ninja** builder):
- `-G Ninja` to build with __ninja__ builder
- `-G "Unix Makefiles"` to build with __make__ builder
- `-G "Visual Studio 17 2022" -A x64` to create a VS 2022 solution (.sln) file, Windows only
- **Native build only**
- Not **officially** supported to build Google Dawn
Example:
- using **make** instead **ninja**:
- `cmake -G "Unix Makefiles" -DIMGUI_DAWN_DIR=path_to_sdk_dir -B where_to_build_dir`
**Syntax is case sensitive and the "" are necessary in case of spaces between words*
#### Directories
- The directory path can be absolute or relative (starting from the current directory)
- It's necessary to use different `where_to_build_dir` for different CMake generations
#### Build type
The default build type is **Debug**
It is possible to use a different build type using:
- `-DCMAKE_BUILD_TYPE=Release`
- `-DCMAKE_BUILD_TYPE=MinSizeRel`
- `-DCMAKE_BUILD_TYPE=RelWithDebInfo`
Example:
- building **Release**:
- `cmake -G ninja -DIMGUI_WGPU_DIR=path_to_sdk_dir -DCMAKE_BUILD_TYPE=Release -B where_to_build_dir `
#### GLFW / SDL2 / SDL3 includes, libraries, search paths and package manager
Includes and libraries, by default, are searched in system/compiler paths (environment variables): you can add the path to your development tools to the environment variables without having to modify the `CMakeLists.txt` file.
- e.g. CLang search in path specified from the following environment variables:
- include files: CPATH, C_INCLUDE_PATH, CPLUS_INCLUDE_PATH
- library files: LIBRARY_PATH
If you are using a package manager (**vcpkg** / **conan** / ... ) you need/can to specify it, adding to cmake command:
- `-DCMAKE_TOOLCHAIN_FILE=path/to/package_manager.cmake`
Examples:
- using **vcpkg** package manager it's necessary adding:
- `-DCMAKE_TOOLCHAIN_FILE=<vcpkg_root_dir>/scripts/buildsystems/vcpkg.cmake`
- full cmake command using **vcpkg** package manager:
- `cmake -G Ninja -DIMGUI_DAWN_DIR=path_to_sdk_dir -DCMAKE_TOOLCHAIN_FILE=<vcpkg_root_dir>/scripts/buildsystems/vcpkg.cmake -B where_to_build_dir`
---
### Using makefile
- You need to install Emscripten from https://emscripten.org/docs/getting_started/downloads.html, and have the environment variables set, as described in https://emscripten.org/docs/getting_started/downloads.html#installation-instructions
- Depending on your configuration, in Windows you may need to run `emsdk/emsdk_env.bat` in your console to access the Emscripten command-line tools.
- You may also refer to our [Continuous Integration setup](https://github.com/ocornut/imgui/tree/master/.github/workflows) for Emscripten setup.
- Then build using `make -f Makefile.emscripten` while in the `example_glfw_wgpu/` directory.
- Requires recent Emscripten as WGPU is still a work-in-progress API.
---
## How to Run
To run on a local machine:
- Make sure your browse supports WGPU and it is enabled. WGPU is still WIP not enabled by default in most browser.
- `make serve` will use Python3 to spawn a local webserver, you can then browse http://localhost:8000 to access your build.
- Otherwise, generally you will need a local webserver:
- Quoting [https://emscripten.org/docs/getting_started](https://emscripten.org/docs/getting_started/Tutorial.html#generating-html):<br>
_"Unfortunately several browsers (including Chrome, Safari, and Internet Explorer) do not support file:// [XHR](https://emscripten.org/docs/site/glossary.html#term-xhr) requests, and cant load extra files needed by the HTML (like a .wasm file, or packaged file data as mentioned lower down). For these browsers youll need to serve the files using a [local webserver](https://emscripten.org/docs/getting_started/FAQ.html#faq-local-webserver) and then open http://localhost:8000/hello.html."_
- Emscripten SDK has a handy `emrun` command: `emrun web/example_glfw_wgpu.html --browser firefox` which will spawn a temporary local webserver (in Firefox). See https://emscripten.org/docs/compiling/Running-html-files-with-emrun.html for details.
- You may use Python 3 builtin webserver: `python -m http.server -d web` (this is what `make serve` uses).
- You may use Python 2 builtin webserver: `cd web && python -m SimpleHTTPServer`.
- If you are accessing the files over a network, certain browsers, such as Firefox, will restrict Gamepad API access to secure contexts only (e.g. https only).

View File

@@ -0,0 +1,543 @@
// Dear ImGui: standalone example application for using SDL2 + WebGPU
// - Emscripten is supported for publishing on web. See https://emscripten.org.
// - Dawn is used as a WebGPU implementation on desktop.
// Learn about Dear ImGui:
// - FAQ https://dearimgui.com/faq
// - Getting Started https://dearimgui.com/getting-started
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
// - Introduction, links and more at the top of imgui.cpp
#include "imgui.h"
#include "imgui_impl_sdl2.h"
#include "imgui_impl_wgpu.h"
#include <stdio.h>
#include <SDL.h>
// This example can also compile and run with Emscripten! See 'Makefile.emscripten' for details.
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#include <emscripten/html5.h>
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#include <emscripten/html5_webgpu.h>
#endif
#include "../libs/emscripten/emscripten_mainloop_stub.h"
#endif
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
#include <webgpu/webgpu_cpp.h>
#endif
// Data
static WGPUInstance wgpu_instance = nullptr;
static WGPUDevice wgpu_device = nullptr;
static WGPUSurface wgpu_surface = nullptr;
static WGPUQueue wgpu_queue = nullptr;
static WGPUSurfaceConfiguration wgpu_surface_configuration = {};
static int wgpu_surface_width = 1280;
static int wgpu_surface_height = 800;
// Forward declarations
static bool InitWGPU(SDL_Window* window);
WGPUSurface CreateWGPUSurface(const WGPUInstance& instance, SDL_Window* window);
static void ResizeSurface(int width, int height)
{
wgpu_surface_configuration.width = wgpu_surface_width = width;
wgpu_surface_configuration.height = wgpu_surface_height = height;
wgpuSurfaceConfigure(wgpu_surface, (WGPUSurfaceConfiguration*)&wgpu_surface_configuration);
}
// Main code
int main(int, char**)
{
// Setup SDL
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER);
// Create window with graphics context
float main_scale = ImGui_ImplSDL2_GetContentScaleForDisplay(0);
SDL_WindowFlags window_flags = SDL_WINDOW_RESIZABLE;
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)
{
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return 1;
}
// Initialize WGPU
InitWGPU(window);
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsLight();
// Setup scaling
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
// Setup Platform/Renderer backends
ImGui_ImplSDL2_InitForOther(window);
ImGui_ImplWGPU_InitInfo init_info;
init_info.Device = wgpu_device;
init_info.NumFramesInFlight = 3;
init_info.RenderTargetFormat = wgpu_surface_configuration.format;
init_info.DepthStencilFormat = WGPUTextureFormat_Undefined;
ImGui_ImplWGPU_Init(&init_info);
// Load Fonts
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
// - Read 'docs/FONTS.md' for more instructions and details.
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
// - Our Emscripten build process allows embedding fonts to be accessible at runtime from the "fonts/" folder. See Makefile.emscripten for details.
//style.FontSizeBase = 20.0f;
//io.Fonts->AddFontDefaultVector();
//io.Fonts->AddFontDefaultBitmap();
#ifndef IMGUI_DISABLE_FILE_FUNCTIONS
//io.Fonts->AddFontFromFileTTF("fonts/segoeui.ttf");
//io.Fonts->AddFontFromFileTTF("fonts/DroidSans.ttf");
//io.Fonts->AddFontFromFileTTF("fonts/Roboto-Medium.ttf");
//io.Fonts->AddFontFromFileTTF("fonts/Cousine-Regular.ttf");
//ImFont* font = io.Fonts->AddFontFromFileTTF("fonts/ArialUni.ttf");
//IM_ASSERT(font != nullptr);
#endif
// Our state
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
// Main loop
bool done = false;
#ifdef __EMSCRIPTEN__
// For an Emscripten build we are disabling file-system access, so let's not attempt to do a fopen() of the imgui.ini file.
// You may manually call LoadIniSettingsFromMemory() to load settings from your own storage.
io.IniFilename = nullptr;
EMSCRIPTEN_MAINLOOP_BEGIN
#else
while (!done)
#endif
{
// Poll and handle events (inputs, window resize, etc.)
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
SDL_Event event;
while (SDL_PollEvent(&event))
{
ImGui_ImplSDL2_ProcessEvent(&event);
if (event.type == SDL_QUIT)
done = true;
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
done = true;
}
// React to changes in screen size
int width, height;
SDL_GetWindowSize(window, &width, &height);
if (width != wgpu_surface_width || height != wgpu_surface_height)
ResizeSurface(width, height);
// Check surface status for error. If texture is not optimal, try to reconfigure the surface.
WGPUSurfaceTexture surface_texture;
wgpuSurfaceGetCurrentTexture(wgpu_surface, &surface_texture);
if (ImGui_ImplWGPU_IsSurfaceStatusError(surface_texture.status))
{
fprintf(stderr, "Unrecoverable Surface Texture status=%#.8x\n", surface_texture.status);
abort();
}
if (ImGui_ImplWGPU_IsSurfaceStatusSubOptimal(surface_texture.status))
{
if (surface_texture.texture)
wgpuTextureRelease(surface_texture.texture);
if (width > 0 && height > 0)
ResizeSurface(width, height);
continue;
}
// Start the Dear ImGui frame
ImGui_ImplWGPU_NewFrame();
ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
if (show_demo_window)
ImGui::ShowDemoWindow(&show_demo_window);
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
{
static float f = 0.0f;
static int counter = 0;
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
ImGui::Checkbox("Another Window", &show_another_window);
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
ImGui::End();
}
// 3. Show another simple window.
if (show_another_window)
{
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
ImGui::Text("Hello from another window!");
if (ImGui::Button("Close Me"))
show_another_window = false;
ImGui::End();
}
// Rendering
ImGui::Render();
WGPUTextureViewDescriptor view_desc = {};
view_desc.format = wgpu_surface_configuration.format;
view_desc.dimension = WGPUTextureViewDimension_2D;
view_desc.mipLevelCount = WGPU_MIP_LEVEL_COUNT_UNDEFINED;
view_desc.arrayLayerCount = WGPU_ARRAY_LAYER_COUNT_UNDEFINED;
view_desc.aspect = WGPUTextureAspect_All;
WGPUTextureView texture_view = wgpuTextureCreateView(surface_texture.texture, &view_desc);
WGPURenderPassColorAttachment color_attachments = {};
color_attachments.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED;
color_attachments.loadOp = WGPULoadOp_Clear;
color_attachments.storeOp = WGPUStoreOp_Store;
color_attachments.clearValue = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w };
color_attachments.view = texture_view;
WGPURenderPassDescriptor render_pass_desc = {};
render_pass_desc.colorAttachmentCount = 1;
render_pass_desc.colorAttachments = &color_attachments;
render_pass_desc.depthStencilAttachment = nullptr;
WGPUCommandEncoderDescriptor enc_desc = {};
WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(wgpu_device, &enc_desc);
WGPURenderPassEncoder pass = wgpuCommandEncoderBeginRenderPass(encoder, &render_pass_desc);
ImGui_ImplWGPU_RenderDrawData(ImGui::GetDrawData(), pass);
wgpuRenderPassEncoderEnd(pass);
WGPUCommandBufferDescriptor cmd_buffer_desc = {};
WGPUCommandBuffer cmd_buffer = wgpuCommandEncoderFinish(encoder, &cmd_buffer_desc);
wgpuQueueSubmit(wgpu_queue, 1, &cmd_buffer);
#ifndef __EMSCRIPTEN__
wgpuSurfacePresent(wgpu_surface);
// Tick needs to be called in Dawn to display validation errors
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
wgpuDeviceTick(wgpu_device);
#endif
#endif
wgpuTextureViewRelease(texture_view);
wgpuRenderPassEncoderRelease(pass);
wgpuCommandEncoderRelease(encoder);
wgpuCommandBufferRelease(cmd_buffer);
}
#ifdef __EMSCRIPTEN__
EMSCRIPTEN_MAINLOOP_END;
#endif
// Cleanup
ImGui_ImplWGPU_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();
wgpuSurfaceUnconfigure(wgpu_surface);
wgpuSurfaceRelease(wgpu_surface);
wgpuQueueRelease(wgpu_queue);
wgpuDeviceRelease(wgpu_device);
wgpuInstanceRelease(wgpu_instance);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
static WGPUAdapter RequestAdapter(wgpu::Instance& instance)
{
wgpu::Adapter acquired_adapter;
wgpu::RequestAdapterOptions adapter_options;
auto onRequestAdapter = [&](wgpu::RequestAdapterStatus status, wgpu::Adapter adapter, wgpu::StringView message)
{
if (status != wgpu::RequestAdapterStatus::Success)
{
printf("Failed to get an adapter: %s\n", message.data);
return;
}
acquired_adapter = std::move(adapter);
};
// Synchronously (wait until) acquire Adapter
wgpu::Future waitAdapterFunc { instance.RequestAdapter(&adapter_options, wgpu::CallbackMode::WaitAnyOnly, onRequestAdapter) };
wgpu::WaitStatus waitStatusAdapter = instance.WaitAny(waitAdapterFunc, UINT64_MAX);
IM_ASSERT(acquired_adapter != nullptr && waitStatusAdapter == wgpu::WaitStatus::Success && "Error on Adapter request");
return acquired_adapter.MoveToCHandle();
}
static WGPUDevice RequestDevice(wgpu::Instance& instance, wgpu::Adapter& adapter)
{
// Set device callback functions
wgpu::DeviceDescriptor device_desc;
device_desc.SetDeviceLostCallback(wgpu::CallbackMode::AllowSpontaneous,
[](const wgpu::Device&, wgpu::DeviceLostReason type, wgpu::StringView msg) { fprintf(stderr, "%s error: %s\n", ImGui_ImplWGPU_GetDeviceLostReasonName((WGPUDeviceLostReason)type), msg.data); }
);
device_desc.SetUncapturedErrorCallback(
[](const wgpu::Device&, wgpu::ErrorType type, wgpu::StringView msg) { fprintf(stderr, "%s error: %s\n", ImGui_ImplWGPU_GetErrorTypeName((WGPUErrorType)type), msg.data); }
);
wgpu::Device acquired_device;
auto onRequestDevice = [&](wgpu::RequestDeviceStatus status, wgpu::Device local_device, wgpu::StringView message)
{
if (status != wgpu::RequestDeviceStatus::Success)
{
printf("Failed to get an device: %s\n", message.data);
return;
}
acquired_device = std::move(local_device);
};
// Synchronously (wait until) get Device
wgpu::Future waitDeviceFunc { adapter.RequestDevice(&device_desc, wgpu::CallbackMode::WaitAnyOnly, onRequestDevice) };
wgpu::WaitStatus waitStatusDevice = instance.WaitAny(waitDeviceFunc, UINT64_MAX);
IM_ASSERT(acquired_device != nullptr && waitStatusDevice == wgpu::WaitStatus::Success && "Error on Device request");
return acquired_device.MoveToCHandle();
}
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#ifdef __EMSCRIPTEN__
// Adapter and device initialization via JS
EM_ASYNC_JS( void, getAdapterAndDeviceViaJS, (),
{
if (!navigator.gpu)
throw Error("WebGPU not supported.");
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
Module.preinitializedWebGPUDevice = device;
} );
#else // __EMSCRIPTEN__
static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void* userdata1, void* userdata2)
{
if (status == WGPURequestAdapterStatus_Success)
{
WGPUAdapter* extAdapter = (WGPUAdapter*)userdata1;
*extAdapter = adapter;
}
else
{
printf("Request_adapter status=%#.8x message=%.*s\n", status, (int)message.length, message.data);
}
}
static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void* userdata1, void* userdata2)
{
if (status == WGPURequestDeviceStatus_Success)
{
WGPUDevice* extDevice = (WGPUDevice*)userdata1;
*extDevice = device;
}
else
{
printf("Request_device status=%#.8x message=%.*s\n", status, (int)message.length, message.data);
}
}
static WGPUAdapter RequestAdapter(WGPUInstance& instance)
{
WGPURequestAdapterOptions adapter_options = {};
WGPUAdapter local_adapter;
WGPURequestAdapterCallbackInfo adapterCallbackInfo = {};
adapterCallbackInfo.callback = handle_request_adapter;
adapterCallbackInfo.userdata1 = &local_adapter;
wgpuInstanceRequestAdapter(instance, &adapter_options, adapterCallbackInfo);
IM_ASSERT(local_adapter && "Error on Adapter request");
return local_adapter;
}
static WGPUDevice RequestDevice(WGPUAdapter& adapter)
{
WGPUDevice local_device;
WGPURequestDeviceCallbackInfo deviceCallbackInfo = {};
deviceCallbackInfo.callback = handle_request_device;
deviceCallbackInfo.userdata1 = &local_device;
wgpuAdapterRequestDevice(adapter, nullptr, deviceCallbackInfo);
IM_ASSERT(local_device && "Error on Device request");
return local_device;
}
#endif // __EMSCRIPTEN__
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
static bool InitWGPU(SDL_Window* window)
{
WGPUTextureFormat preferred_fmt = WGPUTextureFormat_Undefined; // acquired from SurfaceCapabilities
// Google DAWN backend: Adapter and Device acquisition, Surface creation
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
wgpu::InstanceDescriptor instance_desc = {};
static constexpr wgpu::InstanceFeatureName timedWaitAny = wgpu::InstanceFeatureName::TimedWaitAny;
instance_desc.requiredFeatureCount = 1;
instance_desc.requiredFeatures = &timedWaitAny;
wgpu::Instance instance = wgpu::CreateInstance(&instance_desc);
wgpu::Adapter adapter = RequestAdapter(instance);
ImGui_ImplWGPU_DebugPrintAdapterInfo(adapter.Get());
wgpu_device = RequestDevice(instance, adapter);
// Create the surface.
#ifdef __EMSCRIPTEN__
wgpu::EmscriptenSurfaceSourceCanvasHTMLSelector canvas_desc = {};
canvas_desc.selector = "#canvas";
wgpu::SurfaceDescriptor surface_desc = {};
surface_desc.nextInChain = &canvas_desc;
wgpu::Surface surface = instance.CreateSurface(&surface_desc);
#else
wgpu::Surface surface = CreateWGPUSurface(instance.Get(), window);
#endif
if (!surface)
return false;
// Moving Dawn objects into WGPU handles
wgpu_instance = instance.MoveToCHandle();
wgpu_surface = surface.MoveToCHandle();
WGPUSurfaceCapabilities surface_capabilities = {};
wgpuSurfaceGetCapabilities(wgpu_surface, adapter.Get(), &surface_capabilities);
preferred_fmt = surface_capabilities.formats[0];
// WGPU backend: Adapter and Device acquisition, Surface creation
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
wgpu_instance = wgpuCreateInstance(nullptr);
#ifdef __EMSCRIPTEN__
getAdapterAndDeviceViaJS();
wgpu_device = emscripten_webgpu_get_device();
assert(wgpu_device != nullptr && "Error creating the Device");
WGPUSurfaceDescriptorFromCanvasHTMLSelector html_surface_desc = {};
html_surface_desc.chain.sType = WGPUSType_SurfaceDescriptorFromCanvasHTMLSelector;
html_surface_desc.selector = "#canvas";
WGPUSurfaceDescriptor surface_desc = {};
surface_desc.nextInChain = &html_surface_desc.chain;
// Create the surface.
wgpu_surface = wgpuInstanceCreateSurface(wgpu_instance, &surface_desc);
preferred_fmt = wgpuSurfaceGetPreferredFormat(wgpu_surface, {} /* adapter */);
#else // __EMSCRIPTEN__
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);
WGPUAdapter adapter = RequestAdapter(wgpu_instance);
ImGui_ImplWGPU_DebugPrintAdapterInfo(adapter);
wgpu_device = RequestDevice(adapter);
// Create the surface.
wgpu_surface = CreateWGPUSurface(wgpu_instance, window);
if (!wgpu_surface)
return false;
WGPUSurfaceCapabilities surface_capabilities = {};
wgpuSurfaceGetCapabilities(wgpu_surface, adapter, &surface_capabilities);
preferred_fmt = surface_capabilities.formats[0];
#endif // __EMSCRIPTEN__
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
wgpu_surface_configuration.presentMode = WGPUPresentMode_Fifo;
wgpu_surface_configuration.alphaMode = WGPUCompositeAlphaMode_Auto;
wgpu_surface_configuration.usage = WGPUTextureUsage_RenderAttachment;
wgpu_surface_configuration.width = wgpu_surface_width;
wgpu_surface_configuration.height = wgpu_surface_height;
wgpu_surface_configuration.device = wgpu_device;
wgpu_surface_configuration.format = preferred_fmt;
wgpuSurfaceConfigure(wgpu_surface, &wgpu_surface_configuration);
wgpu_queue = wgpuDeviceGetQueue(wgpu_device);
return true;
}
// SDL2 helper to create a WebGPU surface (exclusively!) for Native/Desktop applications: available only together with WebGPU/WGPU backend
// As of today (2025/10/31) there is no "official" support in SDL2 to create a surface for WebGPU backend.
// This stub uses "low level" SDL2 calls to acquire information from a specific Window Manager.
// Currently supported platforms: Windows / Linux (X11 and Wayland) / MacOS. Not necessary nor available with EMSCRIPTEN.
#ifndef __EMSCRIPTEN__
#include <SDL_syswm.h>
#undef Status // X11 headers are leaking this and also 'Success', 'Always', 'None', all used in DAWN api. Add #undef if necessary.
WGPUSurface CreateWGPUSurface(const WGPUInstance& instance, SDL_Window* window)
{
SDL_SysWMinfo sysWMInfo;
SDL_VERSION(&sysWMInfo.version);
SDL_GetWindowWMInfo(window, &sysWMInfo);
ImGui_ImplWGPU_CreateSurfaceInfo create_info = {};
create_info.Instance = instance;
#if defined(SDL_VIDEO_DRIVER_COCOA)
{
create_info.System = "cocoa";
create_info.RawWindow = (void*)sysWMInfo.info.cocoa.window;
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
}
#elif defined(SDL_VIDEO_DRIVER_WAYLAND) || defined(SDL_VIDEO_DRIVER_X11)
const char* sdl_driver = SDL_GetCurrentVideoDriver();
if (sdl_driver && strcmp(sdl_driver, "wayland") == 0)
{
create_info.System = "wayland";
create_info.RawDisplay = (void*)sysWMInfo.info.wl.display;
create_info.RawSurface = (void*)sysWMInfo.info.wl.surface;
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
}
else
{
create_info.System = "x11";
create_info.RawWindow = (void*)sysWMInfo.info.x11.window;
create_info.RawDisplay = (void*)sysWMInfo.info.x11.display;
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
}
#elif defined(SDL_VIDEO_DRIVER_WINDOWS)
{
create_info.System = "win32";
create_info.RawWindow = (void*)sysWMInfo.info.win.window;
create_info.RawInstance = (void*)sysWMInfo.info.win.hinstance;
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
}
#else
#error "Unsupported WebGPU native platform!"
#endif
return nullptr;
}
#endif // #ifndef __EMSCRIPTEN__

View File

@@ -0,0 +1,8 @@
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
@set OUT_DIR=Debug
@set OUT_EXE=example_sdl3_directx11
@set INCLUDES=/I..\.. /I..\..\backends /I%SDL3_DIR%\include /I "%WindowsSdkDir%Include\um" /I "%WindowsSdkDir%Include\shared" /I "%DXSDK_DIR%Include"
@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl3.cpp ..\..\backends\imgui_impl_dx11.cpp ..\..\imgui*.cpp
@set LIBS=/LIBPATH:%SDL3_DIR%\lib\x86 SDL3.lib /LIBPATH:"%DXSDK_DIR%/Lib/x86" d3d11.lib d3dcompiler.lib shell32.lib
mkdir %OUT_DIR%
cl /nologo /Zi /MD /utf-8 %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console

View File

@@ -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>{009DAC16-1A9C-47BE-9770-A30A046E8090}</ProjectGuid>
<RootNamespace>example_sdl3_directx11</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
<ProjectName>example_sdl3_directx11</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;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>%SDL3_DIR%\lib\x86;$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>SDL3.lib;d3d11.lib;d3dcompiler.lib;dxgi.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;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>%SDL3_DIR%\lib\x64;$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>SDL3.lib;d3d11.lib;d3dcompiler.lib;dxgi.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;%(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;$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>SDL3.lib;d3d11.lib;d3dcompiler.lib;dxgi.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;%(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;$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>SDL3.lib;d3d11.lib;d3dcompiler.lib;dxgi.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_dx11.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_dx11.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>

View File

@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="imgui">
<UniqueIdentifier>{0587d7a3-f2ce-4d56-b84f-a0005d3bfce6}</UniqueIdentifier>
</Filter>
<Filter Include="sources">
<UniqueIdentifier>{08e36723-ce4f-4cff-9662-c40801cf1acf}</UniqueIdentifier>
</Filter>
</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_dx11.h">
<Filter>sources</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\imgui.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="main.cpp">
<Filter>sources</Filter>
</ClCompile>
<ClCompile Include="..\..\imgui_demo.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="..\..\imgui_draw.cpp">
<Filter>imgui</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_dx11.cpp">
<Filter>sources</Filter>
</ClCompile>
</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>

View File

@@ -0,0 +1,260 @@
// Dear ImGui: standalone example application for SDL3 + DirectX 11
// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan/Metal graphics context creation, etc.)
// Learn about Dear ImGui:
// - FAQ https://dearimgui.com/faq
// - Getting Started https://dearimgui.com/getting-started
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
// - Introduction, links and more at the top of imgui.cpp
#include "imgui.h"
#include "imgui_impl_sdl3.h"
#include "imgui_impl_dx11.h"
#include <d3d11.h>
#include <stdio.h> // printf
#include <SDL3/SDL.h>
// Data
static ID3D11Device* g_pd3dDevice = nullptr;
static ID3D11DeviceContext* g_pd3dDeviceContext = nullptr;
static IDXGISwapChain* g_pSwapChain = nullptr;
static ID3D11RenderTargetView* g_mainRenderTargetView = nullptr;
// Forward declarations of helper functions
bool CreateDeviceD3D(HWND hWnd);
void CleanupDeviceD3D();
void CreateRenderTarget();
void CleanupRenderTarget();
// Main code
int main(int, char**)
{
// Setup SDL
// [If using SDL_MAIN_USE_CALLBACKS: all code below until the main loop starts would likely be your SDL_AppInit() function]
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD))
{
printf("Error: SDL_Init(): %s\n", SDL_GetError());
return 1;
}
// Setup window
float main_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
SDL_WindowFlags window_flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN | SDL_WINDOW_HIGH_PIXEL_DENSITY;
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+DirectX11 example", (int)(1280 * main_scale), (int)(800 * main_scale), window_flags);
if (window == nullptr)
{
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return 1;
}
SDL_PropertiesID props = SDL_GetWindowProperties(window);
HWND hwnd = (HWND)SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WIN32_HWND_POINTER, nullptr);
// Initialize Direct3D
if (!CreateDeviceD3D(hwnd))
{
CleanupDeviceD3D();
return 1;
}
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
SDL_ShowWindow(window);
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsLight();
// Setup scaling
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
// Setup Platform/Renderer backends
ImGui_ImplSDL3_InitForD3D(window);
ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext);
// Load Fonts
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
// - Read 'docs/FONTS.md' for more instructions and details.
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
//style.FontSizeBase = 20.0f;
//io.Fonts->AddFontDefaultVector();
//io.Fonts->AddFontDefaultBitmap();
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf");
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf");
//IM_ASSERT(font != nullptr);
// Our state
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
// Main loop
bool done = false;
while (!done)
{
// Poll and handle events (inputs, window resize, etc.)
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
// [If using SDL_MAIN_USE_CALLBACKS: call ImGui_ImplSDL3_ProcessEvent() from your SDL_AppEvent() function]
SDL_Event event;
while (SDL_PollEvent(&event))
{
ImGui_ImplSDL3_ProcessEvent(&event);
if (event.type == SDL_EVENT_QUIT)
done = true;
if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED && event.window.windowID == SDL_GetWindowID(window))
done = true;
if (event.type == SDL_EVENT_WINDOW_RESIZED && event.window.windowID == SDL_GetWindowID(window))
{
// Release all outstanding references to the swap chain's buffers before resizing.
CleanupRenderTarget();
g_pSwapChain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);
CreateRenderTarget();
}
}
// [If using SDL_MAIN_USE_CALLBACKS: all code below would likely be your SDL_AppIterate() function]
if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED)
{
SDL_Delay(10);
continue;
}
// Start the Dear ImGui frame
ImGui_ImplDX11_NewFrame();
ImGui_ImplSDL3_NewFrame();
ImGui::NewFrame();
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
if (show_demo_window)
ImGui::ShowDemoWindow(&show_demo_window);
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
{
static float f = 0.0f;
static int counter = 0;
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
ImGui::Checkbox("Another Window", &show_another_window);
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
ImGui::End();
}
// 3. Show another simple window.
if (show_another_window)
{
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
ImGui::Text("Hello from another window!");
if (ImGui::Button("Close Me"))
show_another_window = false;
ImGui::End();
}
// Rendering
ImGui::Render();
const float clear_color_with_alpha[4] = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w };
g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, nullptr);
g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, clear_color_with_alpha);
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
g_pSwapChain->Present(1, 0); // Present with vsync
//g_pSwapChain->Present(0, 0); // Present without vsync
}
// Cleanup
// [If using SDL_MAIN_USE_CALLBACKS: all code below would likely be your SDL_AppQuit() function]
ImGui_ImplDX11_Shutdown();
ImGui_ImplSDL3_Shutdown();
ImGui::DestroyContext();
CleanupDeviceD3D();
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
// Helper functions to use DirectX11
bool CreateDeviceD3D(HWND hWnd)
{
// Setup swap chain
// This is a basic setup. Optimally could use e.g. DXGI_SWAP_EFFECT_FLIP_DISCARD and handle fullscreen mode differently. See #8979 for suggestions.
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 2;
sd.BufferDesc.Width = 0;
sd.BufferDesc.Height = 0;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = hWnd;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Windowed = TRUE;
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
UINT createDeviceFlags = 0;
//createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
D3D_FEATURE_LEVEL featureLevel;
const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, };
HRESULT res = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext);
if (res == DXGI_ERROR_UNSUPPORTED) // Try high-performance WARP software driver if hardware is not available.
res = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_WARP, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext);
if (res != S_OK)
return false;
CreateRenderTarget();
return true;
}
void CleanupDeviceD3D()
{
CleanupRenderTarget();
if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = nullptr; }
if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = nullptr; }
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = nullptr; }
}
void CreateRenderTarget()
{
ID3D11Texture2D* pBackBuffer;
g_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, &g_mainRenderTargetView);
pBackBuffer->Release();
}
void CleanupRenderTarget()
{
if (g_mainRenderTargetView) { g_mainRenderTargetView->Release(); g_mainRenderTargetView = nullptr; }
}

View File

@@ -0,0 +1,48 @@
#
# You will need SDL3 (http://www.libsdl.org):
# brew install sdl3
#
#CXX = g++
#CXX = clang++
EXE = example_sdl3_metal
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_sdl3.cpp $(IMGUI_DIR)/backends/imgui_impl_metal.mm
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
LIBS = -framework Metal -framework MetalKit -framework Cocoa -framework IOKit -framework CoreVideo -framework QuartzCore
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
CXXFLAGS += -std=c++11 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
CXXFLAGS += -Wall -Wformat
CFLAGS = $(CXXFLAGS)
%.o:%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
%.o:$(IMGUI_DIR)/%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
%.o:$(IMGUI_DIR)/backends/%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
%.o:%.mm
$(CXX) $(CXXFLAGS) -ObjC++ -fobjc-weak -fobjc-arc -c -o $@ $<
%.o:$(IMGUI_DIR)/backends/%.mm
$(CXX) $(CXXFLAGS) -ObjC++ -fobjc-weak -fobjc-arc -c -o $@ $<
all: $(EXE)
@echo Build complete
$(EXE): $(OBJS)
$(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS)
clean:
rm -f $(EXE) $(OBJS)

View File

@@ -0,0 +1,210 @@
// Dear ImGui: standalone example application for SDL3 + Metal
// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan/Metal graphics context creation, etc.)
// Learn about Dear ImGui:
// - FAQ https://dearimgui.com/faq
// - Getting Started https://dearimgui.com/getting-started
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
// - Introduction, links and more at the top of imgui.cpp
#include "imgui.h"
#include "imgui_impl_sdl3.h"
#include "imgui_impl_metal.h"
#include <stdio.h> // printf, fprintf
#include <SDL3/SDL.h>
#import <Metal/Metal.h>
#import <QuartzCore/QuartzCore.h>
// Main code
int main(int, char**)
{
// Setup SDL
// [If using SDL_MAIN_USE_CALLBACKS: all code below until the main loop starts would likely be your SDL_AppInit() function]
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD))
{
printf("Error: SDL_Init(): %s\n", SDL_GetError());
return 1;
}
// Create SDL window graphics context
float main_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
SDL_WindowFlags window_flags = SDL_WINDOW_METAL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN | SDL_WINDOW_HIGH_PIXEL_DENSITY;
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+Metal 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);
// Create Metal device _before_ creating the view/layer
id<MTLDevice> metalDevice = MTLCreateSystemDefaultDevice();
if (!metalDevice)
{
printf("Error: failed to create Metal device.\n");
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
SDL_MetalView view = SDL_Metal_CreateView(window);
CAMetalLayer* layer = (__bridge CAMetalLayer*)SDL_Metal_GetLayer(view);
layer.device = metalDevice;
layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
id<MTLCommandQueue> commandQueue = [layer.device newCommandQueue];
MTLRenderPassDescriptor* renderPassDescriptor = [MTLRenderPassDescriptor new];
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsLight();
// Setup scaling
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
// Setup Platform/Renderer backends
ImGui_ImplMetal_Init(layer.device);
ImGui_ImplSDL3_InitForMetal(window);
// Load Fonts
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
// - Read 'docs/FONTS.md' for more instructions and details.
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
//style.FontSizeBase = 20.0f;
//io.Fonts->AddFontDefaultVector();
//io.Fonts->AddFontDefaultBitmap();
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf");
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf");
//IM_ASSERT(font != nullptr);
// Our state
bool show_demo_window = true;
bool show_another_window = false;
float clear_color[4] = { 0.45f, 0.55f, 0.60f, 1.00f };
// Main loop
bool done = false;
while (!done)
{
@autoreleasepool
{
// Poll and handle events (inputs, window resize, etc.)
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
// [If using SDL_MAIN_USE_CALLBACKS: call ImGui_ImplSDL3_ProcessEvent() from your SDL_AppEvent() function]
SDL_Event event;
while (SDL_PollEvent(&event))
{
ImGui_ImplSDL3_ProcessEvent(&event);
if (event.type == SDL_EVENT_QUIT)
done = true;
if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED && event.window.windowID == SDL_GetWindowID(window))
done = true;
}
// [If using SDL_MAIN_USE_CALLBACKS: all code below would likely be your SDL_AppIterate() function]
if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED)
{
SDL_Delay(10);
continue;
}
int width, height;
SDL_GetWindowSizeInPixels(window, &width, &height);
layer.drawableSize = CGSizeMake(width, height);
id<CAMetalDrawable> drawable = [layer nextDrawable];
id<MTLCommandBuffer> commandBuffer = [commandQueue commandBuffer];
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clear_color[0] * clear_color[3], clear_color[1] * clear_color[3], clear_color[2] * clear_color[3], clear_color[3]);
renderPassDescriptor.colorAttachments[0].texture = drawable.texture;
renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear;
renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
id <MTLRenderCommandEncoder> renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
[renderEncoder pushDebugGroup:@"ImGui demo"];
// Start the Dear ImGui frame
ImGui_ImplMetal_NewFrame(renderPassDescriptor);
ImGui_ImplSDL3_NewFrame();
ImGui::NewFrame();
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
if (show_demo_window)
ImGui::ShowDemoWindow(&show_demo_window);
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
{
static float f = 0.0f;
static int counter = 0;
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
ImGui::Checkbox("Another Window", &show_another_window);
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
ImGui::End();
}
// 3. Show another simple window.
if (show_another_window)
{
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
ImGui::Text("Hello from another window!");
if (ImGui::Button("Close Me"))
show_another_window = false;
ImGui::End();
}
// Rendering
ImGui::Render();
ImDrawData* draw_data = ImGui::GetDrawData();
ImGui_ImplMetal_RenderDrawData(draw_data, commandBuffer, renderEncoder);
[renderEncoder popDebugGroup];
[renderEncoder endEncoding];
[commandBuffer presentDrawable:drawable];
[commandBuffer commit];
}
}
// Cleanup
// [If using SDL_MAIN_USE_CALLBACKS: all code below would likely be your SDL_AppQuit() function]
ImGui_ImplMetal_Shutdown();
ImGui_ImplSDL3_Shutdown();
ImGui::DestroyContext();
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}

View File

@@ -36,7 +36,7 @@ EMS =
##---------------------------------------------------------------------
# ("EMS" options gets added to both CPPFLAGS and LDFLAGS, whereas some options are for linker only)
EMS += -s USE_SDL=2
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

View File

@@ -30,7 +30,7 @@ int main(int, char**)
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD))
{
printf("Error: SDL_Init(): %s\n", SDL_GetError());
return -1;
return 1;
}
// Decide GL+GLSL versions
@@ -70,17 +70,17 @@ int main(int, char**)
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
float main_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
SDL_WindowFlags window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN | SDL_WINDOW_HIGH_PIXEL_DENSITY;
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+OpenGL3 example", (int)(1280 * main_scale), (int)(720 * main_scale), window_flags);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+OpenGL3 example", (int)(1280 * main_scale), (int)(800 * main_scale), window_flags);
if (window == nullptr)
{
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return -1;
return 1;
}
SDL_GLContext gl_context = SDL_GL_CreateContext(window);
if (gl_context == nullptr)
{
printf("Error: SDL_GL_CreateContext(): %s\n", SDL_GetError());
return -1;
return 1;
}
SDL_GL_MakeCurrent(window, gl_context);
@@ -102,22 +102,24 @@ int main(int, char**)
// Setup scaling
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
style.FontScaleDpi = main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose)
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
// Setup Platform/Renderer backends
ImGui_ImplSDL3_InitForOpenGL(window, gl_context);
ImGui_ImplOpenGL3_Init(glsl_version);
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
// - Read 'docs/FONTS.md' for more instructions and details.
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
// - Our Emscripten build process allows embedding fonts to be accessible at runtime from the "fonts/" folder. See Makefile.emscripten for details.
//style.FontSizeBase = 20.0f;
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontDefaultVector();
//io.Fonts->AddFontDefaultBitmap();
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");

View File

@@ -1,4 +1,5 @@
// Dear ImGui: standalone example application for SDL3 + SDL_GPU
// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan/Metal graphics context creation, etc.)
// Learn about Dear ImGui:
// - FAQ https://dearimgui.com/faq
@@ -30,36 +31,36 @@ int main(int, char**)
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD))
{
printf("Error: SDL_Init(): %s\n", SDL_GetError());
return -1;
return 1;
}
// Create SDL window graphics context
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+SDL_GPU example", (int)(1280 * main_scale), (int)(720 * main_scale), window_flags);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+SDL_GPU example", (int)(1280 * main_scale), (int)(800 * main_scale), window_flags);
if (window == nullptr)
{
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return -1;
return 1;
}
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
SDL_ShowWindow(window);
// Create GPU Device
SDL_GPUDevice* gpu_device = SDL_CreateGPUDevice(SDL_GPU_SHADERFORMAT_SPIRV | SDL_GPU_SHADERFORMAT_DXIL | SDL_GPU_SHADERFORMAT_METALLIB,true,nullptr);
SDL_GPUDevice* gpu_device = SDL_CreateGPUDevice(SDL_GPU_SHADERFORMAT_SPIRV | SDL_GPU_SHADERFORMAT_DXIL | SDL_GPU_SHADERFORMAT_MSL | SDL_GPU_SHADERFORMAT_METALLIB, true, nullptr);
if (gpu_device == nullptr)
{
printf("Error: SDL_CreateGPUDevice(): %s\n", SDL_GetError());
return -1;
return 1;
}
// Claim window for GPU Device
if (!SDL_ClaimWindowForGPUDevice(gpu_device, window))
{
printf("Error: SDL_ClaimWindowForGPUDevice(): %s\n", SDL_GetError());
return -1;
return 1;
}
SDL_SetGPUSwapchainParameters(gpu_device, window, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, SDL_GPU_PRESENTMODE_MAILBOX);
SDL_SetGPUSwapchainParameters(gpu_device, window, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, SDL_GPU_PRESENTMODE_VSYNC);
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
@@ -75,25 +76,29 @@ int main(int, char**)
// Setup scaling
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
style.FontScaleDpi = main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose)
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
// Setup Platform/Renderer backends
ImGui_ImplSDL3_InitForSDLGPU(window);
ImGui_ImplSDLGPU3_InitInfo init_info = {};
init_info.Device = gpu_device;
init_info.ColorTargetFormat = SDL_GetGPUSwapchainTextureFormat(gpu_device, window);
init_info.MSAASamples = SDL_GPU_SAMPLECOUNT_1;
init_info.MSAASamples = SDL_GPU_SAMPLECOUNT_1; // Only used in multi-viewports mode.
init_info.SwapchainComposition = SDL_GPU_SWAPCHAINCOMPOSITION_SDR; // Only used in multi-viewports mode.
init_info.PresentMode = SDL_GPU_PRESENTMODE_VSYNC;
ImGui_ImplSDLGPU3_Init(&init_info);
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
// - Read 'docs/FONTS.md' for more instructions and details.
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
//style.FontSizeBase = 20.0f;
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontDefaultVector();
//io.Fonts->AddFontDefaultBitmap();
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
@@ -154,7 +159,7 @@ int main(int, char**)
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::ColorEdit4("clear color", (float*)&clear_color); // Edit 3 floats representing a color
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
counter++;
@@ -183,7 +188,7 @@ int main(int, char**)
SDL_GPUCommandBuffer* command_buffer = SDL_AcquireGPUCommandBuffer(gpu_device); // Acquire a GPU command buffer
SDL_GPUTexture* swapchain_texture;
SDL_AcquireGPUSwapchainTexture(command_buffer, window, &swapchain_texture, nullptr, nullptr); // Acquire a swapchain texture
SDL_WaitAndAcquireGPUSwapchainTexture(command_buffer, window, &swapchain_texture, nullptr, nullptr); // Acquire a swapchain texture
if (swapchain_texture != nullptr && !is_minimized)
{

View File

@@ -28,24 +28,24 @@ int main(int, char**)
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD))
{
printf("Error: SDL_Init(): %s\n", SDL_GetError());
return -1;
return 1;
}
// Create window with SDL_Renderer graphics context
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+SDL_Renderer example", (int)(1280 * main_scale), (int)(720 * main_scale), window_flags);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+SDL_Renderer example", (int)(1280 * main_scale), (int)(800 * main_scale), window_flags);
if (window == nullptr)
{
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return -1;
return 1;
}
SDL_Renderer* renderer = SDL_CreateRenderer(window, nullptr);
SDL_SetRenderVSync(renderer, 1);
if (renderer == nullptr)
{
SDL_Log("Error: SDL_CreateRenderer(): %s\n", SDL_GetError());
return -1;
return 1;
}
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
SDL_ShowWindow(window);
@@ -64,22 +64,23 @@ int main(int, char**)
// Setup scaling
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
style.FontScaleDpi = main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose)
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
// Setup Platform/Renderer backends
ImGui_ImplSDL3_InitForSDLRenderer(window, renderer);
ImGui_ImplSDLRenderer3_Init(renderer);
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
// - Read 'docs/FONTS.md' for more instructions and details.
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
// - Our Emscripten build process allows embedding fonts to be accessible at runtime from the "fonts/" folder. See Makefile.emscripten for details.
//style.FontSizeBase = 20.0f;
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontDefaultVector();
//io.Fonts->AddFontDefaultBitmap();
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");

View File

@@ -194,7 +194,7 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
pool_info.maxSets = 0;
for (VkDescriptorPoolSize& pool_size : pool_sizes)
pool_info.maxSets += pool_size.descriptorCount;
pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes);
pool_info.poolSizeCount = (uint32_t)IM_COUNTOF(pool_sizes);
pool_info.pPoolSizes = pool_sizes;
err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool);
check_vk_result(err);
@@ -205,11 +205,9 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
// Your real engine/app may not use them.
static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface, int width, int height)
{
wd->Surface = surface;
// Check for WSI support
VkBool32 res;
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, wd->Surface, &res);
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, surface, &res);
if (res != VK_TRUE)
{
fprintf(stderr, "Error no WSI support on physical device 0\n");
@@ -219,7 +217,8 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface
// Select Surface Format
const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
wd->Surface = surface;
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_COUNTOF(requestSurfaceImageFormat), requestSurfaceColorSpace);
// Select Present Mode
#ifdef APP_USE_UNLIMITED_FRAME_RATE
@@ -227,12 +226,12 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface
#else
VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_FIFO_KHR };
#endif
wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_modes[0], IM_ARRAYSIZE(present_modes));
wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_modes[0], IM_COUNTOF(present_modes));
//printf("[vulkan] Selected PresentMode = %d\n", wd->PresentMode);
// Create SwapChain, RenderPass, Framebuffer, etc.
IM_ASSERT(g_MinImageCount >= 2);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, 0);
}
static void CleanupVulkan()
@@ -249,9 +248,10 @@ static void CleanupVulkan()
vkDestroyInstance(g_Instance, g_Allocator);
}
static void CleanupVulkanWindow()
static void CleanupVulkanWindow(ImGui_ImplVulkanH_Window* wd)
{
ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, &g_MainWindowData, g_Allocator);
ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, wd, g_Allocator);
vkDestroySurfaceKHR(g_Instance, wd->Surface, g_Allocator);
}
static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
@@ -349,17 +349,17 @@ int main(int, char**)
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD))
{
printf("Error: SDL_Init(): %s\n", SDL_GetError());
return -1;
return 1;
}
// Create window with Vulkan graphics context
float main_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
SDL_WindowFlags window_flags = SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN | SDL_WINDOW_HIGH_PIXEL_DENSITY;
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+Vulkan example", (int)(1280 * main_scale), (int)(720 * main_scale), window_flags);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+Vulkan example", (int)(1280 * main_scale), (int)(800 * main_scale), window_flags);
if (window == nullptr)
{
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return -1;
return 1;
}
ImVector<const char*> extensions;
@@ -402,7 +402,7 @@ int main(int, char**)
// Setup scaling
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
style.FontScaleDpi = main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose)
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
// Setup Platform/Renderer backends
ImGui_ImplSDL3_InitForVulkan(window);
@@ -415,24 +415,26 @@ int main(int, char**)
init_info.Queue = g_Queue;
init_info.PipelineCache = g_PipelineCache;
init_info.DescriptorPool = g_DescriptorPool;
init_info.RenderPass = wd->RenderPass;
init_info.Subpass = 0;
init_info.MinImageCount = g_MinImageCount;
init_info.ImageCount = wd->ImageCount;
init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
init_info.Allocator = g_Allocator;
init_info.PipelineInfoMain.RenderPass = wd->RenderPass;
init_info.PipelineInfoMain.Subpass = 0;
init_info.PipelineInfoMain.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
init_info.CheckVkResultFn = check_vk_result;
ImGui_ImplVulkan_Init(&init_info);
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
// - Read 'docs/FONTS.md' for more instructions and details.
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
//style.FontSizeBase = 20.0f;
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontDefaultVector();
//io.Fonts->AddFontDefaultBitmap();
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
@@ -478,7 +480,7 @@ int main(int, char**)
if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height))
{
ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, 0);
g_MainWindowData.FrameIndex = 0;
g_SwapChainRebuild = false;
}
@@ -548,7 +550,7 @@ int main(int, char**)
ImGui_ImplSDL3_Shutdown();
ImGui::DestroyContext();
CleanupVulkanWindow();
CleanupVulkanWindow(&g_MainWindowData);
CleanupVulkan();
SDL_DestroyWindow(window);

View File

@@ -0,0 +1,207 @@
# Building for desktop (WebGPU-native) 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]
# Building for desktop (WGPU-Native) 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]
# Building for Emscripten:
# 1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html
# 2. Install Ninja build system
# 3. emcmake cmake -G Ninja -B build
# (optional) -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path/to/emdawnwebgpu_package/emdawnwebgpu.port.py", see ReadMe.md
# 4. cmake --build build
# 5. emrun build/index.html
cmake_minimum_required(VERSION 3.22) # Dawn requires CMake >= 3.22
project(imgui_example_sdl3_wgpu C CXX)
set(IMGUI_EXECUTABLE example_sdl3_wgpu)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
endif()
set(CMAKE_CXX_STANDARD 17) # Dawn requires C++17
# Dear ImGui
set(IMGUI_DIR ../../)
# ImGui example commons source files
set(IMGUI_EXAMPLE_SOURCE_FILES
main.cpp
# backend files
${IMGUI_DIR}/backends/imgui_impl_sdl3.cpp
${IMGUI_DIR}/backends/imgui_impl_wgpu.cpp
# Dear ImGui files
${IMGUI_DIR}/imgui.cpp
${IMGUI_DIR}/imgui_draw.cpp
${IMGUI_DIR}/imgui_demo.cpp
${IMGUI_DIR}/imgui_tables.cpp
${IMGUI_DIR}/imgui_widgets.cpp
)
if(EMSCRIPTEN)
if(EMSCRIPTEN_VERSION VERSION_LESS "4.0.15")
message(FATAL_ERROR "Using Emscripten with SDL3 needs Emscripten version >= 4.0.15")
endif()
if(NOT IMGUI_EMSCRIPTEN_WEBGPU_FLAG) # if IMGUI_EMSCRIPTEN_WEBGPU_FLAG not used, set by current EMSCRIPTEN version
if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "4.0.10")
set(IMGUI_EMSCRIPTEN_WEBGPU_FLAG "--use-port=emdawnwebgpu" CACHE STRING "Choose between --use-port=emdawnwebgpu (Dawn implementation of EMSCRIPTEN) and -sUSE_WEBGPU=1 (WGPU implementation of EMSCRIPTEN, deprecated in 4.0.10): default to --use-port=emdawnwebgpu for EMSCRIPTEN >= 4.0.10")
else()
set(IMGUI_EMSCRIPTEN_WEBGPU_FLAG "-sUSE_WEBGPU=1" CACHE STRING "Use -sUSE_WEBGPU=1 for EMSCRIPTEN WGPU implementation")
endif()
else() # if IMGUI_EMSCRIPTEN_WEBGPU_FLAG used, check correct version
if(EMSCRIPTEN_VERSION VERSION_LESS "4.0.10" AND "${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}" MATCHES "emdawnwebgpu")
# it's necessary EMSCRIPTEN >= v4.0.10 (although "--use-port=path/to/emdawnwebgpu.port.py" is supported/tested from v4.0.8)
message(FATAL_ERROR "emdawnwebgpu needs EMSCRIPTEN version >= 4.0.10")
endif()
endif()
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")
endif()
if(APPLE) # Add SDL3 module to get Surface, with libs and file property for MacOS build
set_source_files_properties(${IMGUI_DIR}/backends/imgui_impl_wgpu.cpp PROPERTIES COMPILE_FLAGS "-x objective-c++")
set(OS_LIBRARIES "-framework CoreFoundation -framework QuartzCore -framework Metal -framework MetalKit -framework Cocoa")
endif()
find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3)
if(IMGUI_DAWN_DIR) # DAWN-Native build options
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
if(Dawn_FOUND)
message("Dawn Installation has been found!")
set(LIBRARIES dawn::webgpu_dawn ${OS_LIBRARIES})
else()
set(IMGUI_DAWN_DIR CACHE PATH "Path to Dawn repository")
option(DAWN_USE_GLFW OFF) # disable builtin GLFW in DAWN when we use SDL2 / SDL3
option(DAWN_FETCH_DEPENDENCIES "Use fetch_dawn_dependencies.py as an alternative to using depot_tools" ON)
set(DAWN_BUILD_MONOLITHIC_LIBRARY "STATIC" CACHE STRING "Build monolithic library: SHARED, STATIC, or OFF.")
# Dawn builds many things by default - disable things we don't need
option(DAWN_BUILD_SAMPLES "Enables building Dawn's samples" OFF)
option(TINT_BUILD_CMD_TOOLS "Build the Tint command line tools" OFF)
option(TINT_BUILD_DOCS "Build documentation" OFF)
option(TINT_BUILD_TESTS "Build tests" OFF)
if(NOT APPLE)
option(TINT_BUILD_MSL_WRITER "Build the MSL output writer" OFF)
endif()
if(WIN32)
option(DAWN_FORCE_SYSTEM_COMPONENT_LOAD "Allow system component fallback" ON)
option(TINT_BUILD_SPV_READER "Build the SPIR-V input reader" OFF)
option(TINT_BUILD_WGSL_READER "Build the WGSL input reader" ON)
option(TINT_BUILD_GLSL_WRITER "Build the GLSL output writer" OFF)
option(TINT_BUILD_GLSL_VALIDATOR "Build the GLSL output validator" OFF)
option(TINT_BUILD_SPV_WRITER "Build the SPIR-V output writer" ON)
option(TINT_BUILD_WGSL_WRITER "Build the WGSL output writer" ON)
endif()
# check if WAYLAND is the current Session Type and enable DAWN_USE_WAYLAND Wayland option @compile time
# You can override this using: cmake -DDAWN_USE_WAYLAND=X (X = ON | OFF)
if(LINUX)
if($ENV{XDG_SESSION_TYPE} MATCHES wayland)
option(DAWN_USE_WAYLAND "Enable support for Wayland surface" ON)
endif()
endif()
add_subdirectory("${IMGUI_DAWN_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/dawn" EXCLUDE_FROM_ALL)
set(LIBRARIES webgpu_dawn ${OS_LIBRARIES})
endif()
else() # WGPU-Native build options
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)
set(OS_LIBRARIES d3dcompiler ws2_32 userenv bcrypt ntdll opengl32 Propsys RuntimeObject)
elseif(UNIX AND NOT APPLE)
set(OS_LIBRARIES "-lm -ldl")
endif()
set(LIBRARIES ${WGPU_LIBRARY} ${OS_LIBRARIES})
endif()
endif()
add_executable(${IMGUI_EXECUTABLE} ${IMGUI_EXAMPLE_SOURCE_FILES})
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC
${IMGUI_DIR}
${IMGUI_DIR}/backends
${SDL3_INCLUDE_DIRS}
)
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_EXAMPLE_SDL3_WGPU")
# Enable warning level compiler option only for IMGUI_EXAMPLE_SOURCE_FILES
if (MSVC)
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC /W4) # warning level 4
else()
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC -Wall) # -Wextra -Wpedantic
endif()
# IMGUI_IMPL_WEBGPU_BACKEND_DAWN/WGPU internal define is set according to:
# EMSCRIPTEN: by used FLAG
# --use-port=emdawnwebgpu --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN enabled (+EMSCRIPTEN)
# -sUSE_WEBGPU=1 --> IMGUI_IMPL_WEBGPU_BACKEND_WGPU enabled (+EMSCRIPTEN)
# NATIVE: by used SDK installation directory
# if IMGUI_DAWN_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN enabled
# if IMGUI_WGPU_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_WGPU enabled
if(NOT EMSCRIPTEN) # WegGPU-Native settings
if(IMGUI_DAWN_DIR)
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_DAWN")
if(NOT Dawn_FOUND)
target_link_libraries(${IMGUI_EXECUTABLE} INTERFACE webgpu_cpp)
endif()
else()
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGPU_DIR}/include)
endif()
target_link_libraries(${IMGUI_EXECUTABLE} PUBLIC ${LIBRARIES} SDL3::SDL3)
else() # Emscripten settings
set(CMAKE_EXECUTABLE_SUFFIX ".html")
if("${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}" MATCHES "emdawnwebgpu")
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}")
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_DAWN")
else()
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
endif()
message(STATUS "Using ${IMGUI_EMSCRIPTEN_WEBGPU_FLAG} WebGPU implementation")
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "-sUSE_SDL=3")
target_link_options(${IMGUI_EXECUTABLE} PRIVATE
"${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}"
"-sUSE_SDL=3"
"-sWASM=1"
"-sASYNCIFY=1"
"-sALLOW_MEMORY_GROWTH=1"
"-sNO_EXIT_RUNTIME=0"
"-sASSERTIONS=1"
"-sDISABLE_EXCEPTION_CATCHING=1"
# "-sNO_FILESYSTEM=1"
"--shell-file=${CMAKE_CURRENT_LIST_DIR}/../libs/emscripten/shell_minimal.html"
)
set_target_properties(${IMGUI_EXECUTABLE} PROPERTIES OUTPUT_NAME "index")
endif()

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