Add experimental preset L and fix DLSS resource lifetimes and waits

- Build L texture variants and complete older release kernel bundles.
- Add selective Swin encoder fallback to reduce L/M motion trails.
- Add opt-in GPU motion-vector dilation for thin geometry and sky gaps.
- Replace GPU input waits with cancellable readiness polling and use
  sleeping event queries for completion.
- Retain recorded resources through command allocator completion, defer
  shutdown until cleanup, and preserve unfinished output synchronization.
- Extend lifecycle harness checks and add event, model and motion tests.
- Update configuration defaults, build scripts and release documentation.
This commit is contained in:
ayo committed 2026-10-02 00:30:46 -04:00
1 parent b645ef9096
commit f66cccaf28
32 files changed
+1362 -249

No files matched your search

+34
View File
@@ -31,6 +31,9 @@ int main(int argc, char** argv) {
puts("");
return 0;
}
if (argc == 3 && strcmp(argv[1], "kernel") == 0) {
printf("%d\n", d4r_native_kernel_allowed(argv[2])); return 0;
}
if (argc != 5) return 2;
char path[1024] = {0};
int kind = d4r_select_native_source(argv[1], argv[2], atoi(argv[3]), atoi(argv[4]), path, sizeof(path));
@@ -140,6 +143,37 @@ int main(int argc, char** argv) {
result = self.config("[Kernels]\nPreferAccuracy=perhaps\n", expected=2)
self.assertIn("PreferAccuracy must be true or false", result.stderr)
def test_swin_encoder_fallback_keeps_other_layers(self):
encoders = ("rrlite_enc1_4x4", "rrlite_enc2_4x4")
others = ("rrlite_enc3_tube_4x4", "rrlite_dec1_4x4", "rrlite_dec2_4x4",
"rrlite_enc0_4x4_mvhi_hdr", "rrlite_post_3_1_mvhi_hdr", "dltss_pwin_enc1_layer")
for value in ("0", "1", None):
env = {k: v for k, v in os.environ.items() if k != "D4R_NATIVE_SWIN_ENCODERS"}
if value is not None:
env["D4R_NATIVE_SWIN_ENCODERS"] = value
for name in encoders + others:
got = subprocess.check_output([str(self.runner), "kernel", name], env=env, text=True).strip()
self.assertEqual(got, "0" if value == "0" and name in encoders else "1")
def test_swin_encoder_config_and_environment_override(self):
for value, expected in (("false", "0"), ("true", "1"), ("auto", "1")):
self.assertIn(f"export D4R_NATIVE_SWIN_ENCODERS={expected}",
self.config(f"[Kernels]\nNativeSwinEncoders = {value}\n").stdout)
result = self.config("[Kernels]\nNativeSwinEncoders = false\n",
{"D4R_NATIVE_SWIN_ENCODERS": "1"})
self.assertNotIn("export D4R_NATIVE_SWIN_ENCODERS", result.stdout)
self.config("[Kernels]\nNativeSwinEncoders = maybe\n", expected=2)
def test_motion_dilation_config_bounds_and_environment_precedence(self):
for value, expected in (("0", "0"), ("1", "1"), ("2", "2"), ("auto", "0")):
self.assertIn(f"export D4R_MOTION_DILATION={expected}",
self.config(f"[Interop]\nMotionVectorDilation = {value}\n").stdout)
for value in ("-1", "3", "true", "1.5"):
self.config(f"[Interop]\nMotionVectorDilation = {value}\n", expected=2)
self.assertNotIn("export D4R_MOTION_DILATION",
self.config("[Interop]\nMotionVectorDilation = 2\n",
{"D4R_MOTION_DILATION": "0"}).stdout)
def test_shipped_configs_default_off(self):
for file in ("config/d4r.ini.default", "packaging/d4r.ini"):
self.assertRegex((ROOT / file).read_text(), r"(?m)^PreferAccuracy\s*=\s*false$")
+36
View File
@@ -0,0 +1,36 @@
"""Completion/error contracts for the sleeping CUDA event wait (no GPU needed)."""
from pathlib import Path
import subprocess
import tempfile
import unittest
ROOT = Path(__file__).resolve().parents[1]
class EventWaitTests(unittest.TestCase):
def test_completion_pending_and_error(self):
source = r'''
#include "d4r_event_wait.h"
#include <cassert>
int main() {
int sleeps = 0, queries = 0;
assert(d4r_wait_event([] { return 0; }, [&] { ++sleeps; }) == 0);
assert(sleeps == 0);
assert(d4r_wait_event([&] { return ++queries <= 7 ? 600 : 0; },
[&] { ++sleeps; }) == 0);
assert(queries == 8 && sleeps == 7);
sleeps = 0;
assert(d4r_wait_event([] { return 719; }, [&] { ++sleeps; }) == 719);
assert(sleeps == 0);
queries = 0;
assert(d4r_wait_event([&] { return ++queries == 1 ? 600 : 700; },
[&] { ++sleeps; }) == 700);
assert(sleeps == 1);
}
'''
with tempfile.TemporaryDirectory() as tmp:
runner = Path(tmp) / "wait"
subprocess.run(["c++", "-x", "c++", "-std=c++17", "-Wall", "-Wextra", "-Werror",
"-I", str(ROOT / "tools"), "-o", str(runner), "-"],
input=source, text=True, check=True, capture_output=True)
subprocess.run([str(runner)], check=True, timeout=5)
+48
View File
@@ -0,0 +1,48 @@
"""L must retain its unfolded neural math when native surface stores are substituted."""
import os
from pathlib import Path
import subprocess
import tempfile
import unittest
ROOT = Path(__file__).resolve().parents[1]
class ModelLTests(unittest.TestCase):
def test_model_l_config_and_environment_precedence(self):
with tempfile.TemporaryDirectory() as directory:
ini = Path(directory) / 'd4r.ini'
ini.write_text('[DLSS]\nModel = L\n')
env = dict(os.environ)
env.pop('D4R_DLSS_PRESET', None)
cmd = ['python3', str(ROOT / 'scripts/d4r_config.py'), '--config', str(ini)]
self.assertIn('export D4R_DLSS_PRESET=12', subprocess.check_output(cmd, env=env, text=True))
env['D4R_DLSS_PRESET'] = '11'
self.assertNotIn('export D4R_DLSS_PRESET=', subprocess.check_output(cmd, env=env, text=True))
def test_unfolded_variants_preserve_neural_arithmetic(self):
names = ['rrlite_dec0_4x4']
for mv in ('mvhi', 'mvlo'):
for dynamic_range in ('hdr', 'ldr'):
names.append(f'rrlite_enc0_4x4_{mv}_{dynamic_range}')
names.extend(f'rrlite_post_{v}_{mv}_{dynamic_range}' for v in ('3_1', '3_2'))
math = 'mma.sync.aligned.m16n8k32.row.col.f16.e4m3.e4m3.f16 {%r1, %r2}, {%r3, %r4, %r5, %r6}, {%r7, %r8}, {%r9, %r10};'
store = 'sust.b.2d.v2.b16.zero [%rd1, {%r1,%r2}], {%rs1,%rs2};'
with tempfile.TemporaryDirectory() as directory:
ptx = Path(directory)
env = dict(os.environ, D4R_DLSS_PTX_DIR=directory, D4R_SUST_KINDS='b16,p,b32')
for name in names:
with self.subTest(kernel=name):
(ptx / 'input.ptx').write_text(f'.visible .entry {name}(\n)\n{{\n{math}\n{store}\nret;\n}}\n')
subprocess.run(['python3', str(ROOT / 'kernels/tex/make_ptx.py'), name, str(ptx / 'out.ptx')],
env=env, check=True, capture_output=True)
output = (ptx / 'out.ptx').read_text()
self.assertIn(math, output)
self.assertNotIn(store, output)
self.assertIn('call d4r_sust_v2b16', output)
self.assertNotIn('d4r_enc0_tail', output)
self.assertNotIn('d4r_dec0_head', output)
if __name__ == '__main__':
unittest.main()
+45
View File
@@ -0,0 +1,45 @@
"""Motion-grid selection and padded low-resolution allocation regression."""
from pathlib import Path
import subprocess
import tempfile
import unittest
ROOT = Path(__file__).resolve().parents[1]
class MotionGeometryTests(unittest.TestCase):
def test_low_res_padding_flags_and_display_res_mapping(self):
source = r'''
#include "d4r_motion_dilation.h"
#include <cassert>
int main() {
D4rMotionDilationParams p = {};
p.render_width = 854; p.render_height = 480;
p.motion_width = 856; p.motion_height = 480;
p.motion_pitch = 4096; p.jitter_x = 0.375f; p.jitter_y = -0.25f;
auto low = p;
assert(d4r_motion_dilation_geometry(&low, 0xb, 2560, 1440));
assert(low.motion_width == 854 && low.motion_height == 480);
assert(low.motion_pitch == 4096 && low.jitter_x == 0 && low.jitter_y == 0);
low = p;
assert(d4r_motion_dilation_geometry(&low, 0x4b, 2560, 1440));
low = p; low.motion_width = 853;
assert(!d4r_motion_dilation_geometry(&low, 0xb, 2560, 1440));
low = p; low.motion_height = 479;
assert(!d4r_motion_dilation_geometry(&low, 0xb, 2560, 1440));
low = p;
assert(!d4r_motion_dilation_geometry(&low, 0xf, 2560, 1440));
assert(!d4r_motion_dilation_geometry(&p, 0x49, 2560, 1440));
p.motion_width = 2560; p.motion_height = 1440;
assert(d4r_motion_dilation_geometry(&p, 0x49, 2560, 1440));
assert(p.jitter_x == 0.375f && p.jitter_y == -0.25f);
p.render_width = 0;
assert(!d4r_motion_dilation_geometry(&p, 0x49, 2560, 1440));
}
'''
with tempfile.TemporaryDirectory() as tmp:
runner = Path(tmp) / "geometry"
subprocess.run(["c++", "-x", "c++", "-std=c++17", "-Wall", "-Wextra", "-Werror",
"-I", str(ROOT / "tools"), "-o", str(runner), "-"],
input=source, text=True, check=True, capture_output=True)
subprocess.run([str(runner)], check=True, timeout=5)
+123
View File
@@ -0,0 +1,123 @@
"""Optional GPU regression: independently specified thin-foreground velocity coverage.
D4R_RUN_GPU_TESTS=1 D4R_DUMP_RUNNER=/path/to/dump_runner python3 -m unittest discover -s tests -v
Build the embedded kernels first with scripts/build_d4r_motion_kernels.sh.
"""
import os
from pathlib import Path
import struct
import subprocess
import tempfile
import unittest
ROOT = Path(__file__).resolve().parents[1]
@unittest.skipUnless(os.environ.get('D4R_RUN_GPU_TESTS') == '1', 'opt-in GPU test')
class MotionKernelGpuTests(unittest.TestCase):
def test_low_resolution_opaque_edges_and_padded_rows(self):
runner = os.environ['D4R_DUMP_RUNNER']
kernel = ROOT / 'build/wine-nvcuda/generated' / (os.environ.get('D4R_GPU_ARCH', 'gfx1101') + '.hsaco')
width, height, stride = 5, 3, 8
sentinel = 0xA5A5A5A5
for reversed_depth in (False, True):
for radius in (1, 2):
with self.subTest(reversed_depth=reversed_depth, radius=radius), tempfile.TemporaryDirectory() as t:
directory = Path(t); output = directory / 'out'; output.mkdir()
depth = [0.1 if reversed_depth else 0.9] * (stride*height)
depth[stride+2] = 0.9 if reversed_depth else 0.1
motion = list(range(stride*height))
arrays = [struct.pack('<24f', *depth), struct.pack('<24I', *motion), struct.pack('<24I', *([sentinel]*24))]
addresses = (0x100000000, 0x200000000, 0x300000000)
args = struct.pack('<5Q4I2f2I', *addresses, stride*4, stride*4,
width, height, width, height, 0.0, 0.0, radius, reversed_depth)
(directory/'args.bin').write_bytes(args)
manifest = ['kernel d4r_motion_dilate', 'launch 1 1 1 128 1 1 0', 'args 72']
for i, data in enumerate(arrays):
(directory/f'alloc-{i}.bin').write_bytes(data)
manifest += [f'alloc {i} {hex(addresses[i])} {len(data)}', f'pointer {i*8} {i} 0']
(directory/'manifest.txt').write_text('\n'.join(manifest)+'\n')
subprocess.run([runner, str(kernel), 'd4r_motion_dilate', str(directory), str(output), '1'], check=True, capture_output=True)
self.assertEqual((output/'alloc-0.bin').read_bytes(), arrays[0])
self.assertEqual((output/'alloc-1.bin').read_bytes(), arrays[1])
expected = [sentinel] * 24
for y in range(height):
for x in range(width):
expected[y*stride+x] = motion[stride+2] if abs(x-2) <= radius and abs(y-1) <= radius else motion[y*stride+x]
self.assertEqual((output/'alloc-2.bin').read_bytes(), struct.pack('<24I', *expected))
def test_foreground_coverage_padding_and_input_immutability(self):
runner = os.environ['D4R_DUMP_RUNNER']
kernel = ROOT / 'build/wine-nvcuda/generated' / (os.environ.get('D4R_GPU_ARCH', 'gfx1101') + '.hsaco')
sentinel = 0xA5A5A5A5
for reversed_depth in (False, True):
for radius in (1, 2):
for jitter in ((0.0, 0.0), (0.25, -0.25)):
with self.subTest(reversed_depth=reversed_depth, radius=radius, jitter=jitter), tempfile.TemporaryDirectory() as t:
directory = Path(t); output = directory / 'out'; output.mkdir()
depth = [1000.0] * 16
for y in range(2):
for x in range(3):
depth[y*8+x] = 0.1 if reversed_depth else 0.9
depth[1] = 0.9 if reversed_depth else 0.1
motion = list(range(96))
arrays = [struct.pack('<16f', *depth), struct.pack('<96I', *motion), struct.pack('<96I', *([sentinel]*96))]
addresses = (0x100000000, 0x200000000, 0x300000000)
args = struct.pack('<5Q4I2f2I', *addresses, 32, 64, 3, 2, 9, 6, *jitter, radius, reversed_depth)
(directory/'args.bin').write_bytes(args)
manifest = ['kernel d4r_motion_dilate', 'launch 1 1 1 128 1 1 0', 'args 72']
for i, data in enumerate(arrays):
(directory/f'alloc-{i}.bin').write_bytes(data)
manifest += [f'alloc {i} {hex(addresses[i])} {len(data)}', f'pointer {i*8} {i} 0']
(directory/'manifest.txt').write_text('\n'.join(manifest)+'\n')
subprocess.run([runner, str(kernel), 'd4r_motion_dilate', str(directory), str(output), '1'], check=True, capture_output=True)
self.assertEqual((output/'alloc-0.bin').read_bytes(), arrays[0])
self.assertEqual((output/'alloc-1.bin').read_bytes(), arrays[1])
expected = [sentinel] * 96
# Known single foreground cell: all neighbouring background follows its velocity.
# Foreground itself preserves its original per-pixel velocity; row padding is untouched.
for y in range(6):
for x in range(9):
inside = (3 <= x <= 5 and y <= 2) if jitter == (0.0, 0.0) else (2 <= x <= 4 and y <= 3)
expected[y*16+x] = motion[y*16+x] if inside else motion[1*16+4] if jitter == (0.0, 0.0) else motion[2*16+3]
self.assertEqual((output/'alloc-2.bin').read_bytes(), struct.pack('<96I', *expected))
def test_automatic_sky_fill_circle_nearest_ties_and_empty_sky(self):
runner = os.environ['D4R_DUMP_RUNNER']
kernel = ROOT / 'build/wine-nvcuda/generated' / (os.environ.get('D4R_GPU_ARCH', 'gfx1101') + '.hsaco')
width, height, stride = 23, 23, 32
sentinel = 0xA5A5A5A5
for reversed_depth in (False, True):
for radius in (1, 2):
for empty, near_far in ((False, False), (True, False), (False, True)):
with self.subTest(reversed_depth=reversed_depth, radius=radius, empty=empty, near_far=near_far), tempfile.TemporaryDirectory() as t:
directory = Path(t); output = directory / 'out'; output.mkdir()
depth = [1000.0] * (stride*height)
for y in range(height):
for x in range(width):
depth[y*stride+x] = (1.e-7 if near_far else 0.0) if reversed_depth else 1.0
sources = [] if empty else [(8, 11), (14, 11)]
for x, y in sources:
depth[y*stride+x] = (1.5e-7 if near_far else 0.9) if reversed_depth else (0.99 if near_far else 0.1)
motion = list(range(stride*height))
arrays = [struct.pack(f'<{len(depth)}f', *depth), struct.pack(f'<{len(motion)}I', *motion), struct.pack(f'<{len(motion)}I', *([sentinel]*len(motion)))]
addresses = (0x100000000, 0x200000000, 0x300000000)
args = struct.pack('<5Q4I2f2I', *addresses, stride*4, stride*4, width, height, width, height, 0.0, 0.0, radius, reversed_depth)
(directory/'args.bin').write_bytes(args)
manifest = ['kernel d4r_motion_dilate', 'launch 5 1 1 128 1 1 0', 'args 72']
for i, data in enumerate(arrays):
(directory/f'alloc-{i}.bin').write_bytes(data)
manifest += [f'alloc {i} {hex(addresses[i])} {len(data)}', f'pointer {i*8} {i} 0']
(directory/'manifest.txt').write_text('\n'.join(manifest)+'\n')
subprocess.run([runner, str(kernel), 'd4r_motion_dilate', str(directory), str(output), '1'], check=True, capture_output=True)
self.assertEqual((output/'alloc-0.bin').read_bytes(), arrays[0])
self.assertEqual((output/'alloc-1.bin').read_bytes(), arrays[1])
expected = [sentinel] * len(motion)
for y in range(height):
for x in range(width):
candidates = sorted(((x-sx)**2+(y-sy)**2, sx, sy) for sx, sy in sources)
expected[y*stride+x] = motion[y*stride+x]
if candidates and candidates[0][0] <= 64:
_, sx, sy = candidates[0]
expected[y*stride+x] = motion[sy*stride+sx]
self.assertEqual((output/'alloc-2.bin').read_bytes(), struct.pack(f'<{len(expected)}I', *expected))