From cbba71f8a9a36aa488c6b3d1d231b3b41e218435 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 9 Jun 2026 21:52:01 +0200 Subject: [PATCH] =?UTF-8?q?diag(render):=20#105=20round=202=20=E2=80=94=20?= =?UTF-8?q?tripwires=20on=20the=20upload/registration=20loss=20paths?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Live session evidence narrowed #105 decisively: a wall section rendered as the sky/clear color from session start, HAD collision (cell + physics fully loaded), zero round-1 tripwires fired (all dat reads succeeded), and the hole showed terrain or clear color depending on camera angle. So the wall mesh was built and then lost between mesh-build and draw. New tripwires cover the loss candidates in that window (all print ONLY on anomaly): - [geom-null] ProcessQueueAsync EnvCell branch resolved null, with the failing sub-step (prepare-null / cellstruct-missing / env-read-failed) — a null here means the DEDUPLICATED cell geometry never renders for ANY cell that shares it, and nothing retries (RegisterCell fire-and-forgets the task). - [geom-misroute] an EnvCell geom id (bit 33) whose pending request vanished fell through to the generic path, where its hash-derived low bits resolve to nothing -> silent null. - [up-null] UploadGfxObjMeshData returned null and the EMPTY substitute was cached in _renderData forever (permanently invisible). Pair with the existing one-shot draw-side audit (ACDREAM_A8_AUDIT=1, light: one line per unique cell/geom pair, prints renderData=null + bindless-handle status) for full attribution on the next occurrence. Co-Authored-By: Claude Fable 5 --- .../Rendering/Wb/ObjectMeshManager.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/AcDream.App/Rendering/Wb/ObjectMeshManager.cs b/src/AcDream.App/Rendering/Wb/ObjectMeshManager.cs index baa01cf5..03b7dd61 100644 --- a/src/AcDream.App/Rendering/Wb/ObjectMeshManager.cs +++ b/src/AcDream.App/Rendering/Wb/ObjectMeshManager.cs @@ -500,10 +500,25 @@ namespace AcDream.App.Rendering.Wb { if (_dats.Portal.TryGet(envId, out var environment)) { if (environment.Cells.TryGetValue(req.CellStructure, out var cellStruct)) { data = PrepareCellStructMeshData(id, cellStruct, req.Surfaces, Matrix4x4.Identity, CancellationToken.None); + // TEMP diagnostic #105 (strip with fix): a null prep here means + // this deduplicated cell geometry will NEVER render anywhere. + if (data == null) + Console.WriteLine($"[geom-null] prepare-null geom=0x{id:X10} env=0x{envId:X8} cs=0x{req.CellStructure:X4}"); } + else { + Console.WriteLine($"[geom-null] cellstruct-missing geom=0x{id:X10} env=0x{envId:X8} cs=0x{req.CellStructure:X4}"); + } + } + else { + Console.WriteLine($"[geom-null] env-read-failed geom=0x{id:X10} env=0x{envId:X8}"); } } else { + // TEMP diagnostic #105 (strip with fix): an EnvCell geom id (bit 33) + // whose pending request vanished gets misrouted to the generic path, + // where its hash-derived low bits resolve to nothing -> silent null. + if ((id & 0x2_0000_0000UL) != 0) + Console.WriteLine($"[geom-misroute] envcell geom 0x{id:X10} had no pending request — generic path will null it"); // If it's a direct setup or gfxobj, make sure background loads don't abort half-way data = PrepareMeshData(id, isSetup, CancellationToken.None); } @@ -683,6 +698,9 @@ namespace AcDream.App.Rendering.Wb { var renderData = UploadGfxObjMeshData(meshData); if (renderData == null) { + // TEMP diagnostic #105 (strip with fix): the empty substitute is cached in + // _renderData forever -> the object exists but never draws (invisible walls). + Console.WriteLine($"[up-null] upload returned null for 0x{meshData.ObjectId:X10} — caching EMPTY render data (permanently invisible)"); renderData = new ObjectRenderData(); }