You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
RebindMenuScene.RendersRebindPanelAndProducesPng fails deterministically in full-suite runs on master (UI text does not render; passes in isolation) #520
Found while validating feature/shadow-pcss-performance (2026-07-03); reproduced on a freshly built master (36939c5) test exe, so it is pre-existing and unrelated to that branch.
Symptom: in a full-suite run, RebindMenuScene.RendersRebindPanelAndProducesPng fails its bright-pixel contract with the bit-identical value every time:
RebindMenuVisualEvidenceTest.cpp(146): error: Expected: (maxLum) > (0.3f), actual: 0.269014895 vs 0.3
no bright pixels — panel text/buttons may not have rendered
The evidence PNG shows the panel backdrop and button fills render fine but every text glyph is missing (title, row labels, button captions) — maxLum 0.269 is the button-fill grey; the >0.3 pixels the contract wants are the near-white text. So this is a text-rendering dropout, not a threshold-tuning issue.
Order dependence: passes in isolation (--gtest_filter=RebindMenuScene.*, maxLum ~0.93) and when run together with its immediate in-suite predecessors (SceneWithCamera, SceneRenders3D, LitCubeScene). Only the full 4000+-test run kills the text — some earlier test leaves font/text-path state (font atlas? MSDF asset cache? Renderer2D_Text resources) in a state where RuntimeInputRebindMenu's labels silently don't draw.
Repro (RTX 4090, Windows 11, Debug):
build\OloEngine\tests\Debug\OloEngine-Tests.exe → FAILED, maxLum 0.269014895 (3/3 runs on the feature branch, 1/1 on fresh master)
--gtest_filter=RebindMenuScene.* → OK
The deterministic 0.269014895 across branches and runs points at a reproducible state leak rather than flaky timing.
Silently drops ALL UI text when a font is first parsed headless (before the renderer is up) then rendered — a real render-path correctness bug, not just test signal; sibling of #505 but worse (wrong pixels, not benign). Small, verified fix. Rated per issue-scoring.
Root cause:Font::GetDefault() caches a process-global static Ref<Font>, and SlugFontProcessor::Process only creates the Slug curve/band GPU textures when a GL context is bound. In full-suite order, FontMeasureLineTest (a plain metrics-only TEST(), no GL context) calls Font::GetDefault()before any GPU test brings the renderer up, caching a font that is IsLoaded() but has null curve/band textures. RebindMenuScene then renders its labels through that poisoned cached font (UI text falls back to Font::GetDefault()), so every glyph silently drops — leaving only the button-fill grey (maxLum 0.269). In isolation the font is first loaded during a render (context live), so the textures exist and it passes.
Fix: retain the packed texel data when the GPU upload is deferred and upload the textures lazily on first render (SlugFontProcessor::EnsureGpuTextures, called from Font::GetCurveTexture()/GetBandTexture()), freeing the CPU copy afterward. Makes any headless-first-touched font render-robust — not a test-ordering workaround.
Verified: full suite 4041 passed / 0 failed with RebindMenuScene[ OK ] in the exact failing ordering; minimal poison-then-render repro passes; evidence PNG shows all glyphs rendering. Added deterministic guard SlugDeferredUploadTest.EnsureGpuTexturesUploadsRetainedData and documented the lazy-GPU-resource headless-cache-leak class in docs/agent-rules/testing-architecture.md §6.5.
Activity
coderabbitai commentedon Jul 3, 2026
🔗 Related PRs
#250 - Fix viewport-resize rendering bugs (GTAO ghost halo + transient pool … [merged]
#263 - fix(tests): untangle Renderer3D test coupling for full-pipeline render tests (
#258) [merged]#404 - fix(renderer): repair reflection-probe bake (was all-black) + add vis… [merged]
#465 - Fix/flaky fog visual evidence test [merged]
#479 - feat(renderer): CAS contrast-adaptive sharpening pass (
#432) [merged]🧪 Issue enrichment is currently in open beta.
To disable automatic issue enrichment, add the following to your
.coderabbit.yaml:💬 Have feedback or questions? Drop into our discord!
drsnuggles8 commentedon Jul 3, 2026
Fixed in #529 (commit e948d77).
Root cause:
Font::GetDefault()caches a process-globalstatic Ref<Font>, andSlugFontProcessor::Processonly creates the Slug curve/band GPU textures when a GL context is bound. In full-suite order,FontMeasureLineTest(a plain metrics-onlyTEST(), no GL context) callsFont::GetDefault()before any GPU test brings the renderer up, caching a font that isIsLoaded()but has null curve/band textures.RebindMenuScenethen renders its labels through that poisoned cached font (UI text falls back toFont::GetDefault()), so every glyph silently drops — leaving only the button-fill grey (maxLum 0.269). In isolation the font is first loaded during a render (context live), so the textures exist and it passes.Fix: retain the packed texel data when the GPU upload is deferred and upload the textures lazily on first render (
SlugFontProcessor::EnsureGpuTextures, called fromFont::GetCurveTexture()/GetBandTexture()), freeing the CPU copy afterward. Makes any headless-first-touched font render-robust — not a test-ordering workaround.Verified: full suite 4041 passed / 0 failed with
RebindMenuScene[ OK ]in the exact failing ordering; minimal poison-then-render repro passes; evidence PNG shows all glyphs rendering. Added deterministic guardSlugDeferredUploadTest.EnsureGpuTexturesUploadsRetainedDataand documented the lazy-GPU-resource headless-cache-leak class indocs/agent-rules/testing-architecture.md§6.5.build(cmake): link libstdc++exp for std::stacktrace on Linux/Clang + GCC
Merge pull request #529 from drsnuggles8/feature/rebindmenu-text-rend…