Pin external shader bundle in lighting measurements
This commit is contained in:
@@ -98,6 +98,26 @@ with path.open("w", newline="", encoding="utf-8") as stream:
|
|||||||
|
|
||||||
|
|
||||||
class LightingBenchmarkTests(unittest.TestCase):
|
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):
|
def test_list_runs_has_three_independent_repeats_for_each_shadow_setting(self):
|
||||||
process = subprocess.run([sys.executable, SCRIPT, "--list-runs"],
|
process = subprocess.run([sys.executable, SCRIPT, "--list-runs"],
|
||||||
text=True, capture_output=True, check=True)
|
text=True, capture_output=True, check=True)
|
||||||
@@ -215,6 +235,7 @@ class LightingBenchmarkTests(unittest.TestCase):
|
|||||||
self.assertEqual(report["rows"], 54 * 30)
|
self.assertEqual(report["rows"], 54 * 30)
|
||||||
self.assertTrue(report["forward_plus_gate"]["triggered"])
|
self.assertTrue(report["forward_plus_gate"]["triggered"])
|
||||||
self.assertEqual(report["benchmark_sha256"], hashlib.sha256(fake.read_bytes()).hexdigest())
|
self.assertEqual(report["benchmark_sha256"], hashlib.sha256(fake.read_bytes()).hexdigest())
|
||||||
|
self.assertIsNone(report["shader_bundle"])
|
||||||
self.assertEqual(report["source_revision"], revision)
|
self.assertEqual(report["source_revision"], revision)
|
||||||
self.assertFalse(report["source_dirty"])
|
self.assertFalse(report["source_dirty"])
|
||||||
one = json.loads(next((output / "raw").glob("*.args.json")).read_text())
|
one = json.loads(next((output / "raw").glob("*.args.json")).read_text())
|
||||||
|
|||||||
@@ -238,6 +238,22 @@ def _binary_sha256(path: Path) -> str:
|
|||||||
return hashlib.file_digest(stream, "sha256").hexdigest()
|
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:
|
def _clean_source_revision(root: Path, expected: str) -> str:
|
||||||
revision = subprocess.check_output(["git", "-C", str(root), "rev-parse", "HEAD"],
|
revision = subprocess.check_output(["git", "-C", str(root), "rev-parse", "HEAD"],
|
||||||
text=True).strip()
|
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()
|
source = (source_root or Path(__file__).resolve().parents[1]).resolve()
|
||||||
revision = _clean_source_revision(source, commit)
|
revision = _clean_source_revision(source, commit)
|
||||||
binary_sha256 = _binary_sha256(executable)
|
binary_sha256 = _binary_sha256(executable)
|
||||||
|
shader_manifest = _shader_bundle_manifest(executable)
|
||||||
if output.exists() and any(output.iterdir()):
|
if output.exists() and any(output.iterdir()):
|
||||||
raise ValueError(f"Output directory must be new or empty: {output}")
|
raise ValueError(f"Output directory must be new or empty: {output}")
|
||||||
raw = output / "raw"
|
raw = output / "raw"
|
||||||
@@ -312,14 +329,17 @@ def sweep(executable: Path, output: Path, shadows: str, commit: str,
|
|||||||
"acquisition_index"])
|
"acquisition_index"])
|
||||||
writer.writeheader()
|
writer.writeheader()
|
||||||
writer.writerows(all_rows)
|
writer.writerows(all_rows)
|
||||||
if _binary_sha256(executable) != binary_sha256 or _clean_source_revision(source, commit) != revision:
|
if (_binary_sha256(executable) != binary_sha256 or
|
||||||
raise ValueError("Benchmark binary or source changed during the sweep")
|
_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,
|
summary = {"format": "faset.p3-lighting-benchmark", "version": 1,
|
||||||
"commit": commit, "warmup_frames_per_run": WARMUP_FRAMES,
|
"commit": commit, "warmup_frames_per_run": WARMUP_FRAMES,
|
||||||
"measured_frames_per_run": MEASURED_FRAMES, "width": WIDTH, "height": HEIGHT,
|
"measured_frames_per_run": MEASURED_FRAMES, "width": WIDTH, "height": HEIGHT,
|
||||||
"validation": validation, "driver": driver,
|
"validation": validation, "driver": driver,
|
||||||
"source_revision": revision, "source_root": str(source), "source_dirty": False,
|
"source_revision": revision, "source_root": str(source), "source_dirty": False,
|
||||||
"benchmark_sha256": binary_sha256,
|
"benchmark_sha256": binary_sha256,
|
||||||
|
"shader_bundle": shader_manifest,
|
||||||
"device": identity[0], "lighting_path": identity[2],
|
"device": identity[0], "lighting_path": identity[2],
|
||||||
"validation_enabled": identity[3] == "1", "build_configuration": identity[4],
|
"validation_enabled": identity[3] == "1", "build_configuration": identity[4],
|
||||||
"run_order": run_order,
|
"run_order": run_order,
|
||||||
|
|||||||
Reference in New Issue
Block a user