Repository navigation
Description
Summary
Several renderer visual-evidence / golden tests pass in isolation but fail under --gtest_shuffle — i.e. they are order-dependent. That is the #530 bug species (renderer/GPU global state that survives a boundary which should reset it), manifested at the test level: some state leaks between tests despite the RendererAttachedTest per-test GLStateGuard(Restore) + renderer reset. This is both a CI-reliability risk (a shuffle, or simply adding/reordering a test, reddens the build) and a strong signal of a real renderer state leak that isn't reset on a scene/path/settings boundary in production.
This is distinct from #530 (that issue is the specific blackboard-fingerprint-cache-survives-ResetTopology instance, whose symptom is a whole-graph cull → empty frame). The failures here are subtler (partial frame corruption, a brightness-ordering flip, a shadow-golden mismatch), so they are other instances of the same species — though triage should check whether #530's fix incidentally resolves any of them.
Evidence (fresh Debug build, 2026-07-04)
Full suite --gtest_shuffle --gtest_repeat=2: iteration 1 → 2 failures, iteration 2 → 4 failures. Every shuffle-failing test passes when run alone (verified, each in its own process):
| Test | Shuffled result | Isolated result | Assertion |
|---|---|---|---|
OccludedInstanceFieldScene.OcclusionDoesNotCorruptOrHoleTheFrame |
FAIL | PASS | changed 0.2478 vs 0.02 — 24.8% of the frame changed vs the occlusion-off reference |
GoldenImageTest.SceneShadowIntegrationGolden |
FAIL | PASS | golden mismatch |
ProceduralSkyBakeTest.HigherTurbidityProducesBrighterAverage |
FAIL | PASS | hazyLum 2.403 vs clearLum 2.661 (expected hazy > clear) |
EASUVisualEvidenceTest.GTAOSurvivesRuntimeUpscaleSwitch |
FAIL (both iters) | PASS | upMean 0 vs nativeMean*0.5 — GTAO region black. May overlap #533 (GTAO-too-dark), so treat separately. |
(AppLaunchSmoke.OloRuntimeLaunchesCleanly also failed — that one is a false failure from a partial build that didn't produce OloRuntime.exe, ignore.)
Deterministic reproduction
The pollution reproduces within just the renderer visual suite (246 tests), so the leaking state is inside that set:
build/OloEngine/tests/Debug/OloEngine-Tests.exe \
--gtest_filter="*VisualEvidence*:*Golden*:*Occlu*:*ProceduralSky*:*Evidence*:*GTAO*:*Water*:*SSAO*:*SSGI*:*SSR*" \
--gtest_shuffle --gtest_random_seed=58251
# => OccludedInstanceFieldScene.OcclusionDoesNotCorruptOrHoleTheFrame FAILS
# seed 58250 => GoldenImageTest.SceneShadowIntegrationGolden FAILS; 58252 => Occlusion FAILS again
Each of those same tests passes with --gtest_filter=<TestName> alone.
Notes / narrowing
- The victim tests span occlusion culling, shadow golden, procedural-sky bake, and GTAO/EASU → a shared renderer/GPU global that isn't reset between tests. Candidate leaked state:
Renderer3D::s_Datafields not zeroed by the per-test reset (Settings.Path/ActiveGraphPath,PostProcess.ActiveAOTechnique, upscale mode,OcclusionResultsAvailable,OcclusionHZBValid), the occlusion singletons (OcclusionQueryPool/OcclusionStateManager/ persistent HZB pyramid),IBLCache, or raw GL enable state. - GL clue: the run logs 4×
GL_INVALID_ENUM error generated. <cap> enum is invalid(aglEnable/glDisablewith an out-of-range capability) — a GL-state-handling smell worth checking as part of the same audit. - The immediate predecessor of the occlusion failure (seed 58251) was a 0 ms structural test, so the leak is cumulative, not a single adjacent polluter — a proper bisection (shrink the filter around the fixed seed) is needed to name the exact producer.
Fix direction
- Bisect with the fixed seed (58251) to identify the producing test, then find which global it leaves dirty.
- Extend the
RendererAttachedTestteardown to reset that state (and auditRenderer3D::s_Datafor every "valid until invalidated" member against every reset path — same audit that surfaced RenderGraph: second consecutive Deferred-path switch in one process culls the entire graph (reads=0/writes=0) #530), and/or reset the occlusion singletons between tests. - Add a shuffled renderer-visual job to CI so this regresses loudly rather than depending on definition order.
Score
capability: 3
craft: 1
stability: 5
decay: 3
effort: 3
confidence: 0.8
learning: 3
fun: 3
kano: table-stakes
blocked_by: []
blocks: []
Rated per issue-scoring · score = confidence × (capability + craft + stability + decay) / effort, derived by the picker.
Activity
coderabbitai commentedon Jul 4, 2026
🔗 Related PRs
#263 - fix(tests): untangle Renderer3D test coupling for full-pipeline render tests (
#258) [merged]#335 - fix(tests): de-flake issue
#324CI failures at their real root causes [merged]#465 - Fix/flaky fog visual evidence test [merged]
#506 - test-infra: assert clean GL error state after each GPU test (
#485) [merged]#514 - feat: Implement deferred two-phase occlusion culling [merged]
#528 - fix(renderer): reset water-depth/planar-reflection texture publications per frame (
#505) [merged]#529 - fix(renderer): lazily upload deferred font textures so headless-first-touch fonts render (
#520) [merged]#532 - fix(renderer): resize GTAO scratch textures with the FSR1 scene band [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!
Merge pull request #564 from drsnuggles8/feature/renderer-test-pollution
feat(rhi): Phase 7 — port the full render-pass suite to Vulkan (#691) (…