#!/usr/bin/env python3 """Build the engine's preset M or preset L model directory from a capture of one frame. usage: compile_m.py CAPTURE_DIR OUT_DIR [--frame N] CAPTURE_DIR/replay must hold the frame's rrlite_enc0 and rrlite_dec0 launches and its ten Swin layer launches, with their weight allocations (D4R_CUDA_REPLAY_DUMP_DIR, filter `rrlite_`). A capture of preset M has the `_folded` input and expansion kernels; one of preset L (DLSS preset 12) has the unfolded ones, and gets an L model directory (offsets.bin `D4RL0002`, L_NOTES.md): the same network, layer_m.comp's L input and expansion stages, post_m.comp's L reconstruction. Writes weights8.bin (the layers' FP8 matrices in the blocked fixed-16 tile layout of test_m.pack8, with the front-end enc0/dec0 matrices plain and NGX-ordered as their own stages read them), weights16.bin (f16 vectors and the dither table), offsets.bin and the compiled shaders. The weights are values read from NVIDIA's DLSS and are not redistributable with d4r; the shaders are d4r's own. """ # D4RM0004 / D4RL0002 add active-rectangle sampling for dynamic input sizes. # D4RM0003 coupled the blocked FP8 operands, RGBA32F half-history backing and 8x64 downsample dispatch; # the previous package's shader workgroup dimensions are not interchangeable with this runtime. import argparse, glob, hashlib, json, os, struct, subprocess, sys from pathlib import Path import numpy as np HERE = Path(__file__).resolve().parent sys.path.insert(0, str(HERE)) import m_model as mm import l_model as lm import model_enc3 as me import swin_model as sm from test_m import pack_layer, defines # The network is built with this GPU's own arithmetic and two windows per wave by default (layer_m.comp M_RELAXED, WPW; # engine/README.md): the fastest build, about 1 dB further from an NVIDIA card than NVIDIA's roundings reproduced # exactly. M_EXACT=1 builds those roundings instead (bit-identical to the CUDA path); M_WPW / M_DEFS still apply. EXACT = os.environ.get('M_EXACT') == '1' FAST = [] if EXACT or '-DM_RELAXED' in os.environ.get('M_DEFS', '').split() else ['-DM_RELAXED'] FAST_WPW = [] if EXACT or os.environ.get('M_WPW') or 'WPW=' in os.environ.get('M_DEFS', '') else ['-DWPW=2'] SHADERS = {'enc1': 'm_enc1', 'enc2': 'm_enc2', 'enc3_tube': 'm_tube', 'dec2': 'm_dec2', 'dec1': 'm_dec1'} def blob_of(directory, ptr_offset=0): args = open(f'{directory}/args.bin', 'rb').read() ptr = struct.unpack_from('= 3), # 16 (the whole post_3_2 range), 12 (the compact tier: render/reconstruction <= 0.45, jitter within half a texel) for out, tile in (('post_l', 11), ('post_l_q', 16), ('post_l_c', 12)): glsl('post_m.comp', out + '.spv', ['-DPRESET_L=1', f'-DTILE_W={tile}', f'-DTILE_H={tile}'] + ldr) glsl('down_m.comp', 'down_m.spv', ldr) glsl('down_m.comp', 'down_m_rgb10.spv', ['-DOUTPUT_RGB10=1'] + ldr) if a.hip: package_hip(a, Ps) marker = a.output / 'ldr' if a.ldr: marker.write_text('1\n') elif marker.exists(): marker.unlink() for p in '01': glsl('exposure_k.comp', f'exposure_m{p}.spv', ['-DMODE=1', '-DPASS=' + p]) for stale in ('enc0_m.spv', 'dec0_m.spv', 'post_m.spv', 'post_m_q.spv', 'post_m_c.spv', 'enc0_m_planes.spv', 'dec0_m_planes.spv'): (a.output / stale).unlink(missing_ok=True) files = sorted(a.output.glob('*.bin')) + sorted(a.output.glob('*.spv')) + sorted(a.output.glob('hip/*.hsaco')) (a.output / 'model.json').write_text(json.dumps({'format': 'D4RL0002', 'preset': 'L', 'files': {str(f.relative_to(a.output)): hashlib.sha256(f.read_bytes()).hexdigest() for f in files}}, indent=1)) print(f'Compiled native preset L model in {a.output} ({blob8.size} FP8 bytes, {blob16.size} bytes of f16 data)') def package_hip(a, Ps): """hipnet.bin: "D4RMHIP1", layer count, then per layer {kernel name[32], shift x, y, token grid divisor, weight offset, weight bytes} and the weight allocations as NGX uploads them (the native kernels read that layout)""" scale = {'enc1': 1, 'enc2': 2, 'enc3_tube': 4, 'dec2': 2, 'dec1': 1} blobs, head, at = [], struct.pack('<8sI4x', b'D4RMHIP1', len(Ps)), 16 + 64 * len(Ps) for P, name in zip(Ps, mm.ORDER): w = np.ascontiguousarray(P.wbuf); pad = (-w.size) % 64 head += struct.pack('<32siiIIQQ', f'rrlite_{name}_4x4'.encode(), P.sx, P.sy, scale[name], 0, at, w.size) blobs += [w, np.zeros(pad, np.uint8)]; at += w.size + pad (a.output / 'hipnet.bin').write_bytes(head + np.concatenate(blobs).tobytes()) (a.output / 'hip').mkdir(exist_ok=True) for name in sorted(set(mm.ORDER)): src = a.hip / f'rrlite_{name}_4x4.hsaco' if not src.exists(): raise ValueError(f'{src} is missing') (a.output / 'hip' / src.name).write_bytes(src.read_bytes()) if __name__ == '__main__': main()