Ray Reconstruction's eleven DLSS-D Swin layers still run ZLUDA's compile of NVIDIA's PTX; at 1280x720 -> 3840x2160 on gfx1201 they are 30.2 of a 31.6 ms frame. The denoiser's high-fidelity output kernel is the first one with a native replacement: make_ptx.py replaces its whole-texel RGBA16F store (sust.b.2d.v4.b16.zero) through d4r_sust_v4b16, kernels/build.sh builds the pair as the `rr` family, and packaging builds it into every target folder including the RDNA4 FP8 ones. Both libraries define modules named cuda_dldn_engine_*, with different text, so one manifest cannot take the union of their hashes: kernel_manifest.py now takes the denoiser DLL as --rr-dll and lets only its hashes authorize a cuda_dldn_engine_* binary, and package_release.sh passes it when the denoiser is bundled. Verified in the D3D12 harness with Ray Reconstruction at 1280x720 -> 3840x2160: the output kernel drops from 1.44 to 1.00 ms/frame and the 66 MB raw output is byte-identical to the run with every kernel translated. docs/native-kernels.md gains the denoiser family, the per-kernel cost table and the instruction counts that show why the Swin layers are the remaining work.
81 lines
3.6 KiB
Python
81 lines
3.6 KiB
Python
#!/usr/bin/env python3
|
|
"""Write the d4r-kernels.txt manifest of a native kernel directory.
|
|
|
|
usage: kernel_manifest.py KERNEL_DIR [NVNGX_DLSS_DLL...] [--rr-dll NVNGX_DLSSD_DLL]
|
|
|
|
For every NAME.hsaco in KERNEL_DIR, finds the PTX module of each DLL that defines `.entry NAME` and
|
|
lists the FNV-1a 64 hash of the module's text (trailing NUL bytes removed), one "NAME HASH" line per
|
|
distinct hash. The Wine CUDA bridge serves a native kernel only while DLSS loads a module with a
|
|
listed hash, so a DLSS version that changed the kernel runs ZLUDA's own compile of it instead.
|
|
The manifest is written to KERNEL_DIR/d4r-kernels.txt; it holds hashes, not NVIDIA code.
|
|
RR DLLs are explicit: only a DLL passed with --rr-dll may authorize a cuda_dldn_engine_* replacement,
|
|
and the Super Resolution DLLs passed positionally authorize everything else. Both libraries define
|
|
cuda_dldn_engine_* modules of their own (the shared capture and exposure helpers), so without the split
|
|
a Super Resolution hash could stand in for the denoiser's different implementation of the same name.
|
|
"""
|
|
import argparse
|
|
import hashlib
|
|
import os
|
|
import re
|
|
import sys
|
|
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
from extract_dlss_ptx import fatbins, ptx_entries # noqa: E402
|
|
|
|
ENTRY = re.compile(rb'\.entry[ \t\n]+([A-Za-z0-9_$]+)[ \t\n\r]*\(')
|
|
|
|
|
|
def fnv1a64(data: bytes) -> int:
|
|
value = 0xcbf29ce484222325
|
|
for byte in data:
|
|
value = ((value ^ byte) * 0x100000001b3) & 0xffffffffffffffff
|
|
return value
|
|
|
|
|
|
def module_hashes(dll: str) -> dict:
|
|
"""NAME -> set of module hashes for every PTX entry of one DLL."""
|
|
data = open(dll, 'rb').read()
|
|
found = {}
|
|
for _, fatbin in fatbins(data):
|
|
for ptx in ptx_entries(fatbin):
|
|
text = ptx.rstrip(b'\0')
|
|
value = fnv1a64(text)
|
|
for match in ENTRY.finditer(text):
|
|
found.setdefault(match.group(1).decode(), set()).add(value)
|
|
return found
|
|
|
|
|
|
def main(argv):
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("directory")
|
|
parser.add_argument("dlls", nargs="*")
|
|
parser.add_argument("--rr-dll", action="append", default=[])
|
|
args = parser.parse_args(argv[1:])
|
|
if not args.dlls and not args.rr_dll:
|
|
parser.error("at least one SR DLL or --rr-dll is required")
|
|
directory = args.directory
|
|
names = sorted(name[:-len('.hsaco')] for name in os.listdir(directory) if name.endswith('.hsaco'))
|
|
lines = ['# d4r native kernels: NAME and the FNV-1a 64 hash of the DLSS PTX module each was written for',
|
|
'# (written by kernels/tools/kernel_manifest.py from:']
|
|
listed = {name: set() for name in names}
|
|
for dll, reconstruction in [(dll, False) for dll in args.dlls] + [(dll, True) for dll in args.rr_dll]:
|
|
digest = hashlib.sha256(open(dll, 'rb').read()).hexdigest()[:16]
|
|
lines.append(f'# {os.path.basename(dll)} sha256 {digest}...)')
|
|
hashes = module_hashes(dll)
|
|
for name in names:
|
|
if name.startswith("cuda_dldn_engine_") == reconstruction:
|
|
listed[name] |= hashes.get(name, set())
|
|
missing = [name for name in names if not listed[name]]
|
|
if missing:
|
|
sys.exit(f'no DLL defines {", ".join(missing)}; not writing a manifest')
|
|
for name in names:
|
|
for value in sorted(listed[name]):
|
|
lines.append(f'{name} {value:016x}')
|
|
with open(os.path.join(directory, 'd4r-kernels.txt'), 'w') as out:
|
|
out.write('\n'.join(lines) + '\n')
|
|
print(f'{len(names)} kernels listed in {os.path.join(directory, "d4r-kernels.txt")}')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main(sys.argv)
|