From 8db94cd99283b0af971f95d372ac6be273fe79c6 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 3 Sep 2020 16:11:01 +0200 Subject: [PATCH 01/11] Internals: Scroll related, comments & shallow tweaks. --- imgui.cpp | 58 ++++++++++++++++++++++++++---------------------- imgui_internal.h | 8 +++---- 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e0a15289..e133fd1a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7368,16 +7368,16 @@ static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window) ImVec2 scroll = window->Scroll; if (window->ScrollTarget.x < FLT_MAX) { - float cr_x = window->ScrollTargetCenterRatio.x; - float target_x = window->ScrollTarget.x; - scroll.x = target_x - cr_x * (window->SizeFull.x - window->ScrollbarSizes.x); + float center_x_ratio = window->ScrollTargetCenterRatio.x; + float scroll_target_x = window->ScrollTarget.x; + scroll.x = scroll_target_x - center_x_ratio * (window->SizeFull.x - window->ScrollbarSizes.x); } if (window->ScrollTarget.y < FLT_MAX) { float decoration_up_height = window->TitleBarHeight() + window->MenuBarHeight(); - float cr_y = window->ScrollTargetCenterRatio.y; - float target_y = window->ScrollTarget.y; - scroll.y = target_y - cr_y * (window->SizeFull.y - window->ScrollbarSizes.y - decoration_up_height); + float center_y_ratio = window->ScrollTargetCenterRatio.y; + float scroll_target_y = window->ScrollTarget.y; + scroll.y = scroll_target_y - center_y_ratio * (window->SizeFull.y - window->ScrollbarSizes.y - decoration_up_height); } scroll.x = IM_FLOOR(ImMax(scroll.x, 0.0f)); scroll.y = IM_FLOOR(ImMax(scroll.y, 0.0f)); @@ -7443,38 +7443,44 @@ float ImGui::GetScrollMaxY() return window->ScrollMax.y; } -void ImGui::SetScrollX(float scroll_x) +void ImGui::SetScrollX(ImGuiWindow* window, float scroll_x) { - ImGuiWindow* window = GetCurrentWindow(); window->ScrollTarget.x = scroll_x; window->ScrollTargetCenterRatio.x = 0.0f; } -void ImGui::SetScrollY(float scroll_y) +void ImGui::SetScrollY(ImGuiWindow* window, float scroll_y) { - ImGuiWindow* window = GetCurrentWindow(); window->ScrollTarget.y = scroll_y; window->ScrollTargetCenterRatio.y = 0.0f; } -void ImGui::SetScrollX(ImGuiWindow* window, float new_scroll_x) +void ImGui::SetScrollX(float scroll_x) { - window->ScrollTarget.x = new_scroll_x; - window->ScrollTargetCenterRatio.x = 0.0f; + ImGuiContext& g = *GImGui; + SetScrollX(g.CurrentWindow, scroll_x); } -void ImGui::SetScrollY(ImGuiWindow* window, float new_scroll_y) +void ImGui::SetScrollY(float scroll_y) { - window->ScrollTarget.y = new_scroll_y; - window->ScrollTargetCenterRatio.y = 0.0f; + ImGuiContext& g = *GImGui; + SetScrollY(g.CurrentWindow, scroll_y); } -// Note that a local position will vary depending on initial scroll value -// We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size +// Note that a local position will vary depending on initial scroll value, +// This is a little bit confusing so bear with us: +// - local_pos = (absolution_pos - window->Pos) +// - So local_x/local_y are 0.0f for a position at the upper-left corner of a window, +// and generally local_x/local_y are >(padding+decoration) && <(size-padding-decoration) when in the visible area. +// - They mostly exists because of legacy API. +// Following the rules above, when trying to work with scrolling code, consider that: +// - SetScrollFromPosY(0.0f) == SetScrollY(0.0f + scroll.y) == has no effect! +// - SetScrollFromPosY(-scroll.y) == SetScrollY(-scroll.y + scroll.y) == SetScrollY(0.0f) == reset scroll. Of course writing SetScrollY(0.0f) directly then makes more sense +// We store a target position so centering and clamping can occur on the next frame when we are guaranteed to have a known window size void ImGui::SetScrollFromPosX(ImGuiWindow* window, float local_x, float center_x_ratio) { IM_ASSERT(center_x_ratio >= 0.0f && center_x_ratio <= 1.0f); - window->ScrollTarget.x = IM_FLOOR(local_x + window->Scroll.x); + window->ScrollTarget.x = IM_FLOOR(local_x + window->Scroll.x); // Convert local position to scroll offset window->ScrollTargetCenterRatio.x = center_x_ratio; } @@ -7482,7 +7488,7 @@ void ImGui::SetScrollFromPosY(ImGuiWindow* window, float local_y, float center_y { IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f); local_y -= window->TitleBarHeight() + window->MenuBarHeight(); // FIXME: Would be nice to have a more standardized access to our scrollable/client rect - window->ScrollTarget.y = IM_FLOOR(local_y + window->Scroll.y); + window->ScrollTarget.y = IM_FLOOR(local_y + window->Scroll.y); // Convert local position to scroll offset window->ScrollTargetCenterRatio.y = center_y_ratio; } @@ -7517,15 +7523,15 @@ void ImGui::SetScrollHereX(float center_x_ratio) ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; float spacing_x = g.Style.ItemSpacing.x; - float target_x = ImLerp(window->DC.LastItemRect.Min.x - spacing_x, window->DC.LastItemRect.Max.x + spacing_x, center_x_ratio); + float target_pos_x = ImLerp(window->DC.LastItemRect.Min.x - spacing_x, window->DC.LastItemRect.Max.x + spacing_x, center_x_ratio); // Tweak: snap on edges when aiming at an item very close to the edge const float snap_x_threshold = ImMax(0.0f, window->WindowPadding.x - spacing_x); const float snap_x_min = window->DC.CursorStartPos.x - window->WindowPadding.x; const float snap_x_max = window->DC.CursorStartPos.x + window->ContentSize.x + window->WindowPadding.x; - target_x = CalcScrollSnap(target_x, snap_x_min, snap_x_max, snap_x_threshold, center_x_ratio); + target_pos_x = CalcScrollSnap(target_pos_x, snap_x_min, snap_x_max, snap_x_threshold, center_x_ratio); - SetScrollFromPosX(window, target_x - window->Pos.x, center_x_ratio); + SetScrollFromPosX(window, target_pos_x - window->Pos.x, center_x_ratio); // Convert from absolute to local pos } // center_y_ratio: 0.0f top of last item, 0.5f vertical center of last item, 1.0f bottom of last item. @@ -7534,15 +7540,15 @@ void ImGui::SetScrollHereY(float center_y_ratio) ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; float spacing_y = g.Style.ItemSpacing.y; - float target_y = ImLerp(window->DC.CursorPosPrevLine.y - spacing_y, window->DC.CursorPosPrevLine.y + window->DC.PrevLineSize.y + spacing_y, center_y_ratio); + float target_pos_y = ImLerp(window->DC.CursorPosPrevLine.y - spacing_y, window->DC.CursorPosPrevLine.y + window->DC.PrevLineSize.y + spacing_y, center_y_ratio); // Tweak: snap on edges when aiming at an item very close to the edge const float snap_y_threshold = ImMax(0.0f, window->WindowPadding.y - spacing_y); const float snap_y_min = window->DC.CursorStartPos.y - window->WindowPadding.y; const float snap_y_max = window->DC.CursorStartPos.y + window->ContentSize.y + window->WindowPadding.y; - target_y = CalcScrollSnap(target_y, snap_y_min, snap_y_max, snap_y_threshold, center_y_ratio); + target_pos_y = CalcScrollSnap(target_pos_y, snap_y_min, snap_y_max, snap_y_threshold, center_y_ratio); - SetScrollFromPosY(window, target_y - window->Pos.y, center_y_ratio); + SetScrollFromPosY(window, target_pos_y - window->Pos.y, center_y_ratio); // Convert from absolute to local pos } //----------------------------------------------------------------------------- diff --git a/imgui_internal.h b/imgui_internal.h index 1eed0d5b..b147c5a2 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1826,10 +1826,10 @@ namespace ImGui // Scrolling IMGUI_API void SetNextWindowScroll(const ImVec2& scroll); // Use -1.0f on one axis to leave as-is - IMGUI_API void SetScrollX(ImGuiWindow* window, float new_scroll_x); - IMGUI_API void SetScrollY(ImGuiWindow* window, float new_scroll_y); - IMGUI_API void SetScrollFromPosX(ImGuiWindow* window, float local_x, float center_x_ratio = 0.5f); - IMGUI_API void SetScrollFromPosY(ImGuiWindow* window, float local_y, float center_y_ratio = 0.5f); + IMGUI_API void SetScrollX(ImGuiWindow* window, float scroll_x); + IMGUI_API void SetScrollY(ImGuiWindow* window, float scroll_y); + IMGUI_API void SetScrollFromPosX(ImGuiWindow* window, float local_x, float center_x_ratio); + IMGUI_API void SetScrollFromPosY(ImGuiWindow* window, float local_y, float center_y_ratio); IMGUI_API ImVec2 ScrollToBringRectIntoView(ImGuiWindow* window, const ImRect& item_rect); // Basic Accessors From 70289ab42ca01fccc4c3d18a6ce880cd79b203e4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 3 Sep 2020 17:38:51 +0200 Subject: [PATCH 02/11] Scrolling: Fixed edge snapping being applied prior to knowing ContentSize. (#3452) Fix 473a01adb. --- imgui.cpp | 54 ++++++++++++++++++++++++++---------------------- imgui_internal.h | 1 + 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e133fd1a..ecb3d7be 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7363,6 +7363,19 @@ void ImGui::EndGroup() // [SECTION] SCROLLING //----------------------------------------------------------------------------- +// Helper to snap on edges when aiming at an item very close to the edge, +// So the difference between WindowPadding and ItemSpacing will be in the visible area after scrolling. +// When we refactor the scrolling API this may be configurable with a flag? +// Note that the effect for this won't be visible on X axis with default Style settings as WindowPadding.x == ItemSpacing.x by default. +static float CalcScrollEdgeSnap(float target, float snap_min, float snap_max, float snap_threshold, float center_ratio) +{ + if (target <= snap_min + snap_threshold) + return ImLerp(snap_min, target, center_ratio); + if (target >= snap_max - snap_threshold) + return ImLerp(target, snap_max, center_ratio); + return target; +} + static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window) { ImVec2 scroll = window->Scroll; @@ -7370,6 +7383,10 @@ static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window) { float center_x_ratio = window->ScrollTargetCenterRatio.x; float scroll_target_x = window->ScrollTarget.x; + float snap_x_min = 0.0f; + float snap_x_max = window->ScrollMax.x + window->Size.x; + if (window->ScrollTargetEdgeSnapDist.x > 0.0f) + scroll_target_x = CalcScrollEdgeSnap(scroll_target_x, snap_x_min, snap_x_max, window->ScrollTargetEdgeSnapDist.x, center_x_ratio); scroll.x = scroll_target_x - center_x_ratio * (window->SizeFull.x - window->ScrollbarSizes.x); } if (window->ScrollTarget.y < FLT_MAX) @@ -7377,6 +7394,10 @@ static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window) float decoration_up_height = window->TitleBarHeight() + window->MenuBarHeight(); float center_y_ratio = window->ScrollTargetCenterRatio.y; float scroll_target_y = window->ScrollTarget.y; + float snap_y_min = 0.0f; + float snap_y_max = window->ScrollMax.y + window->Size.y - decoration_up_height; + if (window->ScrollTargetEdgeSnapDist.y > 0.0f) + scroll_target_y = CalcScrollEdgeSnap(scroll_target_y, snap_y_min, snap_y_max, window->ScrollTargetEdgeSnapDist.y, center_y_ratio); scroll.y = scroll_target_y - center_y_ratio * (window->SizeFull.y - window->ScrollbarSizes.y - decoration_up_height); } scroll.x = IM_FLOOR(ImMax(scroll.x, 0.0f)); @@ -7447,12 +7468,14 @@ void ImGui::SetScrollX(ImGuiWindow* window, float scroll_x) { window->ScrollTarget.x = scroll_x; window->ScrollTargetCenterRatio.x = 0.0f; + window->ScrollTargetEdgeSnapDist.x = 0.0f; } void ImGui::SetScrollY(ImGuiWindow* window, float scroll_y) { window->ScrollTarget.y = scroll_y; window->ScrollTargetCenterRatio.y = 0.0f; + window->ScrollTargetEdgeSnapDist.y = 0.0f; } void ImGui::SetScrollX(float scroll_x) @@ -7482,6 +7505,7 @@ void ImGui::SetScrollFromPosX(ImGuiWindow* window, float local_x, float center_x IM_ASSERT(center_x_ratio >= 0.0f && center_x_ratio <= 1.0f); window->ScrollTarget.x = IM_FLOOR(local_x + window->Scroll.x); // Convert local position to scroll offset window->ScrollTargetCenterRatio.x = center_x_ratio; + window->ScrollTargetEdgeSnapDist.x = 0.0f; } void ImGui::SetScrollFromPosY(ImGuiWindow* window, float local_y, float center_y_ratio) @@ -7490,6 +7514,7 @@ void ImGui::SetScrollFromPosY(ImGuiWindow* window, float local_y, float center_y local_y -= window->TitleBarHeight() + window->MenuBarHeight(); // FIXME: Would be nice to have a more standardized access to our scrollable/client rect window->ScrollTarget.y = IM_FLOOR(local_y + window->Scroll.y); // Convert local position to scroll offset window->ScrollTargetCenterRatio.y = center_y_ratio; + window->ScrollTargetEdgeSnapDist.y = 0.0f; } void ImGui::SetScrollFromPosX(float local_x, float center_x_ratio) @@ -7504,19 +7529,6 @@ void ImGui::SetScrollFromPosY(float local_y, float center_y_ratio) SetScrollFromPosY(g.CurrentWindow, local_y, center_y_ratio); } -// Tweak: snap on edges when aiming at an item very close to the edge, -// So the difference between WindowPadding and ItemSpacing will be in the visible area after scrolling. -// When we refactor the scrolling API this may be configurable with a flag? -// Note that the effect for this won't be visible on X axis with default Style settings as WindowPadding.x == ItemSpacing.x by default. -static float CalcScrollSnap(float target, float snap_min, float snap_max, float snap_threshold, float center_ratio) -{ - if (target <= snap_min + snap_threshold) - return ImLerp(snap_min, target, center_ratio); - if (target >= snap_max - snap_threshold) - return ImLerp(target, snap_max, center_ratio); - return target; -} - // center_x_ratio: 0.0f left of last item, 0.5f horizontal center of last item, 1.0f right of last item. void ImGui::SetScrollHereX(float center_x_ratio) { @@ -7524,14 +7536,10 @@ void ImGui::SetScrollHereX(float center_x_ratio) ImGuiWindow* window = g.CurrentWindow; float spacing_x = g.Style.ItemSpacing.x; float target_pos_x = ImLerp(window->DC.LastItemRect.Min.x - spacing_x, window->DC.LastItemRect.Max.x + spacing_x, center_x_ratio); + SetScrollFromPosX(window, target_pos_x - window->Pos.x, center_x_ratio); // Convert from absolute to local pos // Tweak: snap on edges when aiming at an item very close to the edge - const float snap_x_threshold = ImMax(0.0f, window->WindowPadding.x - spacing_x); - const float snap_x_min = window->DC.CursorStartPos.x - window->WindowPadding.x; - const float snap_x_max = window->DC.CursorStartPos.x + window->ContentSize.x + window->WindowPadding.x; - target_pos_x = CalcScrollSnap(target_pos_x, snap_x_min, snap_x_max, snap_x_threshold, center_x_ratio); - - SetScrollFromPosX(window, target_pos_x - window->Pos.x, center_x_ratio); // Convert from absolute to local pos + window->ScrollTargetEdgeSnapDist.x = ImMax(0.0f, window->WindowPadding.x - spacing_x); } // center_y_ratio: 0.0f top of last item, 0.5f vertical center of last item, 1.0f bottom of last item. @@ -7541,14 +7549,10 @@ void ImGui::SetScrollHereY(float center_y_ratio) ImGuiWindow* window = g.CurrentWindow; float spacing_y = g.Style.ItemSpacing.y; float target_pos_y = ImLerp(window->DC.CursorPosPrevLine.y - spacing_y, window->DC.CursorPosPrevLine.y + window->DC.PrevLineSize.y + spacing_y, center_y_ratio); + SetScrollFromPosY(window, target_pos_y - window->Pos.y, center_y_ratio); // Convert from absolute to local pos // Tweak: snap on edges when aiming at an item very close to the edge - const float snap_y_threshold = ImMax(0.0f, window->WindowPadding.y - spacing_y); - const float snap_y_min = window->DC.CursorStartPos.y - window->WindowPadding.y; - const float snap_y_max = window->DC.CursorStartPos.y + window->ContentSize.y + window->WindowPadding.y; - target_pos_y = CalcScrollSnap(target_pos_y, snap_y_min, snap_y_max, snap_y_threshold, center_y_ratio); - - SetScrollFromPosY(window, target_pos_y - window->Pos.y, center_y_ratio); // Convert from absolute to local pos + window->ScrollTargetEdgeSnapDist.y = ImMax(0.0f, window->WindowPadding.y - spacing_y); } //----------------------------------------------------------------------------- diff --git a/imgui_internal.h b/imgui_internal.h index b147c5a2..f6655bd5 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1585,6 +1585,7 @@ struct IMGUI_API ImGuiWindow ImVec2 ScrollMax; ImVec2 ScrollTarget; // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX for no change) ImVec2 ScrollTargetCenterRatio; // 0.0f = scroll so that target position is at top, 0.5f = scroll so that target position is centered + ImVec2 ScrollTargetEdgeSnapDist; // 0.0f = no snapping, >0.0f snapping threshold ImVec2 ScrollbarSizes; // Size taken by each scrollbars on their smaller axis. Pay attention! ScrollbarSizes.x == width of the vertical scrollbar, ScrollbarSizes.y = height of the horizontal scrollbar. bool ScrollbarX, ScrollbarY; // Are scrollbars visible? bool Active; // Set to true on Begin(), unless Collapsed From 751d153ca9f338ec7159e7a250abe198b6a17d73 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 3 Sep 2020 19:09:57 +0200 Subject: [PATCH 03/11] InputText: Fixed callback's helper DeleteChars() function when cursor is inside the deleted block. (#3454). --- docs/CHANGELOG.txt | 3 +++ imgui_demo.cpp | 4 ++-- imgui_widgets.cpp | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 032360ad..8f9aa012 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -40,12 +40,15 @@ Other Changes: - Window: Fixed using non-zero pivot in SetNextWindowPos() when the window is collapsed. (#3433) - Nav: Fixed navigation resuming on first visible item when using gamepad. [@rokups] - Nav: Fixed using Alt to toggle the Menu layer when inside a Modal window. (#787) +- Scrolling: Fixed SetScrollHere functions edge snapping when called during a frame where ContentSize + is changing (issue introduced in 1.78). (#3452). - InputText: Added selection helpers in ImGuiInputTextCallbackData(). - InputText: Added ImGuiInputTextFlags_CallbackEdit to modify internally owned buffer after an edit. (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the underlying buffer while focus is active). - InputText: Fixed using ImGuiInputTextFlags_Password with InputTextMultiline(). (#3427, #3428) It is a rather unusual or useless combination of features but no reason it shouldn't work! +- InputText: Fixed callback's helper DeleteChars() function when cursor is inside the deleted block. (#3454). - DragFloat, DragScalar: Fixed ImGuiSliderFlags_ClampOnInput not being honored in the special case where v_min == v_max. (#3361) - BeginMenuBar: Fixed minor bug where CursorPosMax gets pushed to CursorPos prior to calling BeginMenuBar(), diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 05bb729a..9d0929a2 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -4209,9 +4209,9 @@ struct ExampleAppConsole } ImGui::TextWrapped( - "This example implements a console with basic coloring, completion and history. A more elaborate " + "This example implements a console with basic coloring, completion (TAB key) and history (Up/Down keys). A more elaborate " "implementation may want to store entries along with extra data such as timestamp, emitter, etc."); - ImGui::TextWrapped("Enter 'HELP' for help, press TAB to use text completion."); + ImGui::TextWrapped("Enter 'HELP' for help."); // TODO: display items starting from the bottom diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index eb5e4ad9..ba84c934 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -3620,7 +3620,7 @@ void ImGuiInputTextCallbackData::DeleteChars(int pos, int bytes_count) *dst++ = c; *dst = '\0'; - if (CursorPos + bytes_count >= pos) + if (CursorPos >= pos + bytes_count) CursorPos -= bytes_count; else if (CursorPos >= pos) CursorPos = pos; From b25756be4aa618d2d827363fc7d9014abe23df8e Mon Sep 17 00:00:00 2001 From: Michel Lesoinne Date: Fri, 8 May 2020 17:58:05 -0600 Subject: [PATCH 04/11] Examples: Vulkan: Switch validation layer. Fix CMakeLists to find Vulkan the standard way. (#3459) --- docs/CHANGELOG.txt | 2 ++ examples/example_glfw_vulkan/CMakeLists.txt | 8 +++++--- examples/example_glfw_vulkan/main.cpp | 5 ++--- examples/example_sdl_vulkan/main.cpp | 5 ++--- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 8f9aa012..515b0ff1 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -63,6 +63,8 @@ Other Changes: - Metrics: Various tweaks, listing windows front-to-back, greying inactive items when possible. - Demo: Add simple InputText() callbacks demo (aside from the more elaborate ones in 'Examples->Console'). - Examples: Vulkan: Reworked buffer resize handling, fix for Linux/X11. (#3390, #2626) [@RoryO] +- Examples: Vulkan: Switch validation layer to use "VK_LAYER_KHRONOS_validation" instead of + "VK_LAYER_LUNARG_standard_validation" which is deprecated (#3459) [@FunMiles] ----------------------------------------------------------------------- diff --git a/examples/example_glfw_vulkan/CMakeLists.txt b/examples/example_glfw_vulkan/CMakeLists.txt index 68155ec8..023d791b 100644 --- a/examples/example_glfw_vulkan/CMakeLists.txt +++ b/examples/example_glfw_vulkan/CMakeLists.txt @@ -28,9 +28,11 @@ set(IMGUI_DIR ../../) include_directories(${IMGUI_DIR} ..) # Libraries -find_library(VULKAN_LIBRARY - NAMES vulkan vulkan-1) -set(LIBRARIES "glfw;${VULKAN_LIBRARY}") +find_package(Vulkan REQUIRED) +#find_library(VULKAN_LIBRARY + #NAMES vulkan vulkan-1) +#set(LIBRARIES "glfw;${VULKAN_LIBRARY}") +set(LIBRARIES "glfw;Vulkan::Vulkan") # Use vulkan headers from glfw: include_directories(${GLFW_DIR}/deps) diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index 6dc2e6cf..5e5f7323 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -72,10 +72,9 @@ static void SetupVulkan(const char** extensions, uint32_t extensions_count) create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; create_info.enabledExtensionCount = extensions_count; create_info.ppEnabledExtensionNames = extensions; - #ifdef IMGUI_VULKAN_DEBUG_REPORT - // Enabling multiple validation layers grouped as LunarG standard validation - const char* layers[] = { "VK_LAYER_LUNARG_standard_validation" }; + // Enabling validation layers + const char* layers[] = { "VK_LAYER_KHRONOS_validation" }; create_info.enabledLayerCount = 1; create_info.ppEnabledLayerNames = layers; diff --git a/examples/example_sdl_vulkan/main.cpp b/examples/example_sdl_vulkan/main.cpp index b22e4247..03d7ded3 100644 --- a/examples/example_sdl_vulkan/main.cpp +++ b/examples/example_sdl_vulkan/main.cpp @@ -64,10 +64,9 @@ static void SetupVulkan(const char** extensions, uint32_t extensions_count) create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; create_info.enabledExtensionCount = extensions_count; create_info.ppEnabledExtensionNames = extensions; - #ifdef IMGUI_VULKAN_DEBUG_REPORT - // Enabling multiple validation layers grouped as LunarG standard validation - const char* layers[] = { "VK_LAYER_LUNARG_standard_validation" }; + // Enabling validation layers + const char* layers[] = { "VK_LAYER_KHRONOS_validation" }; create_info.enabledLayerCount = 1; create_info.ppEnabledLayerNames = layers; From 6461fd40ab815e14358923d4ffabbb8c40d8d049 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 7 Sep 2020 12:19:50 +0200 Subject: [PATCH 05/11] Examples: Fixed SDL+OpenGL2 and SDL+Vulkan examples not processing SDL_WINDOWEVENT_CLOSE events which tends to be needed in multi-viewport setting. --- examples/example_sdl_opengl2/main.cpp | 2 ++ examples/example_sdl_vulkan/main.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/examples/example_sdl_opengl2/main.cpp b/examples/example_sdl_opengl2/main.cpp index fcd9ae32..34ea80d0 100644 --- a/examples/example_sdl_opengl2/main.cpp +++ b/examples/example_sdl_opengl2/main.cpp @@ -87,6 +87,8 @@ int main(int, char**) 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; } // Start the Dear ImGui frame diff --git a/examples/example_sdl_vulkan/main.cpp b/examples/example_sdl_vulkan/main.cpp index 03d7ded3..c6ce12a1 100644 --- a/examples/example_sdl_vulkan/main.cpp +++ b/examples/example_sdl_vulkan/main.cpp @@ -454,6 +454,8 @@ int main(int, char**) 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; } // Resize swap chain? From b2039aac671bde42cbcc95de34e73419857fba68 Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Mon, 7 Sep 2020 17:38:56 +0200 Subject: [PATCH 06/11] Slider: Fixed to reach maximum value with inverted integer min/max ranges, both with signed and unsigned types. Added reverse Sliders to Demo. (#3432, #3449) --- imgui_demo.cpp | 10 +++++++++- imgui_internal.h | 4 ++-- imgui_widgets.cpp | 42 +++++++++++++++++++++++------------------- 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 9d0929a2..c7ab4310 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -617,7 +617,7 @@ static void ShowDemoWindowWidgets() "Hold SHIFT/ALT for faster/slower edit.\n" "Double-click or CTRL+click to input value."); - ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%d%%"); + ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%d%%", ImGuiSliderFlags_ClampOnInput); static float f1 = 1.00f, f2 = 0.0067f; ImGui::DragFloat("drag float", &f1, 0.005f); @@ -1688,6 +1688,14 @@ static void ShowDemoWindowWidgets() ImGui::SliderScalar("slider double low log",ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one, "%.10f", ImGuiSliderFlags_Logarithmic); ImGui::SliderScalar("slider double high", ImGuiDataType_Double, &f64_v, &f64_lo_a, &f64_hi_a, "%e grams"); + ImGui::Text("Sliders (reverse)"); + ImGui::SliderScalar("slider s8 reverse", ImGuiDataType_S8, &s8_v, &s8_max, &s8_min, "%d"); + ImGui::SliderScalar("slider u8 reverse", ImGuiDataType_U8, &u8_v, &u8_max, &u8_min, "%u"); + ImGui::SliderScalar("slider s32 reverse", ImGuiDataType_S32, &s32_v, &s32_fifty, &s32_zero, "%d"); + ImGui::SliderScalar("slider u32 reverse", ImGuiDataType_U32, &u32_v, &u32_fifty, &u32_zero, "%u"); + ImGui::SliderScalar("slider s64 reverse", ImGuiDataType_S64, &s64_v, &s64_fifty, &s64_zero, "%I64d"); + ImGui::SliderScalar("slider u64 reverse", ImGuiDataType_U64, &u64_v, &u64_fifty, &u64_zero, "%I64u ms"); + static bool inputs_step = true; ImGui::Text("Inputs"); ImGui::Checkbox("Show step buttons", &inputs_step); diff --git a/imgui_internal.h b/imgui_internal.h index f6655bd5..aceeebca 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1997,8 +1997,8 @@ namespace ImGui // Template functions are instantiated in imgui_widgets.cpp for a finite number of types. // To use them externally (for custom widget) you may need an "extern template" statement in your code in order to link to existing instances and silence Clang warnings (see #2036). // e.g. " extern template IMGUI_API float RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, float v); " - template IMGUI_API float ScaleRatioFromValueT(ImGuiDataType data_type, T v, T v_min, T v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_size); - template IMGUI_API T ScaleValueFromRatioT(ImGuiDataType data_type, float t, T v_min, T v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_size); + template IMGUI_API float ScaleRatioFromValueT(ImGuiDataType data_type, T v, T v_min, T v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_size); + template IMGUI_API T ScaleValueFromRatioT(ImGuiDataType data_type, float t, T v_min, T v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_size); template IMGUI_API bool DragBehaviorT(ImGuiDataType data_type, T* v, float v_speed, T v_min, T v_max, const char* format, ImGuiSliderFlags flags); template IMGUI_API bool SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, T* v, T v_min, T v_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb); template IMGUI_API T RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, T v); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index ba84c934..b0cf70bc 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -2094,9 +2094,9 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const logarithmic_zero_epsilon = ImPow(0.1f, (float)decimal_precision); // Convert to parametric space, apply delta, convert back - float v_old_parametric = ScaleRatioFromValueT(data_type, v_cur, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); + float v_old_parametric = ScaleRatioFromValueT(data_type, v_cur, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); float v_new_parametric = v_old_parametric + g.DragCurrentAccum; - v_cur = ScaleValueFromRatioT(data_type, v_new_parametric, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); + v_cur = ScaleValueFromRatioT(data_type, v_new_parametric, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); v_old_ref_for_accum_remainder = v_old_parametric; } else @@ -2113,7 +2113,7 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const if (is_logarithmic) { // Convert to parametric space, apply delta, convert back - float v_new_parametric = ScaleRatioFromValueT(data_type, v_cur, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); + float v_new_parametric = ScaleRatioFromValueT(data_type, v_cur, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); g.DragCurrentAccum -= (float)(v_new_parametric - v_old_ref_for_accum_remainder); } else @@ -2449,7 +2449,7 @@ bool ImGui::DragScalarN(const char* label, ImGuiDataType data_type, void* p_data //------------------------------------------------------------------------- // Convert a value v in the output space of a slider into a parametric position on the slider itself (the logical opposite of ScaleValueFromRatioT) -template +template float ImGui::ScaleRatioFromValueT(ImGuiDataType data_type, TYPE v, TYPE v_min, TYPE v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_halfsize) { if (v_min == v_max) @@ -2501,11 +2501,11 @@ float ImGui::ScaleRatioFromValueT(ImGuiDataType data_type, TYPE v, TYPE v_min, T } // Linear slider - return (float)((FLOATTYPE)(v_clamped - v_min) / (FLOATTYPE)(v_max - v_min)); + return (float)((FLOATTYPE)(SIGNEDTYPE)(v_clamped - v_min) / (FLOATTYPE)(SIGNEDTYPE)(v_max - v_min)); } // Convert a parametric position on a slider into a value v in the output space (the logical opposite of ScaleRatioFromValueT) -template +template TYPE ImGui::ScaleValueFromRatioT(ImGuiDataType data_type, float t, TYPE v_min, TYPE v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_halfsize) { if (v_min == v_max) @@ -2564,15 +2564,19 @@ TYPE ImGui::ScaleValueFromRatioT(ImGuiDataType data_type, float t, TYPE v_min, T } else { - // For integer values we want the clicking position to match the grab box so we round above - // This code is carefully tuned to work with large values (e.g. high ranges of U64) while preserving this property.. - FLOATTYPE v_new_off_f = (v_max - v_min) * t; - TYPE v_new_off_floor = (TYPE)(v_new_off_f); - TYPE v_new_off_round = (TYPE)(v_new_off_f + (FLOATTYPE)0.5); - if (v_new_off_floor < v_new_off_round) - result = v_min + v_new_off_round; + // - For integer values we want the clicking position to match the grab box so we round above + // This code is carefully tuned to work with large values (e.g. high ranges of U64) while preserving this property.. + // - Not doing a *1.0 multiply at the end of a range as it tends to be lossy. While absolute aiming at a large s64/u64 + // range is going to be imprecise anyway, with this check we at least make the edge values matches expected limits. + if (t < 1.0) + { + FLOATTYPE v_new_off_f = (SIGNEDTYPE)(v_max - v_min) * t; + result = (TYPE)((SIGNEDTYPE)v_min + (SIGNEDTYPE)(v_new_off_f + (FLOATTYPE)(v_min > v_max ? -0.5 : 0.5))); + } else - result = v_min + v_new_off_floor; + { + result = v_max; + } } } @@ -2672,7 +2676,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ } else if (g.SliderCurrentAccumDirty) { - clicked_t = ScaleRatioFromValueT(data_type, *v, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); + clicked_t = ScaleRatioFromValueT(data_type, *v, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); if ((clicked_t >= 1.0f && delta > 0.0f) || (clicked_t <= 0.0f && delta < 0.0f)) // This is to avoid applying the saturation when already past the limits { @@ -2686,10 +2690,10 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ clicked_t = ImSaturate(clicked_t + delta); // Calculate what our "new" clicked_t will be, and thus how far we actually moved the slider, and subtract this from the accumulator - TYPE v_new = ScaleValueFromRatioT(data_type, clicked_t, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); + TYPE v_new = ScaleValueFromRatioT(data_type, clicked_t, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); if (!(flags & ImGuiSliderFlags_NoRoundToFormat)) v_new = RoundScalarWithFormatT(format, data_type, v_new); - float new_clicked_t = ScaleRatioFromValueT(data_type, v_new, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); + float new_clicked_t = ScaleRatioFromValueT(data_type, v_new, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); if (delta > 0) g.SliderCurrentAccum -= ImMin(new_clicked_t - old_clicked_t, delta); @@ -2703,7 +2707,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ if (set_new_value) { - TYPE v_new = ScaleValueFromRatioT(data_type, clicked_t, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); + TYPE v_new = ScaleValueFromRatioT(data_type, clicked_t, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); // Round to user desired precision based on format string if (!(flags & ImGuiSliderFlags_NoRoundToFormat)) @@ -2725,7 +2729,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ else { // Output grab position so it can be displayed by the caller - float grab_t = ScaleRatioFromValueT(data_type, *v, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); + float grab_t = ScaleRatioFromValueT(data_type, *v, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); if (axis == ImGuiAxis_Y) grab_t = 1.0f - grab_t; const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t); From 36af39805605828b1a75e781abb3b1bdc72a49f5 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 7 Sep 2020 19:52:11 +0200 Subject: [PATCH 07/11] Sliders: Fixed using ImGuiSliderFlags_ClampOnInput with reverse sliders. (#3432, #3449) --- docs/CHANGELOG.txt | 2 ++ imgui_widgets.cpp | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 515b0ff1..b401c0ee 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -51,6 +51,8 @@ Other Changes: - InputText: Fixed callback's helper DeleteChars() function when cursor is inside the deleted block. (#3454). - DragFloat, DragScalar: Fixed ImGuiSliderFlags_ClampOnInput not being honored in the special case where v_min == v_max. (#3361) +- SliderInt, SliderScalar: Fixed reaching of maximum value with inverted integer min/max ranges, both + with signed and unsigned types. Added reverse Sliders to Demo. (#3432, #3449) [@rokups] - BeginMenuBar: Fixed minor bug where CursorPosMax gets pushed to CursorPos prior to calling BeginMenuBar(), so e.g. calling the function at the end of a window would often add +ItemSpacing.y to scrolling range. - TreeNode, CollapsingHeader: Made clicking on arrow toggle toggle the open state on the Mouse Down event diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index b0cf70bc..628d4cfd 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1942,7 +1942,7 @@ static bool DataTypeClampT(T* v, const T* v_min, const T* v_max) { // Clamp, both sides are optional, return true if modified if (v_min && *v < *v_min) { *v = *v_min; return true; } - if (v_max && *v > * v_max) { *v = *v_max; return true; } + if (v_max && *v > *v_max) { *v = *v_max; return true; } return false; } @@ -3191,7 +3191,11 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG // Apply new value (or operations) then clamp DataTypeApplyOpFromText(data_buf, g.InputTextState.InitialTextA.Data, data_type, p_data, NULL); if (p_clamp_min || p_clamp_max) + { + if (DataTypeCompare(data_type, p_clamp_min, p_clamp_max) > 0) + ImSwap(p_clamp_min, p_clamp_max); DataTypeClamp(data_type, p_data, p_clamp_min, p_clamp_max); + } // Only mark as edited if new value is different value_changed = memcmp(&data_backup, p_data, data_type_size) != 0; From 206d78a524bbd44e7ab611054e753bd63d5f4b20 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 8 Sep 2020 11:39:56 +0200 Subject: [PATCH 08/11] InputText: Fixed minor glitch when erasing trailing lines in InputTextMultiline(). Fixed cursor being partially covered after using Ctrl+End key. Removed unncessary one-empty-line-worth-of-scrolling. --- docs/CHANGELOG.txt | 2 ++ imgui_widgets.cpp | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b401c0ee..31410eda 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -48,6 +48,8 @@ Other Changes: underlying buffer while focus is active). - InputText: Fixed using ImGuiInputTextFlags_Password with InputTextMultiline(). (#3427, #3428) It is a rather unusual or useless combination of features but no reason it shouldn't work! +- InputText: Fixed minor scrolling glitch when erasing trailing lines in InputTextMultiline(). +- InputText: Fixed cursor being partially covered after using Ctrl+End key. - InputText: Fixed callback's helper DeleteChars() function when cursor is inside the deleted block. (#3454). - DragFloat, DragScalar: Fixed ImGuiSliderFlags_ClampOnInput not being honored in the special case where v_min == v_max. (#3361) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 628d4cfd..c797b1a0 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4433,11 +4433,14 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // Vertical scroll if (is_multiline) { + // Test if cursor is vertically visible float scroll_y = draw_window->Scroll.y; + const float scroll_max_y = ImMax((text_size.y + style.FramePadding.y * 2.0f) - inner_size.y, 0.0f); if (cursor_offset.y - g.FontSize < scroll_y) scroll_y = ImMax(0.0f, cursor_offset.y - g.FontSize); else if (cursor_offset.y - inner_size.y >= scroll_y) - scroll_y = cursor_offset.y - inner_size.y; + scroll_y = cursor_offset.y - inner_size.y + style.FramePadding.y * 2.0f; + scroll_y = ImClamp(scroll_y, 0.0f, scroll_max_y); draw_pos.y += (draw_window->Scroll.y - scroll_y); // Manipulate cursor pos immediately avoid a frame of lag draw_window->Scroll.y = scroll_y; } @@ -4526,7 +4529,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ if (is_multiline) { - Dummy(text_size + ImVec2(0.0f, g.FontSize)); // Always add room to scroll an extra line + Dummy(text_size); EndChild(); EndGroup(); } From 8a9ee9cdedd6f729a58a29cbfcce1bf8951a18f1 Mon Sep 17 00:00:00 2001 From: HALX99 Date: Tue, 8 Sep 2020 03:18:28 -0700 Subject: [PATCH 09/11] Add const qualifier for parameter ImFontConfig of ImFont::AddGlyph (#3461) --- imgui.h | 2 +- imgui_draw.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.h b/imgui.h index 40ffedad..71d1b20b 100644 --- a/imgui.h +++ b/imgui.h @@ -2442,7 +2442,7 @@ struct ImFont IMGUI_API void BuildLookupTable(); IMGUI_API void ClearOutputData(); IMGUI_API void GrowIndex(int new_size); - IMGUI_API void AddGlyph(ImFontConfig* src_cfg, ImWchar c, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x); + IMGUI_API void AddGlyph(const ImFontConfig* src_cfg, ImWchar c, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x); IMGUI_API void AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst = true); // Makes 'dst' character/glyph points to 'src' character/glyph. Currently needs to be called AFTER fonts have been built. IMGUI_API void SetGlyphVisible(ImWchar c, bool visible); IMGUI_API void SetFallbackChar(ImWchar c); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 5b79a449..2f87366a 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2886,7 +2886,7 @@ void ImFont::GrowIndex(int new_size) // x0/y0/x1/y1 are offset from the character upper-left layout position, in pixels. Therefore x0/y0 are often fairly close to zero. // Not to be mistaken with texture coordinates, which are held by u0/v0/u1/v1 in normalized format (0.0..1.0 on each texture axis). // 'cfg' is not necessarily == 'this->ConfigData' because multiple source fonts+configs can be used to build one target font. -void ImFont::AddGlyph(ImFontConfig* cfg, ImWchar codepoint, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x) +void ImFont::AddGlyph(const ImFontConfig* cfg, ImWchar codepoint, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x) { if (cfg != NULL) { From 6a546a500fb94e11c195850996575cb0d3f0e983 Mon Sep 17 00:00:00 2001 From: xndcn Date: Tue, 8 Sep 2020 11:49:30 +0800 Subject: [PATCH 10/11] ImVector: fix max_size() for signed int value. Amend 444873404 (#3429, #3460) --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index 71d1b20b..98a65699 100644 --- a/imgui.h +++ b/imgui.h @@ -1395,7 +1395,7 @@ struct ImVector inline bool empty() const { return Size == 0; } inline int size() const { return Size; } inline int size_in_bytes() const { return Size * (int)sizeof(T); } - inline int max_size() const { return (~(unsigned int)0) / (int)sizeof(T); } + inline int max_size() const { return 0x7FFFFFFF / (int)sizeof(T); } inline int capacity() const { return Capacity; } inline T& operator[](int i) { IM_ASSERT(i < Size); return Data[i]; } inline const T& operator[](int i) const { IM_ASSERT(i < Size); return Data[i]; } From 41e2aa2e7af93c070d9dfd0b822a29968e752cde Mon Sep 17 00:00:00 2001 From: Michel Lesoinne Date: Tue, 8 Sep 2020 16:47:06 +0200 Subject: [PATCH 11/11] Backends: Vulkan: Separate the pipeline of the dear imgui created windows from the one created with the user's render-pass. (#3455, #3459) This is mostly for the benefit of multi-viewports. --- docs/CHANGELOG.txt | 2 + examples/imgui_impl_vulkan.cpp | 259 +++++++++++++++++++++++---------- examples/imgui_impl_vulkan.h | 3 +- 3 files changed, 183 insertions(+), 81 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 31410eda..9cec4446 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -66,6 +66,8 @@ Other Changes: tabs reordered in the tab list popup. [@Xipiryon] - Metrics: Various tweaks, listing windows front-to-back, greying inactive items when possible. - Demo: Add simple InputText() callbacks demo (aside from the more elaborate ones in 'Examples->Console'). +- Backends: Vulkan: Some internal refactor aimed at allowing multi-viewport feature to create their + own render pass. (#3455, #3459) [@FunMiles] - Examples: Vulkan: Reworked buffer resize handling, fix for Linux/X11. (#3390, #2626) [@RoryO] - Examples: Vulkan: Switch validation layer to use "VK_LAYER_KHRONOS_validation" instead of "VK_LAYER_LUNARG_standard_validation" which is deprecated (#3459) [@FunMiles] diff --git a/examples/imgui_impl_vulkan.cpp b/examples/imgui_impl_vulkan.cpp index 465060d5..c47d5aab 100644 --- a/examples/imgui_impl_vulkan.cpp +++ b/examples/imgui_impl_vulkan.cpp @@ -22,6 +22,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2020-09-07: Vulkan: Added VkPipeline parameter to ImGui_ImplVulkan_RenderDrawData (default to one passed to ImGui_ImplVulkan_Init). // 2020-05-04: Vulkan: Fixed crash if initial frame has no vertices. // 2020-04-26: Vulkan: Fixed edge case where render callbacks wouldn't be called if the ImDrawData didn't have vertices. // 2019-08-01: Vulkan: Added support for specifying multisample count. Set ImGui_ImplVulkan_InitInfo::MSAASamples to one of the VkSampleCountFlagBits values to use, default is non-multisampled as before. @@ -80,6 +81,8 @@ static VkDescriptorSetLayout g_DescriptorSetLayout = VK_NULL_HANDLE; static VkPipelineLayout g_PipelineLayout = VK_NULL_HANDLE; static VkDescriptorSet g_DescriptorSet = VK_NULL_HANDLE; static VkPipeline g_Pipeline = VK_NULL_HANDLE; +static VkShaderModule g_ShaderModuleVert; +static VkShaderModule g_ShaderModuleFrag; // Font data static VkSampler g_FontSampler = VK_NULL_HANDLE; @@ -266,11 +269,11 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory p_buffer_size = new_size; } -static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkCommandBuffer command_buffer, ImGui_ImplVulkanH_FrameRenderBuffers* rb, int fb_width, int fb_height) +static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline pipeline, VkCommandBuffer command_buffer, ImGui_ImplVulkanH_FrameRenderBuffers* rb, int fb_width, int fb_height) { // Bind pipeline and descriptor sets: { - vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_Pipeline); + vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); VkDescriptorSet desc_set[1] = { g_DescriptorSet }; vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_PipelineLayout, 0, 1, desc_set, 0, NULL); } @@ -312,7 +315,7 @@ static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkCommandBu // Render function // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) -void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer) +void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline) { // 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); @@ -321,6 +324,8 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm return; ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo; + if (pipeline == VK_NULL_HANDLE) + pipeline = g_Pipeline; // Allocate array to store enough vertex/index buffers ImGui_ImplVulkanH_WindowRenderBuffers* wrb = &g_MainWindowRenderBuffers; @@ -374,7 +379,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm } // Setup desired Vulkan state - ImGui_ImplVulkan_SetupRenderState(draw_data, command_buffer, rb, fb_width, fb_height); + ImGui_ImplVulkan_SetupRenderState(draw_data, pipeline, command_buffer, rb, fb_width, fb_height); // Will project scissor/clipping rectangles into framebuffer space ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports @@ -395,7 +400,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm // 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_ImplVulkan_SetupRenderState(draw_data, command_buffer, rb, fb_width, fb_height); + ImGui_ImplVulkan_SetupRenderState(draw_data, pipeline, command_buffer, rb, fb_width, fb_height); else pcmd->UserCallback(cmd_list, pcmd); } @@ -586,99 +591,103 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer) return true; } -bool ImGui_ImplVulkan_CreateDeviceObjects() +static void ImGui_ImplVulkan_CreateShaderModules(VkDevice device, const VkAllocationCallbacks* allocator) { - ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo; - VkResult err; - VkShaderModule vert_module; - VkShaderModule frag_module; - - // Create The Shader Modules: + // Create the shader modules + if (g_ShaderModuleVert == NULL) { 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; - err = vkCreateShaderModule(v->Device, &vert_info, v->Allocator, &vert_module); + VkResult err = vkCreateShaderModule(device, &vert_info, allocator, &g_ShaderModuleVert); check_vk_result(err); + } + if (g_ShaderModuleFrag == NULL) + { 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; - err = vkCreateShaderModule(v->Device, &frag_info, v->Allocator, &frag_module); + VkResult err = vkCreateShaderModule(device, &frag_info, allocator, &g_ShaderModuleFrag); check_vk_result(err); } +} - if (!g_FontSampler) - { - VkSamplerCreateInfo info = {}; - info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; - info.magFilter = VK_FILTER_LINEAR; - info.minFilter = VK_FILTER_LINEAR; - info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; - info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; - info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; - info.minLod = -1000; - info.maxLod = 1000; - info.maxAnisotropy = 1.0f; - err = vkCreateSampler(v->Device, &info, v->Allocator, &g_FontSampler); - check_vk_result(err); - } +static void ImGui_ImplVulkan_CreateFontSampler(VkDevice device, const VkAllocationCallbacks* allocator) +{ + if (g_FontSampler) + return; - if (!g_DescriptorSetLayout) - { - VkSampler sampler[1] = {g_FontSampler}; - VkDescriptorSetLayoutBinding binding[1] = {}; - binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - binding[0].descriptorCount = 1; - binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - binding[0].pImmutableSamplers = sampler; - VkDescriptorSetLayoutCreateInfo info = {}; - info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - info.bindingCount = 1; - info.pBindings = binding; - err = vkCreateDescriptorSetLayout(v->Device, &info, v->Allocator, &g_DescriptorSetLayout); - check_vk_result(err); - } + VkSamplerCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + info.magFilter = VK_FILTER_LINEAR; + info.minFilter = VK_FILTER_LINEAR; + info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.minLod = -1000; + info.maxLod = 1000; + info.maxAnisotropy = 1.0f; + VkResult err = vkCreateSampler(device, &info, allocator, &g_FontSampler); + check_vk_result(err); +} - // Create Descriptor Set: - { - VkDescriptorSetAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - alloc_info.descriptorPool = v->DescriptorPool; - alloc_info.descriptorSetCount = 1; - alloc_info.pSetLayouts = &g_DescriptorSetLayout; - err = vkAllocateDescriptorSets(v->Device, &alloc_info, &g_DescriptorSet); - check_vk_result(err); - } +static void ImGui_ImplVulkan_CreateDescriptorSetLayout(VkDevice device, const VkAllocationCallbacks* allocator) +{ + if (g_DescriptorSetLayout) + return; - if (!g_PipelineLayout) - { - // Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix - VkPushConstantRange push_constants[1] = {}; - push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - push_constants[0].offset = sizeof(float) * 0; - push_constants[0].size = sizeof(float) * 4; - VkDescriptorSetLayout set_layout[1] = { g_DescriptorSetLayout }; - VkPipelineLayoutCreateInfo layout_info = {}; - layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - layout_info.setLayoutCount = 1; - layout_info.pSetLayouts = set_layout; - layout_info.pushConstantRangeCount = 1; - layout_info.pPushConstantRanges = push_constants; - err = vkCreatePipelineLayout(v->Device, &layout_info, v->Allocator, &g_PipelineLayout); - check_vk_result(err); - } + ImGui_ImplVulkan_CreateFontSampler(device, allocator); + VkSampler sampler[1] = { g_FontSampler }; + VkDescriptorSetLayoutBinding binding[1] = {}; + binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + binding[0].descriptorCount = 1; + binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + binding[0].pImmutableSamplers = sampler; + VkDescriptorSetLayoutCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + info.bindingCount = 1; + info.pBindings = binding; + VkResult err = vkCreateDescriptorSetLayout(device, &info, allocator, &g_DescriptorSetLayout); + check_vk_result(err); +} + +static void ImGui_ImplVulkan_CreatePipelineLayout(VkDevice device, const VkAllocationCallbacks* allocator) +{ + if (g_PipelineLayout) + return; + + // Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix + ImGui_ImplVulkan_CreateDescriptorSetLayout(device, allocator); + VkPushConstantRange push_constants[1] = {}; + push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + push_constants[0].offset = sizeof(float) * 0; + push_constants[0].size = sizeof(float) * 4; + VkDescriptorSetLayout set_layout[1] = { g_DescriptorSetLayout }; + VkPipelineLayoutCreateInfo layout_info = {}; + layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + layout_info.setLayoutCount = 1; + layout_info.pSetLayouts = set_layout; + layout_info.pushConstantRangeCount = 1; + layout_info.pPushConstantRanges = push_constants; + VkResult err = vkCreatePipelineLayout(device, &layout_info, allocator, &g_PipelineLayout); + check_vk_result(err); +} + +static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationCallbacks* allocator, VkPipelineCache pipelineCache, VkRenderPass renderPass, VkSampleCountFlagBits MSAASamples, VkPipeline *pipeline) +{ + ImGui_ImplVulkan_CreateShaderModules(device, allocator); VkPipelineShaderStageCreateInfo stage[2] = {}; stage[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; stage[0].stage = VK_SHADER_STAGE_VERTEX_BIT; - stage[0].module = vert_module; + stage[0].module = g_ShaderModuleVert; stage[0].pName = "main"; stage[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; stage[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; - stage[1].module = frag_module; + stage[1].module = g_ShaderModuleFrag; stage[1].pName = "main"; VkVertexInputBindingDescription binding_desc[1] = {}; @@ -724,10 +733,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() VkPipelineMultisampleStateCreateInfo ms_info = {}; ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - if (v->MSAASamples != 0) - ms_info.rasterizationSamples = v->MSAASamples; - else - ms_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + ms_info.rasterizationSamples = (MSAASamples != 0) ? MSAASamples : VK_SAMPLE_COUNT_1_BIT; VkPipelineColorBlendAttachmentState color_attachment[1] = {}; color_attachment[0].blendEnable = VK_TRUE; @@ -753,6 +759,8 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() dynamic_state.dynamicStateCount = (uint32_t)IM_ARRAYSIZE(dynamic_states); dynamic_state.pDynamicStates = dynamic_states; + ImGui_ImplVulkan_CreatePipelineLayout(device, allocator); + VkGraphicsPipelineCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; info.flags = g_PipelineCreateFlags; @@ -767,9 +775,97 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() info.pColorBlendState = &blend_info; info.pDynamicState = &dynamic_state; info.layout = g_PipelineLayout; - info.renderPass = g_RenderPass; - err = vkCreateGraphicsPipelines(v->Device, v->PipelineCache, 1, &info, v->Allocator, &g_Pipeline); + info.renderPass = renderPass; + VkResult err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &info, allocator, pipeline); check_vk_result(err); +} + +bool ImGui_ImplVulkan_CreateDeviceObjects() +{ + ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo; + VkResult err; + VkShaderModule vert_module; + VkShaderModule frag_module; + + // Create The Shader Modules: + { + 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; + err = vkCreateShaderModule(v->Device, &vert_info, v->Allocator, &vert_module); + check_vk_result(err); + 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; + err = vkCreateShaderModule(v->Device, &frag_info, v->Allocator, &frag_module); + check_vk_result(err); + } + + if (!g_FontSampler) + { + VkSamplerCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + info.magFilter = VK_FILTER_LINEAR; + info.minFilter = VK_FILTER_LINEAR; + info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.minLod = -1000; + info.maxLod = 1000; + info.maxAnisotropy = 1.0f; + err = vkCreateSampler(v->Device, &info, v->Allocator, &g_FontSampler); + check_vk_result(err); + } + + if (!g_DescriptorSetLayout) + { + VkSampler sampler[1] = {g_FontSampler}; + VkDescriptorSetLayoutBinding binding[1] = {}; + binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + binding[0].descriptorCount = 1; + binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + binding[0].pImmutableSamplers = sampler; + VkDescriptorSetLayoutCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + info.bindingCount = 1; + info.pBindings = binding; + err = vkCreateDescriptorSetLayout(v->Device, &info, v->Allocator, &g_DescriptorSetLayout); + check_vk_result(err); + } + + // Create Descriptor Set: + { + VkDescriptorSetAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + alloc_info.descriptorPool = v->DescriptorPool; + alloc_info.descriptorSetCount = 1; + alloc_info.pSetLayouts = &g_DescriptorSetLayout; + err = vkAllocateDescriptorSets(v->Device, &alloc_info, &g_DescriptorSet); + check_vk_result(err); + } + + if (!g_PipelineLayout) + { + // Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix + VkPushConstantRange push_constants[1] = {}; + push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + push_constants[0].offset = sizeof(float) * 0; + push_constants[0].size = sizeof(float) * 4; + VkDescriptorSetLayout set_layout[1] = { g_DescriptorSetLayout }; + VkPipelineLayoutCreateInfo layout_info = {}; + layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + layout_info.setLayoutCount = 1; + layout_info.pSetLayouts = set_layout; + layout_info.pushConstantRangeCount = 1; + layout_info.pPushConstantRanges = push_constants; + err = vkCreatePipelineLayout(v->Device, &layout_info, v->Allocator, &g_PipelineLayout); + check_vk_result(err); + } + + ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, v->PipelineCache, g_RenderPass, v->MSAASamples, &g_Pipeline); vkDestroyShaderModule(v->Device, vert_module, v->Allocator); vkDestroyShaderModule(v->Device, frag_module, v->Allocator); @@ -1017,6 +1113,8 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V wd->ImageCount = 0; if (wd->RenderPass) vkDestroyRenderPass(device, wd->RenderPass, allocator); + if (wd->Pipeline) + vkDestroyPipeline(device, wd->Pipeline, allocator); // If min image count was not specified, request different count of images dependent on selected present mode if (min_image_count == 0) @@ -1112,6 +1210,7 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V info.pDependencies = &dependency; err = vkCreateRenderPass(device, &info, allocator, &wd->RenderPass); check_vk_result(err); + ImGui_ImplVulkan_CreatePipeline(device, allocator, VK_NULL_HANDLE, wd->RenderPass, VK_SAMPLE_COUNT_1_BIT, &wd->Pipeline); } // Create The Image Views diff --git a/examples/imgui_impl_vulkan.h b/examples/imgui_impl_vulkan.h index 0eb772e7..951574cd 100644 --- a/examples/imgui_impl_vulkan.h +++ b/examples/imgui_impl_vulkan.h @@ -46,7 +46,7 @@ struct ImGui_ImplVulkan_InitInfo IMGUI_IMPL_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass); IMGUI_IMPL_API void ImGui_ImplVulkan_Shutdown(); IMGUI_IMPL_API void ImGui_ImplVulkan_NewFrame(); -IMGUI_IMPL_API void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer); +IMGUI_IMPL_API void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline = VK_NULL_HANDLE); IMGUI_IMPL_API bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer); IMGUI_IMPL_API void ImGui_ImplVulkan_DestroyFontUploadObjects(); IMGUI_IMPL_API void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated) @@ -108,6 +108,7 @@ struct ImGui_ImplVulkanH_Window VkSurfaceFormatKHR SurfaceFormat; VkPresentModeKHR PresentMode; VkRenderPass RenderPass; + VkPipeline Pipeline; // The window pipeline uses a different VkRenderPass than the user's bool ClearEnable; VkClearValue ClearValue; uint32_t FrameIndex; // Current frame being rendered to (0 <= FrameIndex < FrameInFlightCount)