From e27b1d1cb5bacdfab8510ffd5f98a90e90192070 Mon Sep 17 00:00:00 2001 From: Gliniak Date: Mon, 13 Oct 2025 22:08:52 +0200 Subject: [PATCH] [UI] Fixed issues with ImGui on Vulkan and few ASAN issues related to ImGui - Simplified handling of notifications to faster version with ranges - Removed usage of STB sprintf on checked due to ASAN violation - Draw ImGui windows only when they're not in close_pending state --- premake5.lua | 3 ++ src/xenia/app/emulator_window.cc | 6 +++- src/xenia/app/profile_dialogs.cc | 15 +++++--- src/xenia/ui/d3d12/d3d12_immediate_drawer.cc | 5 +-- src/xenia/ui/imgui_dialog.cc | 4 ++- src/xenia/ui/imgui_dialog.h | 2 ++ src/xenia/ui/imgui_drawer.cc | 36 ++++++++----------- .../ui/vulkan/vulkan_immediate_drawer.cc | 5 +-- 8 files changed, 40 insertions(+), 36 deletions(-) diff --git a/premake5.lua b/premake5.lua index b3b2d9c16..674cc96c6 100644 --- a/premake5.lua +++ b/premake5.lua @@ -66,6 +66,9 @@ filter("configurations:Checked") editandcontinue("Off") staticruntime("Off") optimize("Off") + removedefines({ + "IMGUI_USE_STB_SPRINTF", + }) defines({ "DEBUG", }) diff --git a/src/xenia/app/emulator_window.cc b/src/xenia/app/emulator_window.cc index e1fb88214..3816b2cd7 100644 --- a/src/xenia/app/emulator_window.cc +++ b/src/xenia/app/emulator_window.cc @@ -1459,7 +1459,11 @@ void EmulatorWindow::ToggleProfilesConfigDialog() { } else { disable_hotkeys_ = false; emulator_->kernel_state()->BroadcastNotification(kXNotificationSystemUI, 0); - profile_config_dialog_.reset(); + if (profile_config_dialog_->IsClosing()) { + profile_config_dialog_.release(); + } else { + profile_config_dialog_.reset(); + } emulator_->kernel_state()->xam_state()->xam_dialogs_shown_--; } } diff --git a/src/xenia/app/profile_dialogs.cc b/src/xenia/app/profile_dialogs.cc index 5bf0fe1af..67148cc6b 100644 --- a/src/xenia/app/profile_dialogs.cc +++ b/src/xenia/app/profile_dialogs.cc @@ -168,6 +168,16 @@ void ProfileConfigDialog::OnDraw(ImGuiIO& io) { return; } + // For whatever reason dialog wasn't opened. It's probably in closing state. + // We need to handle it here before it will make icons allocation. + if (!dialog_open) { + ImGui::CloseCurrentPopup(); + Close(); + ImGui::End(); + emulator_window_->ToggleProfilesConfigDialog(); + return; + } + if (profiles->empty()) { ImGui::TextUnformatted("No profiles found!"); ImGui::Spacing(); @@ -291,11 +301,6 @@ void ProfileConfigDialog::OnDraw(ImGuiIO& io) { } ImGui::End(); - - if (!dialog_open) { - emulator_window_->ToggleProfilesConfigDialog(); - return; - } } } // namespace app diff --git a/src/xenia/ui/d3d12/d3d12_immediate_drawer.cc b/src/xenia/ui/d3d12/d3d12_immediate_drawer.cc index 817221664..70ea18931 100644 --- a/src/xenia/ui/d3d12/d3d12_immediate_drawer.cc +++ b/src/xenia/ui/d3d12/d3d12_immediate_drawer.cc @@ -358,10 +358,7 @@ void D3D12ImmediateDrawer::Begin(UIDrawContext& ui_draw_context, ++it; continue; } - if (std::next(it) != textures_deleted_.end()) { - *it = textures_deleted_.back(); - } - textures_deleted_.pop_back(); + it = textures_deleted_.erase(it); } // Release upload buffers for completed texture uploads. diff --git a/src/xenia/ui/imgui_dialog.cc b/src/xenia/ui/imgui_dialog.cc index 20c9e0d0f..c5e490be9 100644 --- a/src/xenia/ui/imgui_dialog.cc +++ b/src/xenia/ui/imgui_dialog.cc @@ -41,7 +41,9 @@ ImGuiIO& ImGuiDialog::GetIO() { return imgui_drawer()->GetIO(); } void ImGuiDialog::Draw() { // Draw UI. - OnDraw(GetIO()); + if (!has_close_pending_) { + OnDraw(GetIO()); + } // Check to see if the UI closed itself and needs to be deleted. if (has_close_pending_) { diff --git a/src/xenia/ui/imgui_dialog.h b/src/xenia/ui/imgui_dialog.h index c27a6572e..b5eb70f56 100644 --- a/src/xenia/ui/imgui_dialog.h +++ b/src/xenia/ui/imgui_dialog.h @@ -34,6 +34,8 @@ class ImGuiDialog { void Draw(); + bool IsClosing() const { return has_close_pending_; } + protected: ImGuiDialog(ImGuiDrawer* imgui_drawer); diff --git a/src/xenia/ui/imgui_drawer.cc b/src/xenia/ui/imgui_drawer.cc index 82407ab21..9c6d1d9d3 100644 --- a/src/xenia/ui/imgui_drawer.cc +++ b/src/xenia/ui/imgui_drawer.cc @@ -11,6 +11,7 @@ #include #include +#include #include "third_party/imgui/imgui.h" #include "xenia/base/assert.h" @@ -597,32 +598,25 @@ void ImGuiDrawer::Draw(UIDrawContext& ui_draw_context) { dialog_loop_next_index_ = SIZE_MAX; if (!notifications_.empty() && are_notifications_enabled_) { - std::vector guest_notifications = {}; - std::vector host_notifications = {}; + auto guest_notifications = + notifications_ | std::views::filter([](auto* notification) { + return notification->GetNotificationType() == NotificationType::Guest; + }); - std::copy_if(notifications_.cbegin(), notifications_.cend(), - std::back_inserter(guest_notifications), - [](ui::ImGuiNotification* notification) { - return notification->GetNotificationType() == - NotificationType::Guest; - }); + auto host_notifications = + notifications_ | std::views::filter([](auto* notification) { + return notification->GetNotificationType() == NotificationType::Host; + }); - std::copy_if(notifications_.cbegin(), notifications_.cend(), - std::back_inserter(host_notifications), - [](ui::ImGuiNotification* notification) { - return notification->GetNotificationType() == - NotificationType::Host; - }); - - if (guest_notifications.size() > 0) { - guest_notifications.at(0)->Draw(); + if (!guest_notifications.empty()) { + guest_notifications.front()->Draw(); } - if (host_notifications.size() > 0) { - host_notifications.at(0)->Draw(); + if (!host_notifications.empty()) { + host_notifications.front()->Draw(); - if (host_notifications.size() > 1) { - host_notifications.at(0)->SetDeletionPending(); + if (std::ranges::distance(host_notifications) > 1) { + host_notifications.front()->SetDeletionPending(); } } } diff --git a/src/xenia/ui/vulkan/vulkan_immediate_drawer.cc b/src/xenia/ui/vulkan/vulkan_immediate_drawer.cc index eecc93b69..8f7b724fe 100644 --- a/src/xenia/ui/vulkan/vulkan_immediate_drawer.cc +++ b/src/xenia/ui/vulkan/vulkan_immediate_drawer.cc @@ -223,10 +223,7 @@ void VulkanImmediateDrawer::Begin(UIDrawContext& ui_draw_context, continue; } DestroyTextureResource(it->first); - if (std::next(it) != textures_deleted_.end()) { - *it = textures_deleted_.back(); - } - textures_deleted_.pop_back(); + it = textures_deleted_.erase(it); } // Release upload buffers for completed texture uploads.