diff --git a/engine/README.md b/engine/README.md index 947ffce..e0454d6 100644 --- a/engine/README.md +++ b/engine/README.md @@ -83,6 +83,26 @@ It fails for missing/wrong-sized results, nonfinite values, or PSNR below its th `test_k.py --chain` remains available for isolated-layer diagnosis; it now selects the first launch consistently and fails on dispatch errors rather than continuing with a broken chain. +## Models on the user's machine (install.sh) + +A release's `install.sh` builds every model the shim loads, from the user's own DLLs, with +`d4r/tools/build-engine-models.sh` (`packaging/build_engine_models.sh`; `scripts/stage_engine_kit.sh` puts it and +d4r's compilers, shaders, the D3D12 harness and glslang into the release): + +- Ray Reconstruction needs no capture. `nvngx_dlssd.dll` 310.9.1 holds presets D and E (the kernels and weights of + 310.7) and F. `engine/rr/build_native_model.sh --dll DLL D|E OUT` and `engine/compile_rr2.py --dll DLL OUT + --ptx-dir DIR` take the PTX from the DLL (`kernels/tools/extract_dlss_ptx.py`), the weights as before + (`dll_weights.py`, `rr2_pack.py`) and what the capture used to supply from the DLL too: the argument-block + constants (`engine/rr/rr_templates.py`, `rr2_templates.py`, which replays the routine that builds NGX's model + description), encoder 0's second table of preset F and its arena regions. Built this way, D, E and F are + byte-identical to the capture-built models (every file, and `d4r-rr`'s outputs on the reference inputs). +- Super Resolution weights are packed inside `nvngx_dlss.dll`; they are read where NGX unpacks them. The harness + renders one frame per preset (11, 13, 12) through the release's own d4r folder under GE-Proton with + `D4R_CUDA_REPLAY_DUMP_DIR` set; `extract_k.py`, `prepare_k.py --lut-only` and `compile_k.py` / `compile_m.py` + build K, M and L from that, and `--ldr` their LDR variants from the same frame (NGX's HDR and LDR stages read the + same weights). About a minute per preset, ~280 MB of dumps that are deleted afterwards. The results are identical + to the models built from full captures. + ## Ordinary frames, without a capture Create a JSON description with raw linear HDR color, inverse depth, and render-resolution motion vectors: diff --git a/engine/compile_m.py b/engine/compile_m.py index 94156b4..b35e38c 100644 --- a/engine/compile_m.py +++ b/engine/compile_m.py @@ -50,7 +50,7 @@ def blob_of(directory, ptr_offset=0): def main(): ap = argparse.ArgumentParser(description=__doc__) ap.add_argument('capture'); ap.add_argument('output', type=Path); ap.add_argument('--frame', type=int, default=0) - ap.add_argument('--ldr', action='store_true', help="NGX's *_ldr_* stages, for games without the HDR flag (capture such a frame)") + ap.add_argument('--ldr', action='store_true', help="NGX's *_ldr_* stages, for games without the HDR flag (the weights may come from an HDR capture)") ap.add_argument('--hip', type=Path, metavar='KERNEL_DIR', help='also package the network for the native HIP layers: the layer ' 'weights as NGX uploads them (hipnet.bin) and the rrlite_*_4x4.hsaco kernels of KERNEL_DIR (kernels/build.sh output)') a = ap.parse_args() @@ -60,6 +60,10 @@ def main(): if len(d) <= a.frame: raise ValueError(f'no launch of {kernel} for frame {a.frame}') return d[a.frame] R = 'ldr' if a.ldr else 'hdr' + # NGX's HDR and LDR stages read the same weights and constants (RE Requiem's m / m-ldr and l / l-ldr packages, + # built from separate captures, are identical but for the shaders): an LDR model can come from an HDR capture + if a.ldr and not glob.glob(f'{a.capture}/replay/replay-*-rrlite_enc0_4x4_mvlo_ldr*'): + R = 'hdr' preset_l = bool(glob.glob(f'{a.capture}/replay/replay-*-rrlite_enc0_4x4_mvlo_{R}')) if preset_l == bool(glob.glob(f'{a.capture}/replay/replay-*-rrlite_enc0_4x4_mvlo_{R}_folded')): raise ValueError(f'the capture must hold the input stage of exactly one of preset M or L ({R})') diff --git a/engine/prepare_k.py b/engine/prepare_k.py index a3e0354..087f649 100644 --- a/engine/prepare_k.py +++ b/engine/prepare_k.py @@ -2,7 +2,9 @@ """Prepare a full-frame native K replay from a capture. Does not translate kernels. prepare_k.py CAPTURE_DIR OUTPUT_DIR [--frames N] [--start FRAME] -The model's reconstruction tables can be packaged using OUTPUT_DIR/lut.bin. +prepare_k.py CAPTURE_DIR OUTPUT_DIR --lut-only +The model's reconstruction tables can be packaged using OUTPUT_DIR/lut.bin. --lut-only writes only that, from the +first output launch's replay (a capture without the launch dumps: install.sh's weight dump). """ import argparse import json @@ -21,7 +23,15 @@ def main(): parser.add_argument('output', type=Path) parser.add_argument('--frames', type=int, default=0, help='0 = all captured frames') parser.add_argument('--start', type=int, default=0) + parser.add_argument('--lut-only', action='store_true', help='write only lut.bin') a = parser.parse_args() + if a.lut_only: + outputs = launches(a.capture, OUTPUT) + if not outputs: + raise ValueError('capture holds no K output launch') + a.output.mkdir(parents=True, exist_ok=True) + (a.output / 'lut.bin').write_bytes(outputs[0].allocation(280, 16 * 32768)) + return inputs, outputs = launches(a.capture, INPUT), launches(a.capture, OUTPUT) if not inputs or not outputs or len(outputs) > len(inputs): raise ValueError('capture must contain complete K input/output frame pairs')