Snapshot: fog implementation + fidelity tooling baseline (pre bilinear-clamp fix)

Per-vertex GS fog end-to-end (gs_stub emit incl. persp_emit5, gs_prim_list_feeder
XYZ2->XYZF2 on PRIM.FGE, gs_make_sh3_scheduler_fixture.py F/FGE packing), new fog
TBs, fidelity attribution tooling. Functional baseline before removing the dead
bilinear lerp8 clamps (Codex: 161-node comb loop -> -0.042ns setup fail).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-20 19:56:46 -04:00
parent ec82764bef
commit ba74bbd5aa
476 changed files with 696247 additions and 130119 deletions
+16 -3
View File
@@ -53,6 +53,10 @@ def main(argv):
def opt(n, dv=None): return argv[argv.index(n)+1] if n in argv else dv
frame = int(opt("--frame","1")); maxd = int(opt("--max-draws","100000"))
min_area = float(opt("--min-area","0"))
no_z = ("--no-z" in argv) # diagnostic: paint in submission order, last draw wins (bypass z-buffer)
dofog = ("--fog" in argv) # apply authentic GS per-vertex fog (FOGCOL=0 black => color*F/256) on FGE draws
only_tbp = int(opt("--only-tbp","-1")) # diagnostic: render only draws bound to this texture base
only_idx = int(opt("--only-idx","-1")) # diagnostic: render only the draw with this first_idx
outdir = opt("--out", os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
"captures","gs","silenthill3","extracted","recon"))
os.makedirs(outdir, exist_ok=True)
@@ -62,7 +66,9 @@ def main(argv):
d, h, events, uploads, runs, vram = collected
draws, _, _ = C.census(dump, frame_filter=frame, min_prims=1, collected=collected)
draws = [dr for dr in draws if dr["prim"]["tme"] and dr["tex0"]["psm"] in (0x13,0x00)
and dr["onscreen_area"] >= min_area]
and dr["onscreen_area"] >= min_area
and (only_tbp < 0 or dr["tex0"]["tbp"] == only_tbp)
and (only_idx < 0 or dr["first_idx"] == only_idx)]
draws.sort(key=lambda x: x["first_idx"])
print(f"[frameref] frame {frame}: {len(draws)} textured (PSMT8/CT32) draws, min_area={min_area}; "
f"replaying uploads incrementally")
@@ -97,6 +103,7 @@ def main(argv):
if kind is None: continue
tw, th = t0["tw"], t0["th"]
verts = dr["verts"]; pt = dr["prim"]["type"]
draw_fge = dofog and bool(dr["prim"].get("fge",0))
def tri(i0,i1,i2):
nonlocal painted_total
v0,v1,v2 = verts[i0],verts[i1],verts[i2]
@@ -120,8 +127,14 @@ def main(argv):
u=(S/Q)*tw; vv=(T/Q)*th
z=int(b0*v0["z"]+b1*v1["z"]+b2*v2["z"])
o=base+px
if z>=zb[o]:
zb[o]=z; fb[o]=sample(tex,pal,kind,tw,th,u,vv)+(255,); painted_total+=1
if no_z or z>=zb[o]:
rgb=sample(tex,pal,kind,tw,th,u,vv)
if draw_fge:
F=int(b0*v0["fog"]+b1*v1["fog"]+b2*v2["fog"]) # affine per-vertex fog; FOGCOL=0
if F<0: F=0
elif F>255: F=255
rgb=((rgb[0]*F)>>8, (rgb[1]*F)>>8, (rgb[2]*F)>>8)
zb[o]=z; fb[o]=rgb+(255,); painted_total+=1
if pt==4:
for i in range(2,len(verts)): tri(i-2,i-1,i)
elif pt==5: