The in-tower ACDREAM_WB_DIAG launch (the saved character spawns inside the #119 tower - a free deterministic repro lever) produced the mechanism evidence in one run (tower-wbdiag3.log): 1. [wb-error] upload of 0x0100321D died on a GL InvalidOperation in ManagedGLTextureArray..ctor (new TextureAtlasManager) - caught, returns null, and the drop is STICKY: _preparationTasks.TryRemove runs BEFORE the upload, so a failed upload is never re-prepared. Permanently invisible mesh, one log line. This failure class is the likely #119 missing-stairs mechanism (dat + extraction + registration + dispatcher all exonerated by read/test this session). 2. The SAME GL error then fired UNCAUGHT in Tick -> GenerateMipmaps -> ProcessDirtyUpdatesInternal and killed the process. Both render- thread - not thread affinity. Filed as #125 (HIGH) with the open question of GL error attribution (a stale error queued by an earlier unchecked call lands on WB's diligent glGetError checks). Also fixed here: WbDrawDispatcher.MedianMicros crashed with IndexOutOfRange on the first diag flush when exactly 1 sample was recorded (copy[copy.Length - nz/2] with nz==1) - the same off-by-one GameWindow's TerrainDiagMedianMicros twin fixed; same fix applied. ACDREAM_WB_DIAG=1 is usable again. Suites: App 236, Core 1419+2skip, UI 420, Net 294. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
1b8c9f1f50
commit
63d14c3d6b
2 changed files with 50 additions and 1 deletions
|
|
@ -4225,6 +4225,50 @@ selector.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## #125 — GL InvalidOperation during staged texture upload: failed uploads are STICKY (never retried) + uncaught crash in GenerateMipmaps
|
||||||
|
|
||||||
|
**Status:** OPEN — HIGH (the likely #119 missing-stairs mechanism + a process crash)
|
||||||
|
**Filed:** 2026-06-11 (in-tower WB_DIAG launch, `tower-wbdiag3.log` — preserved in the worktree root)
|
||||||
|
**Component:** render — WB staged texture pipeline (ObjectMeshManager / ManagedGLTextureArray)
|
||||||
|
|
||||||
|
**Evidence (one launch, character spawned inside the #119 tower):**
|
||||||
|
1. `[wb-error] Error uploading mesh data for 0x0100321D` — GL
|
||||||
|
`InvalidOperation` thrown in `ManagedGLTextureArray..ctor:70`
|
||||||
|
(TextureAtlasManager ctor → CreateTextureArrayInternal), caught by
|
||||||
|
`UploadMeshData`'s try/catch → returns null. **The drop is STICKY:**
|
||||||
|
`_preparationTasks.TryRemove` runs BEFORE the upload
|
||||||
|
(ObjectMeshManager.cs:685), so a failed upload is never re-prepared —
|
||||||
|
that mesh is permanently invisible for the session (only a one-line
|
||||||
|
[wb-error] marks it).
|
||||||
|
2. Same session, `Tick()` → `GenerateMipmaps()` →
|
||||||
|
`ManagedGLTextureArray.ProcessDirtyUpdatesInternal:283` threw the SAME
|
||||||
|
GL InvalidOperation **uncaught** → process death (exit 82). Both on the
|
||||||
|
render thread (Tick/OnRender) — not a thread-affinity bug.
|
||||||
|
|
||||||
|
**Why this matters for #119:** the missing tower stairs are per-cell
|
||||||
|
Setup statics whose parts are individually uploaded; an intermittent GL
|
||||||
|
error burst during atlas creation/flush kills whichever uploads are in
|
||||||
|
flight — "partially invisible", varying with load order, hitting the
|
||||||
|
late-loading AAB3 interior statics consistently. The dat + extraction +
|
||||||
|
registration + dispatcher are all exonerated by read/test
|
||||||
|
(Issue119TowerDumpTests; the [up-null] pair was a separate, legitimate
|
||||||
|
no-draw class).
|
||||||
|
|
||||||
|
**Open questions (next session):** (a) what makes the GL context error
|
||||||
|
out — a stale error queued by an earlier unchecked call being
|
||||||
|
mis-attributed to WB's diligent glGetError checks (classic GL
|
||||||
|
attribution trap; suspects: the #117 stencil punch state, the new #118 /
|
||||||
|
#121 passes, or a pre-existing per-frame state leak), vs. a genuine
|
||||||
|
invalid texture-array creation state; (b) whether upload failures should
|
||||||
|
re-enqueue instead of dropping (retail has no such failure mode — the
|
||||||
|
sticky drop is OUR invention and must go regardless); (c) the uncaught
|
||||||
|
GenerateMipmaps path needs the same handling either way.
|
||||||
|
**Repro lever:** the test character's save spawns INSIDE the tower —
|
||||||
|
every launch loads the exact content; `ACDREAM_WB_DIAG=1` prints the
|
||||||
|
meshMissing counters.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
# Recently closed
|
# Recently closed
|
||||||
|
|
||||||
## #113 — Phantom staircase: REOPENED 2026-06-11, folded into the HOLISTIC BUILDING-RENDER PORT
|
## #113 — Phantom staircase: REOPENED 2026-06-11, folded into the HOLISTIC BUILDING-RENDER PORT
|
||||||
|
|
|
||||||
|
|
@ -1583,7 +1583,12 @@ public sealed unsafe class WbDrawDispatcher : IDisposable
|
||||||
int nz = 0;
|
int nz = 0;
|
||||||
foreach (var v in copy) if (v > 0) nz++;
|
foreach (var v in copy) if (v > 0) nz++;
|
||||||
if (nz == 0) return 0;
|
if (nz == 0) return 0;
|
||||||
return copy[copy.Length - nz / 2];
|
// Sorted ascending: zero-padding front, samples at the back. (nz - 1) / 2
|
||||||
|
// from the end keeps the offset >= 0 for all nz >= 1 — the original
|
||||||
|
// nz / 2 form indexed copy[copy.Length] (crash) on the first diag flush
|
||||||
|
// when exactly 1 sample was recorded. Same fix as GameWindow's
|
||||||
|
// TerrainDiagMedianMicros twin.
|
||||||
|
return copy[copy.Length - 1 - (nz - 1) / 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long Percentile95Micros(long[] samples)
|
private static long Percentile95Micros(long[] samples)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue