Skip to content

perf: reduce per-frame draw time spikes in toolbar and drawing layer#451

Open
Yoshihiko-Ino wants to merge 3 commits into
una-xiv:mainfrom
Yoshihiko-Ino:perf/optimize-toolbar-rendering
Open

perf: reduce per-frame draw time spikes in toolbar and drawing layer#451
Yoshihiko-Ino wants to merge 3 commits into
una-xiv:mainfrom
Yoshihiko-Ino:perf/optimize-toolbar-rendering

Conversation

@Yoshihiko-Ino

@Yoshihiko-Ino Yoshihiko-Ino commented May 4, 2026

Copy link
Copy Markdown

Summary

  • AuxBarManager: Replaced per-frame LINQ + ToList() in VisibleAuxBarPanels with a pre-allocated list that is cleared and reused each frame.
  • Toolbar: Added _cachedIsCursorNear field so IsCursorNearToolbar() is called exactly once per frame instead of multiple times across UpdateToolbarNodeClassList(), UpdateToolbarAutoHideOffset(), and Toolbar.Nodes.cs.
  • Toolbar.Autohide: Cached ImGui.GetIO() to a local variable to avoid multiple P/Invoke calls per frame; inlined the IsMultiMonitorSupportEnabled() helper.
  • Toolbar.Nodes: Cached ImGui.GetMainViewport() to a local variable inside RenderAuxBarNodes(); removed the redundant auxBarNode.ComputeBoundingSize() call (bounds are already computed inside Render()); removed two unused using directives; expanded ToolbarXPosition / ToolbarYPosition to block-body properties so the viewport is fetched once per call.
  • ToolbarWidget / WidgetManager: Cached ImGui.GetIO() to a local variable where it was called multiple times in the same scope; replaced GetInvocationList() unsubscribe loops with direct = null assignments.
  • UmbraVisibility: Introduced a frame-scoped validity flag (_visibilityCacheValid) reset via [OnDraw(executionOrder: int.MinValue)]; IsToolbarVisible() and AreMarkersVisible() now call the underlying checks at most once per frame and return cached results on subsequent calls.
  • WindowManager: Replaced GetInvocationList() unsubscribe loops with direct = null assignments; moved window iteration outside the lock to reduce contention.

Related

This PR covers only changes to the Umbra layer. Companion optimizations in the Una.Drawing library are submitted separately in una-xiv/drawing#25.

Co-Authored-By: Yoshihiko-Ino <232758239+Yoshihiko-Ino@users.noreply.github.com>
…tion

Co-Authored-By: Yoshihiko-Ino <232758239+Yoshihiko-Ino@users.noreply.github.com>
@Yoshihiko-Ino Yoshihiko-Ino force-pushed the perf/optimize-toolbar-rendering branch from 33652b0 to 8677c30 Compare May 7, 2026 00:24
- CompassRenderer: cache icon textures to avoid per-frame GPU texture lookups;
  integrate upstream viewport size check and error logging
- WorldMarkerNode: replace ToList().IndexOf() with direct dictionary traversal
- WorldMarkerRenderer: reuse _idsToRemove list to reduce GC pressure
- WorldMarkerRegistry: use TryGetValue to avoid KeyNotFoundException overhead
- AuxBarNode: dirty flag to skip per-frame widget traversal when layout unchanged
- WidgetPopup: fix duplicate PushStyleVar/PopStyleVar imbalance; improve error
  handling with finally-guarded ImGui.End(); fix _isCrashed reset on close
- Umbra.Colors: use Stop()/Start() instead of Enabled toggle for thread-safe
  debounce timer reset
- Umbra.DelvClipRects: clear _managedRects on disable to keep dictionaries in sync
- Umbra.Drawing: case-insensitive resource name lookup in DocumentFrom()
- VariablesEditorWindow: fix ValueChanged handler to update node.Value not variable.Value
- WindowManager: lock _instances when removing closed window to prevent races
@Yoshihiko-Ino Yoshihiko-Ino force-pushed the perf/optimize-toolbar-rendering branch from 8677c30 to 2f8205b Compare May 7, 2026 00:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant