From 6d78274e25adf4244d16b6c0e60c59717f1b550c Mon Sep 17 00:00:00 2001 From: Emil <65846814+emil28092005@users.noreply.github.com> Date: Thu, 24 Sep 2026 03:09:49 +0300 Subject: [PATCH] Pin external shader bundle in lighting measurements --- tests/test_p3_lighting_benchmark.py | 21 +++++++++++++++++++++ tools/benchmark_p3_lighting.py | 24 ++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/tests/test_p3_lighting_benchmark.py b/tests/test_p3_lighting_benchmark.py index e3ec100..8f62ff0 100644 --- a/tests/test_p3_lighting_benchmark.py +++ b/tests/test_p3_lighting_benchmark.py @@ -98,6 +98,26 @@ with path.open("w", newline="", encoding="utf-8") as stream: class LightingBenchmarkTests(unittest.TestCase): + def test_native_shader_bundle_manifest_tracks_loaded_spirv_and_reflection(self): + from benchmark_p3_lighting import _shader_bundle_manifest + + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + binary = root / "faset_p3_lighting_benchmark" + binary.write_bytes(b"native fixture") + shaders = root / "shaders" + shaders.mkdir() + with self.assertRaisesRegex(ValueError, "shader bundle"): + _shader_bundle_manifest(binary) + for name in ("vertexMain.spv", "fragmentMain.spv", + "fragmentMain.reflection.json", "tileBuild.spv"): + (shaders / name).write_bytes(name.encode()) + before = _shader_bundle_manifest(binary) + self.assertEqual(set(before), {"vertexMain.spv", "fragmentMain.spv", + "fragmentMain.reflection.json", "tileBuild.spv"}) + (shaders / "tileBuild.spv").write_bytes(b"modified tile shader") + self.assertNotEqual(_shader_bundle_manifest(binary), before) + def test_list_runs_has_three_independent_repeats_for_each_shadow_setting(self): process = subprocess.run([sys.executable, SCRIPT, "--list-runs"], text=True, capture_output=True, check=True) @@ -215,6 +235,7 @@ class LightingBenchmarkTests(unittest.TestCase): self.assertEqual(report["rows"], 54 * 30) self.assertTrue(report["forward_plus_gate"]["triggered"]) self.assertEqual(report["benchmark_sha256"], hashlib.sha256(fake.read_bytes()).hexdigest()) + self.assertIsNone(report["shader_bundle"]) self.assertEqual(report["source_revision"], revision) self.assertFalse(report["source_dirty"]) one = json.loads(next((output / "raw").glob("*.args.json")).read_text()) diff --git a/tools/benchmark_p3_lighting.py b/tools/benchmark_p3_lighting.py index fea1bf0..b5e61ef 100644 --- a/tools/benchmark_p3_lighting.py +++ b/tools/benchmark_p3_lighting.py @@ -238,6 +238,22 @@ def _binary_sha256(path: Path) -> str: return hashlib.file_digest(stream, "sha256").hexdigest() +def _shader_bundle_manifest(executable: Path) -> dict[str, str] | None: + # Test fixtures are Python programs. A native renderer loads SPIR-V from + # the shader directory beside its executable before checking other roots. + if executable.suffix.lower() == ".py": + return None + directory = executable.parent / "shaders" + required = ("vertexMain.spv", "fragmentMain.spv") + if not all((directory / name).is_file() for name in required): + raise ValueError(f"Benchmark shader bundle is missing beside {executable}") + files = sorted((path for path in directory.iterdir() + if path.is_file() and + (path.suffix == ".spv" or path.name.endswith(".reflection.json"))), + key=lambda path: path.name) + return {path.name: _binary_sha256(path) for path in files} + + def _clean_source_revision(root: Path, expected: str) -> str: revision = subprocess.check_output(["git", "-C", str(root), "rev-parse", "HEAD"], text=True).strip() @@ -260,6 +276,7 @@ def sweep(executable: Path, output: Path, shadows: str, commit: str, source = (source_root or Path(__file__).resolve().parents[1]).resolve() revision = _clean_source_revision(source, commit) binary_sha256 = _binary_sha256(executable) + shader_manifest = _shader_bundle_manifest(executable) if output.exists() and any(output.iterdir()): raise ValueError(f"Output directory must be new or empty: {output}") raw = output / "raw" @@ -312,14 +329,17 @@ def sweep(executable: Path, output: Path, shadows: str, commit: str, "acquisition_index"]) writer.writeheader() writer.writerows(all_rows) - if _binary_sha256(executable) != binary_sha256 or _clean_source_revision(source, commit) != revision: - raise ValueError("Benchmark binary or source changed during the sweep") + if (_binary_sha256(executable) != binary_sha256 or + _shader_bundle_manifest(executable) != shader_manifest or + _clean_source_revision(source, commit) != revision): + raise ValueError("Benchmark binary, shader bundle or source changed during the sweep") summary = {"format": "faset.p3-lighting-benchmark", "version": 1, "commit": commit, "warmup_frames_per_run": WARMUP_FRAMES, "measured_frames_per_run": MEASURED_FRAMES, "width": WIDTH, "height": HEIGHT, "validation": validation, "driver": driver, "source_revision": revision, "source_root": str(source), "source_dirty": False, "benchmark_sha256": binary_sha256, + "shader_bundle": shader_manifest, "device": identity[0], "lighting_path": identity[2], "validation_enabled": identity[3] == "1", "build_configuration": identity[4], "run_order": run_order,