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:
@@ -29,10 +29,10 @@ def f32(bits):
|
||||
PRIMT = {0:"POINT",1:"LINE",2:"LINE_STRIP",3:"TRIANGLE",4:"TRI_STRIP",5:"TRI_FAN",6:"SPRITE",7:"INVALID"}
|
||||
VERTS_PER = {0:1,1:2,2:2,3:3,4:3,5:3,6:2,7:0} # min verts to kick a primitive
|
||||
|
||||
def census(dump, frame_filter=None, min_prims=1, collected=None):
|
||||
def census(dump, frame_filter=None, min_prims=1, collected=None, include_untextured=False):
|
||||
d, h, events, uploads, runs, vram = collected if collected is not None else R.collect(dump, 0)
|
||||
# live GS state we latch as we walk
|
||||
prim = dict(type=7, tme=0, fst=0, abe=0, ctxt=0)
|
||||
prim = dict(type=7, tme=0, fge=0, fst=0, abe=0, ctxt=0)
|
||||
tex0 = {1:None, 2:None}
|
||||
ofx = {1:0.0, 2:0.0}; ofy = {1:0.0, 2:0.0}
|
||||
cur_st = (0.0, 0.0, 1.0) # S, T, Q
|
||||
@@ -72,7 +72,8 @@ def census(dump, frame_filter=None, min_prims=1, collected=None):
|
||||
r, v = e.reg, e.value
|
||||
if r == "PRIM":
|
||||
close()
|
||||
prim = dict(type=v&7, tme=(v>>4)&1, fst=(v>>8)&1, abe=(v>>6)&1, ctxt=(v>>9)&1)
|
||||
prim = dict(type=v&7, tme=(v>>4)&1, fge=(v>>5)&1,
|
||||
fst=(v>>8)&1, abe=(v>>6)&1, ctxt=(v>>9)&1)
|
||||
vqueue = []
|
||||
elif r == "PRMODE": # PRIM-less prim mode (rare); ignore topology change w/o reset
|
||||
pass
|
||||
@@ -94,13 +95,14 @@ def census(dump, frame_filter=None, min_prims=1, collected=None):
|
||||
z = (v>>32) & 0xFFFFFF
|
||||
else:
|
||||
z = (v>>32) & 0xFFFFFFFF
|
||||
if not prim["tme"]: # only textured draws are Ch349 candidates
|
||||
fogv = ((v>>56) & 0xFF) if r in ("XYZF2","XYZF3") else 255
|
||||
if not prim["tme"] and not include_untextured:
|
||||
continue
|
||||
if newkey() is None:
|
||||
continue
|
||||
if cur is None or cur["key"] != newkey():
|
||||
close(); open_draw()
|
||||
vtx = dict(x=x, y=y, z=z, s=cur_st[0], t=cur_st[1], q=cur_st[2], rgba=cur_rgba)
|
||||
vtx = dict(x=x, y=y, z=z, fog=fogv, s=cur_st[0], t=cur_st[1], q=cur_st[2], rgba=cur_rgba)
|
||||
cur["verts"].append(vtx); cur["nvert"] += 1
|
||||
cur["nprim"] += 1 # each kick completes one primitive in fan/strip/list
|
||||
cur["xmin"]=min(cur["xmin"],x); cur["xmax"]=max(cur["xmax"],x)
|
||||
@@ -119,9 +121,10 @@ def census(dump, frame_filter=None, min_prims=1, collected=None):
|
||||
if dr["nprim"] < min_prims: continue
|
||||
if frame_filter is not None and dr["frame"] != frame_filter: continue
|
||||
t0 = dr["tex0"]
|
||||
snap = R.snapshot_present(vram, t0["tbp"], nb=512)
|
||||
snap = (True if not dr["prim"]["tme"] else
|
||||
R.snapshot_present(vram, t0["tbp"], nb=512))
|
||||
clut = None
|
||||
if t0["psm"] in R.INDEXED_PSMS:
|
||||
if dr["prim"]["tme"] and t0["psm"] in R.INDEXED_PSMS:
|
||||
csnap = R.snapshot_present(vram, t0["cbp"], nb=1024, min_nz=64)
|
||||
clut = dict(cbp=t0["cbp"], cpsm=t0["cpsm"], cld=t0["cld"], resident=bool(csnap),
|
||||
distinct=(csnap["distinct"] if csnap else None))
|
||||
@@ -156,6 +159,10 @@ def _score(dr):
|
||||
rectangle in perspective. Reward on-screen containment + sampled-texel span, NOT guard-band area."""
|
||||
t0 = dr["tex0"]
|
||||
s = 0.0
|
||||
if not dr["prim"]["tme"]:
|
||||
return (100.0 * dr["onscreen_frac"] +
|
||||
min(dr["onscreen_area"]/200.0,120.0) +
|
||||
min(dr["nprim"],48))
|
||||
if not dr["tex_resident"]: return -1.0 # must be reconstructable
|
||||
if t0["psm"] in R.INDEXED_PSMS:
|
||||
if dr["clut"] and dr["clut"]["resident"]: s += 40.0 # indexed + resident CLUT == the real SH3 path
|
||||
@@ -204,7 +211,8 @@ def main(argv):
|
||||
def opt(n, dv=None): return argv[argv.index(n)+1] if n in argv else dv
|
||||
top = int(opt("--top","25")); minp = int(opt("--min-prims","1"))
|
||||
ff = int(opt("--frame")) if "--frame" in argv else None
|
||||
draws, h, vram = census(dump, frame_filter=ff, min_prims=minp)
|
||||
draws, h, vram = census(dump, frame_filter=ff, min_prims=minp,
|
||||
include_untextured="--include-untextured" in argv)
|
||||
print(f"# Ch349 draw census: {os.path.basename(dump)}")
|
||||
print(f"# textured draws (>= {minp} prim): {len(draws)} vram_snapshot={'present' if vram is not None else 'ABSENT'}")
|
||||
cand = [d for d in draws if d["score"] > 0]
|
||||
|
||||
Reference in New Issue
Block a user