feat: add d4r inference engines and Windows parity tooling
Add native K/M/RR inference engines, HIP kernels, replay and validation harnesses, and Windows DLSS setup and runtime support. Include GPU profiling tools, build and packaging scripts, platform integration patches, and implementation documentation.
This commit is contained in:
1 parent
25493b3198
commit
7c5d3c9157
430 files changed
+76191
No files matched your search
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Run the engine's own K input kernel on a captured launch of NVIDIA's and compare the network input it writes.
|
||||
|
||||
usage: test_in.py CAPTURE_DIR FRAME WORK_DIR KVK [repeats]
|
||||
"""
|
||||
import glob, os, re, struct, subprocess, sys
|
||||
import numpy as np
|
||||
LDR = os.environ.get('LDR') == '1' # the *_ldr_* kernel variant and the shader's LDR path
|
||||
K = 'hiluma_engine_input_depthinv_mvlo_ldr_v2_rel' if LDR else 'hiluma_engine_input_depthinv_mvlo_hdr_v2_rel'
|
||||
cap, frame, work, kvk = sys.argv[1], int(sys.argv[2]), sys.argv[3], sys.argv[4]
|
||||
reps = sys.argv[5] if len(sys.argv) > 5 else '1'
|
||||
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||
os.makedirs(work, exist_ok=True)
|
||||
seqs = sorted({int(re.match(r'launch-(\d+)-', os.path.basename(f)).group(1)) for f in glob.glob(f'{cap}/dump/launch-*-{K}-arg*')})
|
||||
seq = seqs[frame]
|
||||
res = {}
|
||||
for f in glob.glob(f'{cap}/dump/launch-{seq:03d}-{K}-arg*'):
|
||||
m = re.search(r'-arg(\d+)-(texture|surface|buffer)-(.*)-fmt(-?\d+)\.bin$', f)
|
||||
res[int(m.group(1))] = (m.group(2), m.group(3), int(m.group(4)), f)
|
||||
P = open(f'{cap}/replay/replay-{seq:06d}-{K}/args.bin', 'rb').read()
|
||||
f2 = lambda o: struct.unpack_from('<2f', P, o)
|
||||
i2 = lambda o: struct.unpack_from('<2i', P, o)
|
||||
f1 = lambda o: struct.unpack_from('<f', P, o)[0]
|
||||
def expo_tex(off):
|
||||
if off not in res: return 1.0 # LDR: no exposure textures
|
||||
v = float(np.fromfile(res[off][3], np.float16)[0])
|
||||
return 1.0 if v == 0 else v
|
||||
F = np.float32
|
||||
a, b, c = expo_tex(208), expo_tex(200), expo_tex(216)
|
||||
f152, f158 = F(f1(144)) * F(a), F(f1(144)) * F(b)
|
||||
expo = F(f1(156)) * f158; expo = F(1) if expo == 0 else expo
|
||||
expo_in = F(f1(148)) * F(c) / f158
|
||||
ratio = f158 / f152
|
||||
blob = struct.pack('<14f', *f2(40), *f2(24), *f2(8), *f2(16), *f2(120), *f2(136), *f2(128))
|
||||
blob += struct.pack('<12i', *i2(72), *i2(80), *i2(88), *i2(96), *i2(104), *i2(112))
|
||||
blob += struct.pack('<iI4f', struct.unpack_from('<i', P, 64)[0], P[32], float(expo), float(expo_in), float(ratio), f1(160))
|
||||
open(f'{work}/params.bin', 'wb').write(blob)
|
||||
tokW = struct.unpack_from('<i', P, 64)[0]
|
||||
kind, shape, fmt, fref = res[240]
|
||||
nbytes = os.path.getsize(fref)
|
||||
tokH = 256 if tokW == 320 else None
|
||||
# IN_TEX_OVERRIDE="184=FILE,192=FILE" replaces captured textures; IN_REF compares against that file (the translated
|
||||
# reference kernel's output on the same inputs) instead of the captured buffer.
|
||||
for kv in filter(None, os.environ.get('IN_TEX_OVERRIDE', '').split(',')):
|
||||
o, fn = kv.split('='); res[int(o)] = res[int(o)][:3] + (fn,)
|
||||
fref = os.environ.get('IN_REF', fref)
|
||||
lines = [f'param {work}/params.bin']
|
||||
dims = {}
|
||||
for i, (off, filt) in enumerate(((168, 'nearest'), (176, 'linear'), (184, 'nearest'), (192, 'nearest'), (224, 'linear'))):
|
||||
kind, shape, fmt, f = res[off]; w, h, ch = (int(x) for x in shape.split('x'))
|
||||
dims[off] = (w, h)
|
||||
lines.append(f'tex {i + 1} {f} {w} {h} {ch} {32 if fmt == 32 else 16} {filt}')
|
||||
tokH = dims[224][1]
|
||||
lines.insert(1, f'grid {tokW // 8} {tokH // 8}')
|
||||
lines.append(f'outbuf {work}/out.bin {tokW * tokH * 32}')
|
||||
open(f'{work}/manifest', 'w').write('\n'.join(lines) + '\n')
|
||||
spv = f'{work}/input_k.spv'
|
||||
subprocess.run(['glslangValidator', '-V', '--target-env', 'vulkan1.3', *(['-DLDR=1'] if LDR else []), f'{HERE}/input_k.comp', '-o', spv], check=True, stdout=subprocess.DEVNULL)
|
||||
# K requires a 32-lane subgroup (the reconstruction's 2x2 "bright" quad is a subgroup shuffle and the
|
||||
# network layers use 16x16x16 cooperative matrices); wave64 changes both.
|
||||
r = subprocess.run([kvk, spv, f'{work}/manifest', reps, '32'], capture_output=True, text=True)
|
||||
if r.returncode:
|
||||
print('FAILED', r.stderr[-400:]); sys.exit(1)
|
||||
for l in r.stdout.split('\n'):
|
||||
if 'us per' in l: print(l)
|
||||
ref = np.fromfile(fref, np.float16)[:tokW * tokH * 16].astype(np.float64).reshape(tokH, tokW, 4, 4)
|
||||
got = np.fromfile(f'{work}/out.bin', np.float16)[:tokW * tokH * 16].astype(np.float64).reshape(tokH, tokW, 4, 4)
|
||||
print(f'frame {frame} (launch {seq}), tokens {tokW}x{tokH}, reset {P[32]}, exposure {float(expo):.4g} / {float(expo_in):.4g}, ratio {float(ratio):.6g}')
|
||||
for ch, name in enumerate(('current luma', 'history luma', 'token feature', 'mismatch')):
|
||||
a, b = ref[..., ch], got[..., ch]
|
||||
d = np.abs(a - b); peak = max(np.abs(a).max(), 1e-9)
|
||||
print(f' {name:14s} psnr {10 * np.log10(peak ** 2 / max((d ** 2).mean(), 1e-30)):6.1f} dB max |diff| {d.max():.4g} mean |ref| {np.abs(a).mean():.4g} non-finite {int((~np.isfinite(b)).sum())}')
|
||||
Reference in new issue
Block a user