Fix: Skip empty movie refinement generations

Allow frames to finish refinement independently without aborting the movie. Report genuine refinement errors with generation and frame identifiers, and clarify the sample batch contract.

Add a two-frame Schwarzschild regression covering unequal refinement progress. Validated Release and Debug make test suites and 640x360 rendering of the final eight free-fall frames in both builds.
This commit is contained in:
wyj committed 2026-09-06 08:10:29 -04:00
1 parent b69c9cfd45
commit 8cf6106127
4 files changed
+36 -7

No files matched your search

+19 -3
View File
@@ -20,7 +20,7 @@ def run(binary, *args, ok=True):
return result
def image_payload(path):
def image_payload(path, dimensions=(64, 48), allow_black=False):
data = path.read_bytes()
assert data[:8] == b'\x89PNG\r\n\x1a\n'
offset, compressed = 8, bytearray()
@@ -28,12 +28,13 @@ def image_payload(path):
count, kind = struct.unpack_from('>I4s', data, offset)
payload = data[offset + 8:offset + 8 + count]
if kind == b'IHDR':
assert struct.unpack_from('>II', payload) == (64, 48)
assert struct.unpack_from('>II', payload) == dimensions
if kind == b'IDAT':
compressed.extend(payload)
offset += count + 12
raw = zlib.decompress(compressed)
assert any(raw), f'empty image: {path}'
assert raw, f'missing image data: {path}'
assert allow_black or any(raw), f'empty image: {path}'
return raw
@@ -137,4 +138,19 @@ with tempfile.TemporaryDirectory(prefix='gr-camera-cli-') as directory:
assert max_error < 1e-9, max_error
# A map import must still work without evaluating a camera/metric.
assert single == render('import', '--lens-map-input', single_map)
if backend == 'schwarzschild':
# Two inward-looking free-fall samples at r=6.2696 and r=3.1593.
# At 16:9 the latter frame finishes in generation 0, while the
# former still needs refinement. Finishing the empty batch used
# to abort the whole movie in generation 1.
mixed = Path(__file__).parent / 'fixtures/schwarzschild_mixed_refinement.csv'
result = run(binary, *common, '--height', 36, '--fov-deg', 60,
'--refine-max-level', 3, '--observer-track', mixed,
'--movie-track-samples', '--frames-dir', tmp,
'--frames-prefix', 'mixed', '--verbose')
assert 'Ray trace generation 1: frame 0 added' in result.stderr
assert 'Ray trace generation 0: frame 1 added' not in result.stderr
for frame in range(2):
image_payload(tmp / f'mixed_{frame:06d}.png',
dimensions=(64, 36), allow_black=True)
print(f'{backend}: CLI checks passed; single/movie PNG identical, map max error {max_error:.3g}', flush=True)