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:
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Build one scheduler bootlet that preloads the distinct CLUTs required by several fixture tags.
|
||||
|
||||
Usage: gs_merge_scheduler_bootlets.py <output-tag> <input-tag> [<input-tag> ...]
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||
ROOT = os.path.normpath(os.path.join(HERE, ".."))
|
||||
DATA = os.path.join(ROOT, "sim", "data", "top_psmct32_raster_demo")
|
||||
sys.path.insert(0, DATA)
|
||||
import bake
|
||||
|
||||
RAM_QWORDS = 512
|
||||
HEADER_QWORDS = 16
|
||||
FBW = 10
|
||||
FBPXW = 640
|
||||
FBH = 480
|
||||
|
||||
|
||||
def read_payload(tag):
|
||||
path = os.path.join(DATA, f"payload_sh3_{tag}.mem")
|
||||
with open(path) as f:
|
||||
lines = f.readlines()
|
||||
header = next((line for line in lines if line.startswith("//")), "")
|
||||
match = re.search(r"QWC=(\d+)", header)
|
||||
if not match:
|
||||
raise ValueError(f"{path}: missing QWC metadata")
|
||||
cbp_match = re.search(r"CBPs \[([^]]*)\]", header)
|
||||
if not cbp_match:
|
||||
raise ValueError(f"{path}: missing CBP metadata")
|
||||
cbps = [int(x.strip()) for x in cbp_match.group(1).split(",") if x.strip()]
|
||||
words = [int(line.strip(), 16) for line in lines if line.strip() and not line.startswith("//")]
|
||||
if len(words) != RAM_QWORDS:
|
||||
raise ValueError(f"{path}: expected {RAM_QWORDS} qwords, got {len(words)}")
|
||||
qwc = int(match.group(1))
|
||||
if qwc > RAM_QWORDS - HEADER_QWORDS:
|
||||
raise ValueError(f"{path}: QWC {qwc} exceeds payload capacity")
|
||||
return qwc, cbps, words[HEADER_QWORDS:HEADER_QWORDS + qwc]
|
||||
|
||||
|
||||
def main(argv):
|
||||
if len(argv) < 4:
|
||||
print(__doc__.strip())
|
||||
return 2
|
||||
output_tag, input_tags = argv[1], argv[2:]
|
||||
active = []
|
||||
seen_cbps = set()
|
||||
for tag in input_tags:
|
||||
qwc, cbps, words = read_payload(tag)
|
||||
for cbp in set(cbps):
|
||||
if cbp in seen_cbps:
|
||||
raise ValueError(f"duplicate relocated CBP {cbp}: fixture {tag} aliases an earlier input")
|
||||
seen_cbps.add(cbp)
|
||||
if len(words) != qwc:
|
||||
raise ValueError(f"payload word count mismatch for {tag}")
|
||||
active.extend(words)
|
||||
if len(active) > RAM_QWORDS - HEADER_QWORDS:
|
||||
raise ValueError(f"combined QWC {len(active)} exceeds {RAM_QWORDS - HEADER_QWORDS}")
|
||||
|
||||
payload_name = f"payload_sh3_{output_tag}.mem"
|
||||
bios_name = f"bios_sh3_{output_tag}.mem"
|
||||
with open(os.path.join(DATA, payload_name), "w") as f:
|
||||
f.write(f"// combined scheduler CLUT preload tags={input_tags} CBPs={sorted(seen_cbps)} QWC={len(active)}. gitignored.\n")
|
||||
for _ in range(HEADER_QWORDS):
|
||||
f.write("00000000000000000000000000000000\n")
|
||||
for word in active:
|
||||
f.write(f"{word:032x}\n")
|
||||
for _ in range(RAM_QWORDS - HEADER_QWORDS - len(active)):
|
||||
f.write("00000000000000000000000000000000\n")
|
||||
display1_hi = ((FBH - 1) << 12) | (FBPXW - 1)
|
||||
bake.write_bios_mem(
|
||||
bios_name,
|
||||
bake.build_textured_demo_bootlet_disp(len(active), display1_hi, FBW),
|
||||
f"combined scheduler CLUT preload tags={input_tags} QWC={len(active)} DISPLAY1={FBPXW}x{FBH}. gitignored.",
|
||||
)
|
||||
print(f"[bootlet] emitted {bios_name} + {payload_name}: QWC={len(active)} CBPs={sorted(seen_cbps)}")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main(sys.argv))
|
||||
Reference in New Issue
Block a user