Files
filament/test/render-validation/process_results.py
2026-04-28 23:07:30 -07:00

162 lines
5.4 KiB
Python

import argparse
import json
import os
import shutil
import zipfile
from pathlib import Path
from PIL import Image
def get_test_tolerance(config, full_test_name):
# test name is e.g. "basic.opengl.DamagedHelmet"
parts = full_test_name.split('.')
if not parts: return None
test_id = parts[0]
for test in config.get("tests", []):
if test.get("name") == test_id:
return test.get("tolerance")
return None
def process_zip(zip_path, output_dir, device_name):
"""Extract and process a single zip file from the results folder."""
extract_dir = os.path.join(output_dir, "tmp", device_name)
os.makedirs(extract_dir, exist_ok=True)
with zipfile.ZipFile(zip_path, 'r') as z:
z.extractall(extract_dir)
results_json_path = os.path.join(extract_dir, "results.json")
if not os.path.exists(results_json_path):
return {}, []
with open(results_json_path, 'r') as f:
try:
device_results = json.load(f)
except json.JSONDecodeError:
return {}, []
metadata = device_results['metadata']
bundle_zip_path = os.path.join(extract_dir, "bundle.zip")
bundle_dir = os.path.join(extract_dir, "bundle")
if os.path.exists(bundle_zip_path):
os.makedirs(bundle_dir, exist_ok=True)
with zipfile.ZipFile(bundle_zip_path, 'r') as z:
z.extractall(bundle_dir)
config_path = os.path.join(bundle_dir, "default_test", "config.json")
config = {}
if os.path.exists(config_path):
with open(config_path, 'r') as f:
config = json.load(f)
run_results = []
for test_result in device_results.get("results", []):
test_name = test_result.get("test_name")
passed = test_result.get("passed", False)
rendered_path = os.path.join(extract_dir, f"{test_name}.png")
golden_path = os.path.join(bundle_dir, "default_test", "goldens", f"{test_name}.png")
if not os.path.exists(rendered_path):
continue
rendered_img = Image.open(rendered_path).convert("RGBA")
# Output paths for web
rel_test_dir = f"{device_name}/{test_name}"
out_test_dir = os.path.join(output_dir, "assets", rel_test_dir)
os.makedirs(out_test_dir, exist_ok=True)
out_golden = os.path.join(out_test_dir, "golden.png")
out_rendered = os.path.join(out_test_dir, "rendered.png")
out_thumb = os.path.join(out_test_dir, "thumb.png")
rendered_img.save(out_rendered)
# Generate thumbnail
thumb_size = (128, 128)
thumb_img = rendered_img.copy()
thumb_img.thumbnail(thumb_size)
thumb_img.save(out_thumb)
has_golden = False
if os.path.exists(golden_path):
has_golden = True
shutil.copy2(golden_path, out_golden)
else:
Image.new("RGBA", rendered_img.size, (0,0,0,0)).save(out_golden)
tolerance_config = get_test_tolerance(config, test_name)
run_results.append({
"testName": test_name,
"passed": passed,
"golden": f"assets/{rel_test_dir}/golden.png",
"rendered": f"assets/{rel_test_dir}/rendered.png",
"thumb": f"assets/{rel_test_dir}/thumb.png",
"hasGolden": has_golden,
"config": tolerance_config
})
return [metadata, run_results]
def main():
parser = argparse.ArgumentParser(description="Process render validation zip results.")
parser.add_argument("input_dir", help="Directory containing .zip result files")
parser.add_argument("output_dir", help="Directory to output the static web viewer")
args = parser.parse_args()
input_dir = Path(args.input_dir)
output_dir = Path(args.output_dir)
if not input_dir.exists():
print(f"Error: Input directory {input_dir} does not exist.")
return
os.makedirs(output_dir, exist_ok=True)
os.makedirs(output_dir / "assets", exist_ok=True)
all_results = []
for zip_file in input_dir.glob("*.zip"):
device_name = zip_file.stem
print(f"Processing {zip_file.name} for device {device_name}...")
metadata, device_results = process_zip(zip_file, output_dir, device_name)
if device_results:
all_results.append({
"metadata": metadata,
"device": device_name,
"runs": device_results
})
# Cleanup tmp
tmp_dir = output_dir / "tmp"
if tmp_dir.exists():
shutil.rmtree(tmp_dir)
# Write data.json
with open(output_dir / "data.json", "w") as f:
json.dump(all_results, f, indent=2)
# Copy web viewer files
viewer_src = Path(__file__).parent / "result-viewer"
if viewer_src.exists():
for item in viewer_src.iterdir():
if item.is_file():
shutil.copy2(item, output_dir)
elif item.is_dir():
dest_dir = output_dir / item.name
if dest_dir.exists():
shutil.rmtree(dest_dir)
shutil.copytree(item, dest_dir)
print("Done. To view results, run a static server in the output directory:")
print(f"cd {output_dir} && python3 -m http.server 1234")
if __name__ == "__main__":
main()