diag(render): tripwires on every silent dat-miss path (white-walls attribution, #105)
The intermittent white-cottage-walls failure has NEVER produced a log line: every dat-read failure on the walls-relevant paths exits silently, and the failed result is cached for the session (mesh batches build once). Today it reproduced on a probe-free launch with a 35-line, zero-error log — so the prior heavy-probes-starve-the-dat-reader framing is not the whole story. Tripwires (print ONLY on anomaly; zero cost healthy; keep until #105 closes): - [dat-miss] DatDatabaseWrapper.TryGet — a miss for an id whose BTree entry EXISTS (re-probed under the same lock); legit not-found fallbacks stay quiet. - [tex-miss] TextureCache.DecodeFromDats x3 — render-thread decode fell back to magenta (Surface / SurfaceTexture / RenderSurface miss). - [cell-miss] GameWindow interior hydration x2 — EnvCell or Environment read returned null, so a cell''s WALLS are silently never registered while its statics still draw (the exact observed geometry signature). Color discriminates the layer on the next occurrence: magenta = TextureCache; see-through + [tex-skip]/[dat-miss] = mesh build; see-through + [cell-miss] = hydration; broken with NO tripwire output = GL-side upload/residency. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
8fadf770fe
commit
7433b704fb
3 changed files with 39 additions and 1 deletions
|
|
@ -5471,13 +5471,28 @@ public sealed class GameWindow : IDisposable
|
|||
{
|
||||
uint envCellId = firstCellId + offset;
|
||||
var envCell = _dats.Get<DatReaderWriter.DBObjs.EnvCell>(envCellId);
|
||||
if (envCell is null) continue;
|
||||
if (envCell is null)
|
||||
{
|
||||
// TEMP diagnostic (dat-race investigation 2026-06-09, strip with fix):
|
||||
// every id in [0x0100, 0x0100+NumCells) is derived from LandBlockInfo and
|
||||
// MUST exist in the cell dat — a null here is always a read anomaly.
|
||||
Console.WriteLine($"[cell-miss] EnvCell 0x{envCellId:X8} null during interior hydration (NumCells={lbInfo.NumCells})");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Phase 7.1: build and register room geometry for this EnvCell.
|
||||
DatReaderWriter.Types.CellStruct? cellStruct = null;
|
||||
if (envCell.EnvironmentId != 0)
|
||||
{
|
||||
var environment = _dats.Get<DatReaderWriter.DBObjs.Environment>(0x0D000000u | envCell.EnvironmentId);
|
||||
if (environment is null)
|
||||
{
|
||||
// TEMP diagnostic (dat-race investigation 2026-06-09, strip with fix):
|
||||
// a null Environment means this cell's WALLS are silently never
|
||||
// registered while its static objects still draw — the exact
|
||||
// white-walls geometry signature.
|
||||
Console.WriteLine($"[cell-miss] Environment 0x{0x0D000000u | envCell.EnvironmentId:X8} null for EnvCell 0x{envCellId:X8} -> walls not registered");
|
||||
}
|
||||
if (environment is not null
|
||||
&& environment.Cells.TryGetValue(envCell.CellStructure, out cellStruct))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -385,7 +385,11 @@ public sealed unsafe class TextureCache : Wb.ITextureCachePerInstance, IDisposab
|
|||
{
|
||||
var surface = _dats.Get<Surface>(surfaceId);
|
||||
if (surface is null)
|
||||
{
|
||||
// TEMP diagnostic (dat-race investigation 2026-06-09, strip with fix)
|
||||
Console.WriteLine($"[tex-miss] Surface 0x{surfaceId:X8} -> magenta (thread={System.Environment.CurrentManagedThreadId})");
|
||||
return DecodedTexture.Magenta;
|
||||
}
|
||||
|
||||
// Base1Solid surfaces (and any with OrigTextureId==0) carry a ColorValue
|
||||
// instead of a texture chain. Overrides are irrelevant here — there's
|
||||
|
|
@ -401,12 +405,20 @@ public sealed unsafe class TextureCache : Wb.ITextureCachePerInstance, IDisposab
|
|||
uint surfaceTextureId = origTextureOverride ?? (uint)surface.OrigTextureId;
|
||||
var surfaceTexture = _dats.Get<SurfaceTexture>(surfaceTextureId);
|
||||
if (surfaceTexture is null || surfaceTexture.Textures.Count == 0)
|
||||
{
|
||||
// TEMP diagnostic (dat-race investigation 2026-06-09, strip with fix)
|
||||
Console.WriteLine($"[tex-miss] SurfaceTexture 0x{surfaceTextureId:X8} (surface 0x{surfaceId:X8}) -> magenta (thread={System.Environment.CurrentManagedThreadId})");
|
||||
return DecodedTexture.Magenta;
|
||||
}
|
||||
|
||||
uint renderSurfaceId = (uint)surfaceTexture.Textures[0];
|
||||
if (!_dats.Portal.TryGet<RenderSurface>(renderSurfaceId, out var rs)
|
||||
&& !_dats.HighRes.TryGet<RenderSurface>(renderSurfaceId, out rs))
|
||||
{
|
||||
// TEMP diagnostic (dat-race investigation 2026-06-09, strip with fix)
|
||||
Console.WriteLine($"[tex-miss] RenderSurface 0x{renderSurfaceId:X8} (surface 0x{surfaceId:X8}) -> magenta (thread={System.Environment.CurrentManagedThreadId})");
|
||||
return DecodedTexture.Magenta;
|
||||
}
|
||||
|
||||
// Start with the texture's default palette, then apply overlays.
|
||||
// ACViewer's Render/TextureCache.IndexToColor does the same and never
|
||||
|
|
|
|||
|
|
@ -149,6 +149,17 @@ internal sealed class DatDatabaseWrapper : IDatDatabase
|
|||
_cache.TryAdd((typeof(T), fileId), value);
|
||||
return true;
|
||||
}
|
||||
|
||||
// TEMP diagnostic (dat-race investigation 2026-06-09, strip with fix):
|
||||
// a miss for an id whose BTree entry EXISTS is always an anomaly —
|
||||
// either Unpack returned false or the lookup flickered transiently.
|
||||
// Legit not-found probes (e.g. Portal→HighRes fallback) stay silent.
|
||||
if (_db.Tree.TryGetFile(fileId, out _))
|
||||
{
|
||||
Console.WriteLine(
|
||||
$"[dat-miss] {typeof(T).Name} 0x{fileId:X8} entry EXISTS but TryGet failed " +
|
||||
$"(thread={Environment.CurrentManagedThreadId})");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue