From d4b5c71e66e99484eceb1dd8ca6ffd5994f09eff Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 10 Jun 2026 12:14:00 +0200 Subject: [PATCH] =?UTF-8?q?fix(render):=20re-land=20near=20plane=200.1m=20?= =?UTF-8?q?(retail=20Render::znear)=20=E2=80=94=20#110=20resolved,=20close?= =?UTF-8?q?s=20the=20=C2=A74=20corner=20see-through;=20close=20#105/#110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 137b4f2 payload, re-landed now that #110 is resolved: the missing-indoor- textures correlation was the pre-existing #105 staged-texture-flush drop (fixed in c787201), not a near-plane mechanism. znear=0.1 merely raised #105's trigger probability — a closer near plane makes close-up geometry newly visible, inflating per-frame prepare/upload pressure indoors and growing the never-flushed tail. Exactly the handoff's only-credible-link hypothesis, verified instead of assumed. Retail: Render::SetFOVRad sets znear=0.1 flat (decomp :342173, initializer :1101867). 0.1 < the 0.3m camera-collision sphere, so a wall the collided eye presses against no longer falls inside the near plane — the §4 corner see-through-wall closes. Verification on the 0.1 arm (the arm that struck 2-of-3 on 2026-06-10): nearplane-reland-1.log — [tex-flush] after=0 on all 45 lines, 68,291 [shell] lines with zero zh>0 batches, all four dat tripwires silent, no [wb-error]. ISSUES.md: #105 + #110 moved to Recently closed with root cause + evidence. Pending user re-gate: corner press (wall stays solid) + distance scan for z-shimmer (none expected; retail ships 0.1 with D24). Co-Authored-By: Claude Fable 5 --- docs/ISSUES.md | 116 ++++++++---------- src/AcDream.App/Rendering/ChaseCamera.cs | 4 +- src/AcDream.App/Rendering/FlyCamera.cs | 4 +- src/AcDream.App/Rendering/OrbitCamera.cs | 4 +- .../Rendering/RetailChaseCamera.cs | 20 +-- 5 files changed, 66 insertions(+), 82 deletions(-) diff --git a/docs/ISSUES.md b/docs/ISSUES.md index 58170602..89d30c33 100644 --- a/docs/ISSUES.md +++ b/docs/ISSUES.md @@ -44,48 +44,6 @@ Copy this block when adding a new issue: --- -## #105 — Intermittent silent dat-load failure: white/missing cottage walls until relaunch - -**Status:** OPEN -**Severity:** HIGH -**Filed:** 2026-06-09 -**Component:** render, dat, streaming - -**Description:** Intermittently (twice user-confirmed: once under heavy probe logging -2026-06-08, once on a completely clean launch 2026-06-09), the Holtburg cottage wall surfaces -render as background/clear color while the cells' static objects (paintings, furniture, -windows) draw normally. Once broken, broken for the whole session — the failed result is -cached (mesh batches build once, hydration runs once). The failure has never produced a single -log line: every dat-read failure on the walls-relevant paths exits silently. - -**Root cause / status:** LARGELY SUPERSEDED BY #106 (2026-06-09 evening): the live capture -pinned "whole interior missing / enter house and see outside" to the cross-landblock outdoor -membership freeze — most "broken house" reports were that. What REMAINS under #105 is the -narrower residual observed twice earlier: a single wall section missing (sky/clear color) -**while membership and viewer cell were demonstrably correct and INDOOR** (`viewerCell=0171`, -props drawn, collision present). All data/upload/registration layers are exonerated for it: -four rounds of tripwires (`[dat-miss]`/`[tex-miss]`/`[tex-skip]`/`[cell-miss]`, -`[geom-null]`/`[geom-misroute]`/`[up-null]`, `[finalize-replace]`/`[late-register]`) were -silent across every reproduction, the dat library is exonerated (`DatConcurrencyStressTests`, -~1.1M concurrent reads), and the capture analysis shows no never-flooding building and no -empty indoor floods. The teardown dispose-during-read AccessViolation was fixed nearby -(`8fadf77`). Known-benign noise: `[up-null]` for `0x010002B4`/`0x010008A8` (deterministic, -legitimately empty meshes). If the residual reproduces, the remaining suspects are the -draw-level clip path (the §4 edge-on clip family) — note `BuildFromExterior` has NO pv-trace -hook yet (add one for attribution). Keep all tripwires until this closes. - -**Files:** `src/AcDream.App/Rendering/Wb/ObjectMeshManager.cs` (texture chains), -`src/AcDream.App/Rendering/Wb/DatCollectionAdapter.cs` (`DatDatabaseWrapper.TryGet`), -`src/AcDream.App/Rendering/TextureCache.cs` (`DecodeFromDats`), -`src/AcDream.App/Rendering/GameWindow.cs` (`BuildInteriorEntitiesForStreaming` hydration). - -**Research:** `docs/research/2026-06-09-dat-reader-thread-safety-investigation.md`. - -**Acceptance:** the next white-wall occurrence is attributed by a tripwire line (or by their -collective silence, pointing GL-side); the attributed root cause is fixed; walls survive 10+ -launches including heavy-load ones. Tripwires can then be stripped (or kept as permanent -anomaly logging — decide at close). - --- ## #104 — Scene VFX particles not clipped to the PView visible cell set @@ -3768,35 +3726,59 @@ stable now; this is a draw-order/depth oscillation localized to the door surface --- -## #110 — Near plane 0.1 m (retail znear) correlates with missing indoor textures; corner see-through blocked on it - -**Status:** OPEN -**Severity:** HIGH (blocks the §4 corner see-through fix) -**Component:** render / camera projection (+ possibly texture upload / #105 interaction) - -Retail runs `Render::znear = 0.1` (decomp :342173, initializer :1101867); ours is 1.0 m. -Because the camera-collision sphere holds the eye 0.3 m from walls, the 1.0 m near plane -clips away any wall the camera presses against — the §4 "camera clipping into the wall" -corner background (user-gated 2026-06-10, unchanged by the flood fix `dac8f6a`). - -Landing 0.1 (`137b4f2`) fixed the geometry relationship but correlated with MISSING INDOOR -TEXTURES on two consecutive runs; the 1.0 bisect run immediately rendered clean, and the -change was reverted same-day. The #105 dat-miss tripwires were SILENT on the bad runs -(GL-side per the #105 protocol). No mechanism is known by which the near plane affects -texturing — candidates: (a) coincidence with the intermittent #105 (2/2-then-1/1 is a small -sample), (b) a depth-precision interaction (near 0.1 + far 5000 = 50k ratio) breaking a -depth-dependent pass indoors, (c) something in the visible-set/prepare path scaling with -the wider near frustum. Investigation: re-land 0.1 locally, reproduce, RenderDoc the -missing-texture frame; or flip-test 0.1↔1.0 over N runs to settle (a) statistically. -User question pending: did the missing textures render WHITE (upload path) or INVISIBLE -(visibility/depth)? - ---- - --- # Recently closed +## #105 — Intermittent white/missing indoor wall textures — [DONE 2026-06-10 · c787201] + +**Status:** DONE (probe-verified both directions; visual gate pending user) +**Closed:** 2026-06-10 +**Commit:** `c787201` (fix + the `ACDREAM_PROBE_TEXFLUSH` apparatus) +**Component:** render (GL texture upload) + +**Root cause:** `TextureAtlasManager.AddTexture` only STAGES texture content (PBO write + +`ManagedGLTextureArray._pendingUpdates`); the actual `TexSubImage3D` copies + mipmap +regeneration happen in `ProcessDirtyUpdates`, which WB drives once per frame via +`ObjectMeshManager.GenerateMipmaps()` from its render loop (WB `GameScene.cs:975`). +GameScene is the file the N.4/O-T4 extraction replaced with `GameWindow`, so the per-frame +driver was silently dropped. Staged updates only reached the GPU as a side effect of PBO +growth; every layer staged after an array's LAST growth kept undefined `TexStorage3D` +content behind a valid resident bindless handle — white/garbage walls, `zh==0`, all dat +tripwires silent (the dat→decode→stage side had delivered correctly). Only +`ObjectRenderBatch.BindlessTextureHandle` consumers were affected (EnvCellRenderer cell +shells = indoor walls); entities resolve via `TextureCache` (immediate) and terrain via +`TerrainAtlas` (immediate) — which is why only indoor walls ever struck. Intermittency = +background decode-completion order shuffling which textures land in the never-flushed tail. + +**Fix:** `WbMeshAdapter.Tick()` now calls `GenerateMipmaps()` after the staged-upload +drain (Tick runs before all draw passes — the WB-equivalent position). + +**Evidence:** pre-fix `texflush-prefix.log`: pending updates climb 0→48→…→142 and park at +126 across 34/34 atlas arrays forever at standstill. Post-fix `texflush-postfix.log` + +`nearplane-reland-1.log`: `after=0` on every line. The earlier exonerations (dat reads +safe, membership healthy, "not the probes") all stand — this was the predicted +"between staging and the draw" GL-side loss. + +**Tripwires:** the four dat-side tripwires stay (permanent anomaly logging); +`ACDREAM_PROBE_TEXFLUSH` stays env-gated (zero cost off). + +## #110 — Near plane 0.1 m vs missing indoor textures — [DONE 2026-06-10 · c787201 + re-land] + +**Status:** DONE (mechanism resolved; near plane exonerated and re-landed) +**Closed:** 2026-06-10 +**Component:** render / camera projection + +**Resolution:** the missing-texture correlation was the pre-existing #105 +(staged-texture-flush drop, see above), NOT a near-plane mechanism. `znear=0.1` merely +raised #105's trigger probability exactly as the handoff's only-credible-link predicted: +a closer near plane makes close-up geometry newly visible → more prepare/upload pressure +indoors → a larger never-flushed tail. With #105 fixed, retail `Render::znear = 0.1` +(decomp :342173, initializer :1101867) is re-landed on all four cameras — closing the §4 +corner see-through (the 0.3 m-collided eye no longer near-clips the pressed wall). +User re-gate: corner press (wall stays solid) + distance scan for z-shimmer (none +expected; retail ships 0.1 with D24). + ## #106 — Outdoor membership freezes at landblock boundaries — [DONE 2026-06-09 · 7078264 + 23adc9c + 6dbbf95 + e6913ac] **Status:** DONE (user-verified: collision + solid walls everywhere; probe-verified crossings) diff --git a/src/AcDream.App/Rendering/ChaseCamera.cs b/src/AcDream.App/Rendering/ChaseCamera.cs index c5a2a5d6..f58476f2 100644 --- a/src/AcDream.App/Rendering/ChaseCamera.cs +++ b/src/AcDream.App/Rendering/ChaseCamera.cs @@ -59,9 +59,9 @@ public sealed class ChaseCamera : ICamera public Matrix4x4 View => Matrix4x4.CreateLookAt(Position, _lookAt, Vector3.UnitZ); - // Near plane: retail is 0.1 m, parked pending #110 (see RetailChaseCamera.Projection). + // Near plane 0.1 m = retail Render::znear (see RetailChaseCamera.Projection). public Matrix4x4 Projection => - Matrix4x4.CreatePerspectiveFieldOfView(FovY, Aspect, 1f, 5000f); + Matrix4x4.CreatePerspectiveFieldOfView(FovY, Aspect, 0.1f, 5000f); /// /// Update the camera position to follow the player. diff --git a/src/AcDream.App/Rendering/FlyCamera.cs b/src/AcDream.App/Rendering/FlyCamera.cs index 36ef9e6f..49a5341b 100644 --- a/src/AcDream.App/Rendering/FlyCamera.cs +++ b/src/AcDream.App/Rendering/FlyCamera.cs @@ -32,9 +32,9 @@ public sealed class FlyCamera : ICamera } } - // Near plane: retail is 0.1 m, parked pending #110 (see RetailChaseCamera.Projection). + // Near plane 0.1 m = retail Render::znear (see RetailChaseCamera.Projection). public Matrix4x4 Projection - => Matrix4x4.CreatePerspectiveFieldOfView(FovY, Aspect, 1f, 5000f); + => Matrix4x4.CreatePerspectiveFieldOfView(FovY, Aspect, 0.1f, 5000f); /// /// Integrate position for one frame based on WASD + vertical keys. diff --git a/src/AcDream.App/Rendering/OrbitCamera.cs b/src/AcDream.App/Rendering/OrbitCamera.cs index acf67d9c..358dc9c2 100644 --- a/src/AcDream.App/Rendering/OrbitCamera.cs +++ b/src/AcDream.App/Rendering/OrbitCamera.cs @@ -23,7 +23,7 @@ public sealed class OrbitCamera : ICamera } } - // Near plane: retail is 0.1 m, parked pending #110 (see RetailChaseCamera.Projection). + // Near plane 0.1 m = retail Render::znear (see RetailChaseCamera.Projection). public Matrix4x4 Projection - => Matrix4x4.CreatePerspectiveFieldOfView(FovY, Aspect, 1f, 5000f); + => Matrix4x4.CreatePerspectiveFieldOfView(FovY, Aspect, 0.1f, 5000f); } diff --git a/src/AcDream.App/Rendering/RetailChaseCamera.cs b/src/AcDream.App/Rendering/RetailChaseCamera.cs index 77257919..553e977c 100644 --- a/src/AcDream.App/Rendering/RetailChaseCamera.cs +++ b/src/AcDream.App/Rendering/RetailChaseCamera.cs @@ -38,16 +38,18 @@ public sealed class RetailChaseCamera : ICamera public float Aspect { get; set; } = 16f / 9f; public float FovY { get; set; } = MathF.PI / 3f; public Matrix4x4 View { get; private set; } = Matrix4x4.Identity; - // ⚠️ Near plane SHOULD be retail Render::znear = 0.1 m (decomp :342173/:1101867), and - // must eventually be smaller than the 0.3 m camera-collision sphere — at 1.0 m a wall - // the collided eye sits 0.3 m from falls INSIDE the near plane and is clipped away - // (the §4 corner see-through, user-gated 2026-06-10). The 0.1 change was landed - // (137b4f2) and REVERTED the same day: two consecutive runs lost indoor textures on - // 0.1 and recovered on the 1.0 bisect run. Mechanism not yet understood (a near-plane - // change shouldn't touch texturing; the intermittent #105 may have coincided). Issue - // #110 tracks the investigation — do not re-land 0.1 without it. + // Near plane = retail Render::znear = 0.1 m (decomp :342130/:342173/:1101867 — + // Render::SetFOVRad sets 0.1 flat; the legacy set_vdst variant is max(0.1, vdst·0.25)). + // MUST be smaller than the 0.3 m camera-collision sphere (PhysicsCameraCollisionProbe. + // ViewerSphereRadius): with a 1.0 m near, a wall the collided eye sits 0.3 m from + // falls INSIDE the near plane and is clipped away — pressing the camera into a corner + // let you see straight through the wall (§4 corner residual). History: 0.1 landed + // (137b4f2), was reverted (8bd3492) after correlating with missing indoor textures, + // and re-landed once #110 resolved: the textures were the pre-existing #105 + // staged-texture-flush drop (WbMeshAdapter.Tick), and 0.1 merely raised its trigger + // probability by making more close-up geometry visible (more uploads in flight). public Matrix4x4 Projection => - Matrix4x4.CreatePerspectiveFieldOfView(FovY, Aspect, 1f, 5000f); + Matrix4x4.CreatePerspectiveFieldOfView(FovY, Aspect, 0.1f, 5000f); // ── Public tunables (per-instance) ──────────────────────────────