Skip to content

Compare the GL context, not the ImGui context, when detecting a context change - #463

Merged
matt-edmondson merged 1 commit into
mainfrom
claude/detect-gl-context-change
Sep 24, 2026
Merged

matt-edmondson merged 1 commit into
mainfrom
claude/detect-gl-context-change

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #462.

The bug

CheckAndHandleContextChange() is called from RemapCanvas and the window Move handler, and is documented as reloading textures when the GL context changes. It compared ImGui.GetCurrentContext().Handle against a cached currentGLContextHandle — but that is the ImGui context, created once in ImGuiController.Init and never replaced. The comparison could never differ, so ReloadAllTextures() was unreachable and a replaced GL context left every id in Textures naming an object the new context had never created: images render blank for the rest of the process, silently.

The fix

Per the issue's suggested approach, track the thing that actually identifies the context — the GL the tracked textures were uploaded against — and compare it by reference:

  • internal static IntPtr currentGLContextHandle becomes internal static GL? currentGLContext.
  • The ImGui.GetCurrentContext() capture in onConfigureIO is removed; the field is owned entirely by the detector, so no new assignment site can forget to update it.
  • The first observation records the GL without reloading. Those textures were uploaded against that GL, and reloading would re-upload every one of them and orphan the handles it replaced — ReloadAllTextures deliberately does not delete the old ids ("the context is already gone"), which is only true when the context really has changed.
  • Reset() clears the field.

CheckAndHandleContextChange no longer needs unsafe, so that block and its S6640 suppression are gone.

What this does and does not detect

It detects a GL the application replaced. A driver-side reset that invalidates the context underneath an unchanged GL instance — the hybrid-graphics and resume-from-sleep cases the issue also mentions — is not observable this way; catching those needs a GL_KHR_robustness reset query, which requires a robustness-enabled context and hardware to verify against. That is recorded in a <remarks> on the method and is deliberately not attempted here. What this change does settle is that the comparison is now against the right object, instead of one that provably never changes.

Tests

Two tests in ImGuiAppTests, using the existing FakeRendererBackend — the reload uploads through IRendererBackend, not through GL directly, so no GL entry point is ever called and the test needs no live context. The GL instances are constructed over a Mock<INativeContext> purely to be distinct references.

  • CheckAndHandleContextChange_WhenTheGLIsReplaced_ReloadsTrackedTextures — the regression the issue asks for. Asserts the first observation leaves the texture alone, then that replacing the GL reloads it and the tracked entry picks up the id the new context handed back. Fails against the previous implementation (verified by restoring ImGuiApp.cs and re-running: 1 failed, 472 passed).
  • CheckAndHandleContextChange_WithTheSameGL_DoesNotReload — the guard against the opposite failure. RemapCanvas calls this on every move and resize, so reloading unconditionally would re-upload every texture and orphan the replaced handles. Passes before and after by design.

Full ImGui.App.Tests suite: 473 passed, 0 failed (471 pre-existing, unchanged). Release build of ImGui.App: 0 warnings, 0 errors.

🤖 Generated with Claude Code

https://claude.ai/code/session_01XD56Kg65nsraeL7vTL9MgU


Generated by Claude Code

…xt change

CheckAndHandleContextChange compared ImGui.GetCurrentContext().Handle, but
that context is created once in ImGuiController.Init and never replaced, so
the comparison could never differ and ReloadAllTextures was unreachable. A
replaced GL context therefore left every tracked texture id naming an object
the new context had never created.

Track the GL the tracked textures were uploaded against and compare it by
reference instead. The first observation records without reloading, so a
window move or resize does not re-upload textures that are still valid.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XD56Kg65nsraeL7vTL9MgU
@sonarqubecloud

Copy link
Copy Markdown

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.

GPU context-loss detection compares the ImGui context handle, not the GL context, so ReloadAllTextures never fires

2 participants