#!/usr/bin/env python3 """Run the engine's own preset L stages on a captured launch and compare them with its outputs. usage: test_l.py enc0|dec0 CAPTURE_DIR FRAME WORK_DIR KVK [repeats] enc0: layer_m.comp KIND 3 (features, embedding, block, merge) against rrlite_enc0_4x4_mv*_*: the block output (dec0's skip input), the merged tokens (the network's input) and the three motion surfaces dec0: layer_m.comp KIND 4 (expand, block, head) against rrlite_dec0_4x4: its four surfaces CAPTURE_DIR as for test_enc0_m.py (replay/ before each launch, dump/ after it, filter `rrlite_`). KVK is vulkan/kvk built with its `bindings` manifest line. The half-resolution previous result (texture 152) is not in the dumps: enc0 uses WORK_DIR/half-prev.bin if it exists (zeros otherwise), which only matters after the first frame. """ import glob, os, re, struct, subprocess, sys import numpy as np HERE = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, HERE) import l_model as lm import model_enc3 as me from test_m import pack_layer, defines, token_codes, report def launch(cap, kernel_re, frame): """(sequence number, replay dir, dumped resources by parameter offset) of the frame's launch of the kernel""" names = sorted({re.match(r'launch-(\d+)-(.*)-arg', os.path.basename(f)).groups() for f in glob.glob(f'{cap}/dump/launch-*-arg*')}) hits = [(int(s), k) for s, k in names if re.fullmatch(kernel_re, k)] if len(hits) <= frame: raise SystemExit(f'no launch of {kernel_re} for frame {frame}') seq, k = hits[frame] res = {int(re.search(r'-arg(\d+)-', f).group(1)): f for f in glob.glob(f'{cap}/dump/launch-{seq:03d}-{k}-arg*')} return seq, k, f'{cap}/replay/replay-{seq:06d}-{k}', res class Replay: def __init__(self, d): self.P = open(d + '/args.bin', 'rb').read() self.allocs = {} for line in open(d + '/manifest.txt'): q = line.split() if q and q[0] == 'alloc': self.allocs[int(q[1])] = (int(q[2], 16), np.fromfile(f'{d}/alloc-{q[1]}.bin', np.uint8)) def at(self, ptr): """the replayed allocation bytes from address ptr on""" a, b = next((a, b) for a, b in self.allocs.values() if a <= ptr < a + b.size) return b[ptr - a:] def q(self, o): return struct.unpack_from(' 6 else '1' os.makedirs(work, exist_ok=True) {'enc0': enc0, 'dec0': dec0}[stage](cap, frame, work, kvk, reps)