feat(render) Campaign FW3.2b-1: the walk frame driver
WalkFrameDriver executes one full static-content frame from the walk's turns so GPU command-buffer order equals retail's walk order. One rule does the interleaving: the accumulated OrderedDrawStream flushes through SubmitOrderedStream immediately before EVERY non-stream draw (sky, terrain slice, cell shell, punch fan, alpha barrier). Turn script, all decomp-cited and two of them corrected in review: - Interior flood: per cell IN FLOOD ORDER, shell first then contents (PView::DrawCells @0x005a4840: DrawEnvCell @0x005a4abe precedes DrawObjCellForDummies @0x005a4b0d). - Landscape: sky once, terrain per active slice, then blocks far-to-near; per cell the building turn precedes the cell's outdoor statics (DrawSortCell @0x0059f140). - Building (DrawBuilding @0x0059f2a0): the BLD probe event stays at entry, but the ENTIRE body - alpha barrier, portal passes, shell - sits inside retail's gfxobj[deg_level]!=0 gate @0x0059f2d3, and the order is FlushAlphaList @0x0059f30b -> the two-pass punch/look-in walk -> THEN the shell draw @0x0059f345. The driver review caught both the missing gate and a shell-before-punch inversion; fixed with the addresses cited. Walk seam: three additive default-implemented IWalkEventSink hooks (OnLandscapeCellTurn / OnBuildingTurn / OnBuildingShellTurn / OnPunchGeometry) - every existing sink and all FW1 conformance fixtures unchanged. WalkLandBlock gains LandblockId for the cell-id encoding. Leaf draws go through IWalkFrameLeafRenderer so FW3.2b-2 wires the real renderers and the referee suite runs on fakes + RecordingGpuDevice. Flagged for FW3.2b-2/FW4 adjudication (documented in code): FlushFartherThan(building distance) vs retail flush-all FlushAlphaList(0f); terrain-before-statics within the landscape turn. Suites: full Release build 0 warnings; Walk lane 200/1 skip; InstalledDat Walk conformance 40/1 untouched; hermetic 6,752/0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
81c6531727
commit
03f63686cc
6 changed files with 1303 additions and 7 deletions
|
|
@ -142,17 +142,33 @@ public sealed class RetailFrameWalk
|
|||
{
|
||||
continue;
|
||||
}
|
||||
// RenderDeviceD3D::DrawSortCell @0x0059f140 (decomp-
|
||||
// confirmed 2026-08-30): DrawBuilding(building) FIRST, then
|
||||
// DrawObjCell(cell) UNCONDITIONALLY — the building's turn
|
||||
// (shell + portal machinery) precedes this cell's own
|
||||
// outdoor-static turn.
|
||||
if (block.CellBuildings[cellIndex] is WalkBuilding building)
|
||||
DrawBuilding(building, activeViews, ctx, sink);
|
||||
sink.OnLandscapeCellTurn((block.LandblockId & 0xFFFF0000u) | (uint)(cellIndex + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><c>RenderDeviceD3D::DrawBuilding</c> @0x0059f2a0 at the walk
|
||||
/// level: the BLD event fires at ENTRY (before the degrade check); the
|
||||
/// portal pass walks the drawing BSP twice per active view (punch, then
|
||||
/// look-in + DrawCells on the outdoor pview); the shell pass emits no
|
||||
/// walk event.</summary>
|
||||
/// level: the BLD event fires at ENTRY (before the degrade check — the
|
||||
/// oracle traces' breakpoint sat there, so this stays unconditional for
|
||||
/// conformance). The ENTIRE rest of the body — the alpha barrier, the
|
||||
/// portal pass, and the shell draw — sits inside retail's
|
||||
/// <c>if (part->gfxobj[part->deg_level] != 0)</c> @0x0059f2d3; a
|
||||
/// degraded-out slot draws NOTHING beyond the BLD event.
|
||||
/// <c>HasGeometry</c> + a non-null <c>SelectDrawingBsp</c> together model
|
||||
/// that one gate. Inside the gate, retail's own order
|
||||
/// (@0x0059f30b–0x0059f345) is <c>D3DPolyRender::FlushAlphaList(0f)</c> →
|
||||
/// <c>CPhysicsPart::Draw(parts, 1)</c> (the PORTAL flavor — the two-pass
|
||||
/// punch/look-in walk below) → <c>CPhysicsPart::Draw(parts, 0)</c> (the
|
||||
/// plain mesh — the building's own SHELL) → flag reset: the alpha
|
||||
/// barrier and the portal pass both precede the shell draw, not follow
|
||||
/// it.</summary>
|
||||
public void DrawBuilding(
|
||||
WalkBuilding building, WalkPortalView activeViews,
|
||||
IRetailFrameWalkContext ctx, IWalkEventSink sink)
|
||||
|
|
@ -167,8 +183,15 @@ public sealed class RetailFrameWalk
|
|||
degradeMultiplier: DegradeMultiplier);
|
||||
if (bsp is null) return;
|
||||
|
||||
// Additive (Campaign FW3.2b-1): the alpha barrier
|
||||
// (D3DPolyRender::FlushAlphaList(0f) @0x0059f30b) — gated by the
|
||||
// SAME part->gfxobj[deg_level]!=0 check as everything below it, so
|
||||
// this fires only now that both HasGeometry and the bsp lookup have
|
||||
// passed.
|
||||
sink.OnBuildingTurn(building);
|
||||
|
||||
int viewCount = Math.Max(activeViews.ViewCount, 0);
|
||||
var passSink = new PortalPassSink(sink);
|
||||
var passSink = new PortalPassSink(building, sink);
|
||||
Vector3 viewpoint = ctx.ViewpointInBuilding(building);
|
||||
for (int v = 0; v < viewCount; v++)
|
||||
{
|
||||
|
|
@ -182,6 +205,12 @@ public sealed class RetailFrameWalk
|
|||
(portalRef, pass) => WalkBuildingPortals.DrawPortal(
|
||||
_outdoorPView, building, portalRef, pass, ctx, passSink));
|
||||
}
|
||||
|
||||
// Additive (Campaign FW3.2b-1): CPhysicsPart::Draw(parts, 0)
|
||||
// @0x0059f331 — the building's own shell mesh — runs AFTER the
|
||||
// portal walk completes (CPhysicsPart::Draw(parts, 1) just above),
|
||||
// not before it.
|
||||
sink.OnBuildingShellTurn(building);
|
||||
}
|
||||
|
||||
private void EmitDrawCells(WalkPView pview, IWalkEventSink sink)
|
||||
|
|
@ -204,13 +233,17 @@ public sealed class RetailFrameWalk
|
|||
ctx.GetVisible(id)?.PopView();
|
||||
}
|
||||
|
||||
private sealed class PortalPassSink(IWalkEventSink sink)
|
||||
private sealed class PortalPassSink(WalkBuilding building, IWalkEventSink sink)
|
||||
: WalkBuildingPortals.IWalkPortalPassSink
|
||||
{
|
||||
public void OnPunch(WalkPolygon polygon)
|
||||
{
|
||||
// The far-Z punch is a depth-only GPU submission (FW2's ordered
|
||||
// stream); the oracle traces do not log it.
|
||||
// stream); the oracle traces do not log it. Additive (Campaign
|
||||
// FW3.2b-1): forward to the richer sink so a driver can flush +
|
||||
// draw the punch fan — building-local space, world transform is
|
||||
// the driver's job (WalkProductionFrameContext-style lookup).
|
||||
sink.OnPunchGeometry(building, polygon);
|
||||
}
|
||||
|
||||
public void OnDrawCells(WalkPView pview)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue