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,199 @@
|
||||
"""CPU checks for accuracy policy, config precedence and native-set selection.
|
||||
|
||||
Run: python3 -m unittest discover -s tests -v
|
||||
Kernel arithmetic additionally needs kernel/model replays and an RTX reference.
|
||||
"""
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
POLICY = ("D4R_ZLUDA_IGNORE_DENORMAL", "D4R_ZLUDA_WMMA_F32ACC", "D4R_ZLUDA_FAST_MATH",
|
||||
"D4R_ZLUDA_WAVE64", "D4R_ELIDE_NGX_SYNC")
|
||||
|
||||
|
||||
class AccuracyTests(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.build = tempfile.TemporaryDirectory()
|
||||
cls.runner = Path(cls.build.name) / "selection"
|
||||
source = r'''
|
||||
#include "d4r_native_selection.h"
|
||||
int main(int argc, char** argv) {
|
||||
if (argc == 2 && strcmp(argv[1], "policy") == 0) {
|
||||
printf("%d", d4r_apply_accuracy_policy());
|
||||
const char* keys[] = {"D4R_ZLUDA_IGNORE_DENORMAL", "D4R_ZLUDA_WMMA_F32ACC",
|
||||
"D4R_ZLUDA_FAST_MATH", "D4R_ZLUDA_WAVE64", "D4R_ELIDE_NGX_SYNC"};
|
||||
for (unsigned i = 0; i < sizeof(keys) / sizeof(keys[0]); ++i)
|
||||
printf(" %s", getenv(keys[i]) ? getenv(keys[i]) : "unset");
|
||||
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));
|
||||
printf("%d %s\n", kind, path);
|
||||
return 0;
|
||||
}
|
||||
'''
|
||||
subprocess.run(["cc", "-x", "c", "-std=gnu11", "-Wall", "-Wextra", "-Werror",
|
||||
"-I", str(ROOT / "tools"), "-o", str(cls.runner), "-"],
|
||||
input=source, text=True, check=True, capture_output=True)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.build.cleanup()
|
||||
|
||||
def setUp(self):
|
||||
self.temp = tempfile.TemporaryDirectory()
|
||||
self.addCleanup(self.temp.cleanup)
|
||||
self.root = Path(self.temp.name)
|
||||
|
||||
def native(self, directory, accuracy=False, manifest=True):
|
||||
directory.mkdir(parents=True, exist_ok=True)
|
||||
(directory / "kernel.hsaco").write_bytes(b"fixture")
|
||||
if manifest:
|
||||
(directory / "d4r-kernels.txt").write_text("kernel 1234\n")
|
||||
if accuracy:
|
||||
(directory / "d4r-accuracy.txt").write_text("1\n")
|
||||
|
||||
def select(self, architecture="gfx1101", accuracy=True, fp8=True, directory=None):
|
||||
output = subprocess.check_output([str(self.runner), str(directory or self.root), architecture,
|
||||
str(int(accuracy)), str(int(fp8))], text=True).strip()
|
||||
kind, _, path = output.partition(" ")
|
||||
return int(kind), Path(path)
|
||||
|
||||
def test_select_accuracy_for_every_release_target(self):
|
||||
for arch in ("gfx1100", "gfx1101", "gfx1102", "gfx1103", "gfx1200", "gfx1201"):
|
||||
self.native(self.root / arch)
|
||||
accurate = self.root / "accuracy" / arch
|
||||
self.native(accurate, accuracy=True)
|
||||
self.assertEqual(self.select(arch), (1, accurate))
|
||||
self.assertEqual(self.select(arch, accuracy=False), (1, self.root / arch))
|
||||
|
||||
def test_rdna4_fp8_selection_and_widened_fallback(self):
|
||||
for arch in ("gfx1200", "gfx1201"):
|
||||
accurate = self.root / "accuracy" / arch
|
||||
fp8 = self.root / "accuracy" / (arch + "-fp8")
|
||||
self.native(accurate, accuracy=True)
|
||||
self.assertEqual(self.select(arch), (1, accurate))
|
||||
self.native(fp8, accuracy=True)
|
||||
self.assertEqual(self.select(arch), (1, fp8))
|
||||
self.assertEqual(self.select(arch, fp8=False), (1, accurate))
|
||||
|
||||
def test_missing_accuracy_never_selects_fast_or_wrong_gpu(self):
|
||||
self.native(self.root / "gfx1101")
|
||||
self.native(self.root / "accuracy" / "gfx1201", accuracy=True)
|
||||
self.assertEqual(self.select()[0], 0)
|
||||
self.native(self.root / "accuracy" / "gfx1101") # unmarked binaries
|
||||
self.assertEqual(self.select()[0], 0)
|
||||
|
||||
def test_flat_accuracy_developer_set_requires_valid_marker(self):
|
||||
self.native(self.root, manifest=False)
|
||||
self.assertEqual(self.select()[0], 0)
|
||||
self.assertEqual(self.select(accuracy=False), (2, self.root))
|
||||
(self.root / "d4r-accuracy.txt").write_text("1\n")
|
||||
self.assertEqual(self.select(), (2, self.root))
|
||||
(self.root / "d4r-accuracy.txt").write_text("0\n")
|
||||
self.assertEqual(self.select()[0], 0)
|
||||
|
||||
def test_missing_fast_target_does_not_select_release_root(self):
|
||||
self.native(self.root / "gfx1201")
|
||||
self.assertEqual(self.select(accuracy=False)[0], 0)
|
||||
|
||||
def test_accuracy_policy_overrides_conflicting_fast_settings(self):
|
||||
env = dict(os.environ, D4R_PREFER_ACCURACY="1", **dict.fromkeys(POLICY, "1"))
|
||||
output = subprocess.check_output([str(self.runner), "policy"], env=env, text=True).strip()
|
||||
self.assertEqual(output, "1 0 0 0 0 0")
|
||||
|
||||
def test_default_off_preserves_existing_policy(self):
|
||||
env = {k: v for k, v in os.environ.items() if k != "D4R_PREFER_ACCURACY"}
|
||||
env.update(dict.fromkeys(POLICY, "1"))
|
||||
output = subprocess.check_output([str(self.runner), "policy"], env=env, text=True).strip()
|
||||
self.assertEqual(output, "0 1 1 1 1 1")
|
||||
|
||||
def config(self, text, extra_env=None, expected=0):
|
||||
path = self.root / "d4r.ini"
|
||||
path.write_text(text)
|
||||
env = {k: v for k, v in os.environ.items() if not k.startswith("D4R_")}
|
||||
env.update(extra_env or {})
|
||||
result = subprocess.run(["python3", str(ROOT / "scripts/d4r_config.py"), "--config", str(path)],
|
||||
env=env, text=True, capture_output=True)
|
||||
self.assertEqual(result.returncode, expected, result.stderr)
|
||||
return result
|
||||
|
||||
def test_config_default_and_boolean_spellings(self):
|
||||
self.assertIn("export D4R_PREFER_ACCURACY=0", self.config("").stdout)
|
||||
for value in ("true", "on", "yes", "1"):
|
||||
result = self.config(f"[Kernels]\nPreferAccuracy = {value}\nNativeKernels = off\n")
|
||||
self.assertIn("export D4R_PREFER_ACCURACY=1", result.stdout)
|
||||
self.assertNotIn("D4R_ZLUDA_NATIVE_DIR", result.stdout)
|
||||
for value in ("false", "off", "no", "0"):
|
||||
self.assertIn("export D4R_PREFER_ACCURACY=0",
|
||||
self.config(f"[Kernels]\nPreferAccuracy = {value}\n").stdout)
|
||||
|
||||
def test_explicit_environment_wins_and_invalid_setting_is_reported(self):
|
||||
self.assertNotIn("export D4R_PREFER_ACCURACY",
|
||||
self.config("[Kernels]\nPreferAccuracy=true\n", {"D4R_PREFER_ACCURACY": "0"}).stdout)
|
||||
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$")
|
||||
|
||||
def test_builder_refuses_to_certify_mixed_fast_binaries(self):
|
||||
compiler = self.root / "rocm/lib/llvm/bin/clang++"
|
||||
compiler.parent.mkdir(parents=True)
|
||||
compiler.write_text("#!/bin/sh\nexit 99\n")
|
||||
compiler.chmod(0o755)
|
||||
output = self.root / "mixed"
|
||||
self.native(output, manifest=False)
|
||||
env = dict(os.environ, D4R_PREFER_ACCURACY="1", D4R_ROCM_DIR=str(self.root / "rocm"))
|
||||
for marker in (None, "0\n"):
|
||||
if marker is not None:
|
||||
(output / "d4r-accuracy.txt").write_text(marker)
|
||||
result = subprocess.run(["bash", str(ROOT / "kernels/build.sh"), "k", str(output)],
|
||||
env=env, text=True, capture_output=True)
|
||||
self.assertEqual(result.returncode, 2)
|
||||
self.assertIn("accuracy kernels need an empty output directory", result.stderr)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
@@ -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))
|
||||
@@ -0,0 +1,23 @@
|
||||
import unittest
|
||||
|
||||
import numpy as np
|
||||
|
||||
from engine.rr.rrmath import q8
|
||||
|
||||
|
||||
class F16ToE4M3Tests(unittest.TestCase):
|
||||
def test_special_values_and_signed_nan(self):
|
||||
bits = np.array([0x0000, 0x3C00, 0x7C00, 0xFC00, 0x7E00, 0xFE00], dtype=np.uint16)
|
||||
values = bits.view(np.float16)
|
||||
self.assertEqual(q8(values).tolist(), [0x00, 0x38, 0x7E, 0xFE, 0x7F, 0x7F])
|
||||
|
||||
def test_every_half_pattern_maps_to_byte(self):
|
||||
values = np.arange(65536, dtype=np.uint16).view(np.float16)
|
||||
codes = q8(values)
|
||||
self.assertEqual(codes.shape, (65536,))
|
||||
self.assertEqual(codes.dtype, np.uint8)
|
||||
self.assertTrue(np.all(codes[0x7C01:0x8000] == 0x7F))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user