diag(render): composite-warmup stall probe for the session-3 tunnel hang
The 2026-07-29 Coldeve session 3 stuck the player in the portal tunnel forever: generation 2 (Town Network, 0x00070156) published render but composites/collision never became ready, and the reveal latch correctly held the tunnel. The composite warmup queue in WbDrawDispatcher has exactly two permanent-stall shapes - a GfxObj id that never resolves (silent load failure, e.g. custom-server content absent from the baked pak) or an upload budget that never reopens - and they are indistinguishable from the reveal log alone. ACDREAM_PROBE_REVEAL=1 (NetDiagnostics.ProbeReveal) now emits one [composite-warmup] STALL line per second while warmup blocks a reveal: pending count, queue depth, scan state, upload-budget gate, and the first four pending GfxObj ids. Zero cost when off. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
d6a2e595c8
commit
b2b5e3d54a
2 changed files with 57 additions and 0 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
@ -228,6 +229,50 @@ public sealed partial class WbDrawDispatcher : IDisposable
|
||||||
+ (_compositeWarmupScanComplete ? 0 : entities.Count - _compositeWarmupScanIndex);
|
+ (_compositeWarmupScanComplete ? 0 : entities.Count - _compositeWarmupScanIndex);
|
||||||
CompositeTexturesReady = _compositeWarmupScanComplete
|
CompositeTexturesReady = _compositeWarmupScanComplete
|
||||||
&& _compositeWarmupQueue.Count == 0;
|
&& _compositeWarmupQueue.Count == 0;
|
||||||
|
if (!CompositeTexturesReady
|
||||||
|
&& AcDream.Core.Net.NetDiagnostics.ProbeReveal)
|
||||||
|
{
|
||||||
|
ProbeRevealWarmupStall();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #260 probe: while composite warmup blocks a reveal, name the stall once
|
||||||
|
// per second. The two permanent-stall shapes — a GfxObj id that never
|
||||||
|
// resolves (silent load failure, e.g. custom-server content missing from
|
||||||
|
// the baked pak) versus an upload budget that never reopens — are
|
||||||
|
// otherwise indistinguishable from the reveal log's composites=False.
|
||||||
|
private long _probeWarmupLastEmitTs;
|
||||||
|
|
||||||
|
private void ProbeRevealWarmupStall()
|
||||||
|
{
|
||||||
|
long now = Stopwatch.GetTimestamp();
|
||||||
|
if (_probeWarmupLastEmitTs != 0
|
||||||
|
&& now - _probeWarmupLastEmitTs < Stopwatch.Frequency)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_probeWarmupLastEmitTs = now;
|
||||||
|
|
||||||
|
var pendingIds = new System.Text.StringBuilder();
|
||||||
|
int listed = 0;
|
||||||
|
foreach (WorldEntity entity in _compositeWarmupQueue)
|
||||||
|
{
|
||||||
|
if (listed >= 4)
|
||||||
|
break;
|
||||||
|
ulong gfxObjId = entity.MeshRefs.Count > 0
|
||||||
|
? entity.MeshRefs[0].GfxObjId
|
||||||
|
: 0;
|
||||||
|
if (listed > 0)
|
||||||
|
pendingIds.Append(',');
|
||||||
|
pendingIds.Append($"0x{gfxObjId:X8}");
|
||||||
|
listed++;
|
||||||
|
}
|
||||||
|
Console.WriteLine(
|
||||||
|
$"[composite-warmup] STALL pending={LastCompositeWarmupPendingCount}"
|
||||||
|
+ $" queue={_compositeWarmupQueue.Count}"
|
||||||
|
+ $" scanComplete={_compositeWarmupScanComplete}"
|
||||||
|
+ $" uploadOpen={_textures.CanStartCompositeUpload}"
|
||||||
|
+ $" firstPending=[{pendingIds}]");
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static bool RequiresCompositeWarmupRebuild(
|
internal static bool RequiresCompositeWarmupRebuild(
|
||||||
|
|
|
||||||
|
|
@ -33,4 +33,16 @@ public static class NetDiagnostics
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool ProbeNet { get; set; } =
|
public static bool ProbeNet { get; set; } =
|
||||||
Environment.GetEnvironmentVariable("ACDREAM_PROBE_NET") == "1";
|
Environment.GetEnvironmentVariable("ACDREAM_PROBE_NET") == "1";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <c>ACDREAM_PROBE_REVEAL=1</c> — #260 reveal-stall probe: while a
|
||||||
|
/// reveal destination's composite warmup is incomplete, emit one
|
||||||
|
/// <c>[composite-warmup]</c> line per second naming the pending queue
|
||||||
|
/// depth, scan state, upload-budget gate, and the first few unresolved
|
||||||
|
/// GfxObj ids. The two permanent-stall shapes (a mesh id that never
|
||||||
|
/// resolves vs. an upload budget that never reopens) are otherwise
|
||||||
|
/// indistinguishable and invisible.
|
||||||
|
/// </summary>
|
||||||
|
public static bool ProbeReveal { get; set; } =
|
||||||
|
Environment.GetEnvironmentVariable("ACDREAM_PROBE_REVEAL") == "1";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue