From a62ee9f811e9b0e67db9dae5fa904d861995ce8f Mon Sep 17 00:00:00 2001 From: Asuro Date: Mon, 16 Jan 2023 02:10:57 +0100 Subject: [PATCH] perf stuff --- AsuroTool/ApplicationData.h | 1 + AsuroTool/AsuroTool.cpp | 47 +++++++++++++++++++++++++++++++------ AsuroTool/AudioApi.cpp | 3 +++ ImguiBase/ImguiBase.cpp | 39 +++++++++++++++++++++++++++++- ImguiBase/ImguiBase.h | 28 ++++++++++++++++++++++ 5 files changed, 110 insertions(+), 8 deletions(-) diff --git a/AsuroTool/ApplicationData.h b/AsuroTool/ApplicationData.h index 4a251d7..e19f145 100644 --- a/AsuroTool/ApplicationData.h +++ b/AsuroTool/ApplicationData.h @@ -46,6 +46,7 @@ public: bool autostart = false; bool docked = false; bool showDisabledDevices = false; + bool showChecklistExtras = false; std::vector taskNames = {}; std::unordered_map> tasks = {}; }; diff --git a/AsuroTool/AsuroTool.cpp b/AsuroTool/AsuroTool.cpp index 2fd1831..f655969 100644 --- a/AsuroTool/AsuroTool.cpp +++ b/AsuroTool/AsuroTool.cpp @@ -23,6 +23,7 @@ #include #define MAX_FONT_PATH_LENGTH 2048 +#define SETTINGS_POPUP_NAME "settings_popup" // Globals for use in callbacks DrawData* gDrawData; @@ -175,8 +176,6 @@ ImVec2 menuBar(DrawData& drawData, ApplicationData& appData) updateDocked(drawData, appData); } - ImGui::Checkbox("Show Disabled Devices", &appData.settings.showDisabledDevices); - if (ImGui::Checkbox("Autostart", &appData.settings.autostart)) { setAutostart(appData.settings.autostart); @@ -191,6 +190,10 @@ ImVec2 menuBar(DrawData& drawData, ApplicationData& appData) { reloadDeviceLists(*appData.audioData); } + ImGui::Text("setup: %.1f ms", drawData.frameTimeSetup); + ImGui::Text("draw: %.1f ms", drawData.frameTimeDraw); + ImGui::Text("render: %.1f ms", drawData.frameTimeRender); + ImGui::Text("display: %.1f ms", drawData.frameTimeDisplay); ImGui::EndMenu(); } @@ -242,6 +245,22 @@ bool customButton(const char* id_start, const char* id_end, const char* title, b return result; } +bool windowHeaderButton(const char* id) +{ + ImRect tempRect = ImGui::GetCurrentWindow()->ClipRect; + ImVec2 tempPos = ImGui::GetCursorPos(); + ImVec2 windowMax = ImGui::GetWindowContentRegionMax(); + ImGui::PopClipRect(); + + ImGui::SetCursorPos({ windowMax.x - 20.f, tempPos.y - 28.f }); + bool result = ImGui::SmallButton(id); + + ImGui::PushClipRect(tempRect.Min, tempRect.Max, false); + ImGui::SetCursorPos(tempPos); + + return result; +} + void drawChecklistDayLines(ApplicationData& appData, ImDrawList* drawList, float lineHeight, time_t day) { auto& tasks = appData.settings.tasks; @@ -291,6 +310,11 @@ ImVec2 checklistWindow(ApplicationData& appData, const char* title) { if (ImGui::Begin(title, 0, ImGuiWindowFlags_NoResize)) { + if (windowHeaderButton(ICON_SETTINGS_FILL)) + { + ImGui::OpenPopup(SETTINGS_POPUP_NAME); + } + time_t today = getDayStartOf(std::time(nullptr)); ImDrawList* drawList = ImGui::GetWindowDrawList(); float lineHeight = ImGui::GetFontSize() + ImGui::GetStyle().FramePadding.y * 2; @@ -355,13 +379,11 @@ ImVec2 checklistWindow(ApplicationData& appData, const char* title) ImGui::SameLine(); } - if (ImGui::SmallButton(ICON_SETTINGS_FILL)) - { - ImGui::OpenPopup("checklist settings"); - } - if (ImGui::BeginPopup("checklist settings")) + if (ImGui::BeginPopup(SETTINGS_POPUP_NAME)) { + ImGui::PushItemWidth(75.f); ImGui::DragInt("Task highlight duration", &appData.checklistHighlightDurationDays, .05f, 1, 7, "%d days"); + ImGui::PopItemWidth(); ImGui::EndPopup(); } } @@ -375,6 +397,11 @@ ImVec2 audioDeviceWindow(ApplicationData& appData, std::vector& dev { if (ImGui::Begin(title, 0, ImGuiWindowFlags_NoResize)) { + if (windowHeaderButton(ICON_SETTINGS_FILL)) + { + ImGui::OpenPopup(SETTINGS_POPUP_NAME); + } + if (ImGui::BeginTable("DeviceTable", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_Borders | ImGuiTableFlags_NoSavedSettings)) { ImGui::TableSetupColumn("Devices", ImGuiTableColumnFlags_WidthStretch, 3.); @@ -497,6 +524,12 @@ ImVec2 audioDeviceWindow(ApplicationData& appData, std::vector& dev } } + if (ImGui::BeginPopup(SETTINGS_POPUP_NAME)) + { + ImGui::Checkbox("Show Disabled Devices", &appData.settings.showDisabledDevices); + ImGui::EndPopup(); + } + ImVec2 size = ImGui::GetWindowSize(); ImGui::End(); diff --git a/AsuroTool/AudioApi.cpp b/AsuroTool/AudioApi.cpp index 2eba786..f462f20 100644 --- a/AsuroTool/AudioApi.cpp +++ b/AsuroTool/AudioApi.cpp @@ -143,6 +143,7 @@ void setDefaultAudioDevice(AudioData& audioData, const wchar_t* deviceId, ERole } } +// @slow (.2ms) float getVolume(IAudioEndpointVolume* volumeInterface) { float volume; @@ -160,6 +161,7 @@ void setVolume(IAudioEndpointVolume* volumeInterface, float newVolume) isError(hr, "Failed to set volume level: "); } +// @slow (.4ms) UINT getMeterValues(IAudioMeterInformation* meterInterface, std::array& outLevels) { UINT channelCount; @@ -176,6 +178,7 @@ void getVolumeLimit(IAudioEndpointVolume* volumeInterface, float* outMin, float* volumeInterface->GetVolumeRange(outMin, outMax, &dummy); } +// @slow (.3ms) bool isMuted(IAudioEndpointVolume* volumeInterface) { BOOL result = false; diff --git a/ImguiBase/ImguiBase.cpp b/ImguiBase/ImguiBase.cpp index 5a8eaf6..8604f5d 100644 --- a/ImguiBase/ImguiBase.cpp +++ b/ImguiBase/ImguiBase.cpp @@ -448,6 +448,12 @@ int startImgui(ImGuiCallbacks& callbacks, const char* title, int windowWidth, in ImGui_ImplVulkan_DestroyFontUploadObjects(); } + PerfTimer setupTimer{}; + PerfTimer drawTimer{}; + PerfTimer renderTimer{}; + PerfTimer displayTimer{}; + int drawCounter = IMGUI_REDRAW_COUNT; + // Main loop while (!glfwWindowShouldClose(window)) { @@ -456,7 +462,18 @@ int startImgui(ImGuiCallbacks& callbacks, const char* title, int windowWidth, in // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. - glfwPollEvents(); + if (false && drawCounter == 0) + { + glfwWaitEvents(); + drawCounter = IMGUI_REDRAW_COUNT; + } + else + { + glfwPollEvents(); + drawCounter--; + } + + setupTimer.Start(); // Resize swap chain? if (g_SwapChainRebuild) @@ -480,6 +497,9 @@ int startImgui(ImGuiCallbacks& callbacks, const char* title, int windowWidth, in ImVec2 prevWindowSize = getWindowSize(window); drawData.window_size = prevWindowSize; + setupTimer.End(); + drawTimer.Start(); + if (callbacks.drawFunc) { callbacks.drawFunc(drawData); @@ -490,8 +510,12 @@ int startImgui(ImGuiCallbacks& callbacks, const char* title, int windowWidth, in glfwSetWindowSize(window, drawData.window_size.x, drawData.window_size.y); } + drawTimer.End(); + renderTimer.Start(); + // Rendering ImGui::Render(); + ImDrawData* draw_data = ImGui::GetDrawData(); const bool is_minimized = (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f); if (!is_minimized) @@ -501,8 +525,21 @@ int startImgui(ImGuiCallbacks& callbacks, const char* title, int windowWidth, in wd->ClearValue.color.float32[2] = drawData.clear_color.z * drawData.clear_color.w; wd->ClearValue.color.float32[3] = drawData.clear_color.w; FrameRender(wd, draw_data); + renderTimer.End(); + + displayTimer.Start(); FramePresent(wd); + displayTimer.End(); } + else + { + renderTimer.End(); + } + + drawData.frameTimeSetup = setupTimer.resultSeconds; + drawData.frameTimeDraw = drawTimer.resultSeconds; + drawData.frameTimeRender = renderTimer.resultSeconds; + drawData.frameTimeDisplay = displayTimer.resultSeconds; } // Cleanup diff --git a/ImguiBase/ImguiBase.h b/ImguiBase/ImguiBase.h index f09daac..42d2e17 100644 --- a/ImguiBase/ImguiBase.h +++ b/ImguiBase/ImguiBase.h @@ -11,12 +11,18 @@ #include "imgui.h" #include "remixicon.h" +#define IMGUI_REDRAW_COUNT 3 + class DrawData { public: GLFWwindow* window = nullptr; HWND window_handle = nullptr; ImVec4 clear_color = {}; ImVec2 window_size = {}; + float frameTimeSetup = 0.f; + float frameTimeDraw = 0.f; + float frameTimeRender = 0.f; + float frameTimeDisplay = 0.f; }; class ImGuiCallbacks { @@ -26,6 +32,28 @@ public: std::function cleanupFunc = nullptr; }; +class PerfTimer { +private: + LARGE_INTEGER start; + LARGE_INTEGER end; + LARGE_INTEGER freq; + +public: + LONGLONG resultTicks; + float resultSeconds; + +public: + void Start() { + QueryPerformanceFrequency(&freq); + QueryPerformanceCounter(&start); + } + void End() { + QueryPerformanceCounter(&end); + resultTicks = end.QuadPart - start.QuadPart; + resultSeconds = static_cast(resultTicks * 1000) / freq.QuadPart; + } +}; + int startImgui(ImGuiCallbacks& callbacks, const char* title, int windowWidth, int windowHeight); ImVec2 getWindowSize(GLFWwindow* window);