#!/usr/bin/env python3 """Start real clients and verify a nonuniform GPU framebuffer readback.""" import argparse import hashlib import json import os import platform import re import shutil import sys try: from . import build_mod, build_pack from .test_culling_rays import FixtureTimeout, run_fixture from .test_dispatch import failure_summary except ImportError: import build_mod import build_pack from test_culling_rays import FixtureTimeout, run_fixture from test_dispatch import failure_summary def graphics_failure_summary(run, report_count): """Selected stages/types/codes/methods only; messages and paths stay private.""" result = failure_summary(run, report_count) pattern = r'(?]{1,180})\(') methods = re.findall(stack_pattern, run.stdout, re.MULTILINE | re.ASCII) result['observed_graphics_stack_methods'] = list(dict.fromkeys(methods))[:8] return result def validate_shader_report(report, required): if required and (report.get('shader_required') is not True or report.get('iris_capture_status') != 'available' or report.get('iris_shaders_enabled') is not True or report.get('iris_expected_pack_matches') is not True): raise AssertionError('Required runtime shader activation was not verified') def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('--native-display', action='store_true') parser.add_argument('--profile', action='append', choices=sorted(build_pack.PROFILES)) parser.add_argument('--backend', choices=['opengl', 'vulkan'], help='Override backend in these private instances only') parser.add_argument('--world', action='store_true', help='Create/open a disposable built-in demo world instead of stopping at the title') parser.add_argument('--shaders', action='store_true', help='Require the pinned cinematic shader pack in a private world instance') args = parser.parse_args() if args.shaders and (not args.world or args.profile not in [None, ['cinematic']]): parser.error('--shaders requires --world and the cinematic profile') root = build_pack.ROOT fixture = build_mod.build_integration_fixture('client-graphics', 'dev.horizonlab.metrics.ClientGraphicsIntegration', fixture_mixins=['GraphicsBackendTraceMixin'], fixture_dependencies={}) version = build_pack.read_lock()['pack_version'] mod = root / 'dist' / f'horizon-{version}.jar' original_hash = hashlib.sha256(mod.read_bytes()).hexdigest() results = [] for profile in args.profile or (['cinematic'] if args.shaders else ['core-performance', 'm2-balanced']): instance = root / '.local/runtime' / ('client-graphics-' + profile + ('-override-' + args.backend if args.backend else '') + ('-world' if args.world else '') + ('-shaders' if args.shaders else '')) build_pack.prepare_instance(profile, instance, mod) if args.world: (instance / 'config/client-graphics-world.flag').touch() if args.shaders: expected = build_pack.read_lock()['projects']['complementary-reimagined']['filename'] (instance / 'config/iris.properties').write_text('enableShaders=true\nshaderPack=' + expected + '\n') (instance / 'config/client-graphics-shaders.flag').write_text(expected + '\n') if args.backend: options = instance / 'options.txt' text, count = re.subn(r'^preferredGraphicsBackend:.*$', 'preferredGraphicsBackend:' + json.dumps(args.backend), options.read_text(), flags=re.MULTILINE) if count != 1: raise AssertionError('Private backend preference is missing or ambiguous') options.write_text(text) shutil.copy2(fixture, instance / 'mods/client-graphics-fixture.jar') command = [sys.executable, str(root / 'tools/runtime.py'), 'demo', '--instance', str(instance), '--heap', '6G' if args.shaders else '3G'] if platform.system() == 'Linux' and not args.native_display: command = ['xvfb-run', '-a', *command] try: run = run_fixture(command, instance, os.environ.copy()) except FixtureTimeout as error: diagnostics = graphics_failure_summary(error.run, 0) diagnostics.update(fixture='client-graphics', profile=profile, completed=False, timed_out=True, timeout_seconds=240) print('HORIZON_FIXTURE_FAILURE ' + json.dumps(diagnostics), flush=True) raise RuntimeError('Graphics probe did not finish; diagnostics remain private') from None marker = 'HORIZON_CLIENT_GRAPHICS_RESULT ' reports = [json.loads(line.split(marker, 1)[1]) for line in run.stdout.splitlines() if marker in line] trace_marker = 'HORIZON_GRAPHICS_BACKEND_ATTEMPT ' attempts = [json.loads(line.split(trace_marker, 1)[1]) for line in run.stdout.splitlines() if trace_marker in line] if run.returncode or len(reports) != 1: diagnostics = graphics_failure_summary(run, len(reports)) diagnostics['profile'] = profile diagnostics['preferred_backend'] = args.backend or build_pack.PROFILES[profile].get('backend', 'opengl') print('HORIZON_FIXTURE_FAILURE ' + json.dumps(diagnostics), flush=True) raise RuntimeError('Graphics probe failed; diagnostics remain private') report = reports[0] validate_shader_report(report, args.shaders) if report['observed_mode'] != ('world' if args.world else 'title') or report['ready_client_ticks'] < 40: raise AssertionError('Client never reached the requested graphics scene') if report['overlay_present'] is not False: raise AssertionError('Client graphics scene still has a loading overlay') if args.world: if report['world_loaded'] is not True or report['window_active'] is not True: raise AssertionError('Client never reached focused demo-world gameplay') if not list((instance / 'saves/Demo_World').rglob('*.dat')): raise AssertionError('Disposable world did not leave saved data') if report['sampled_pixels'] < 256 or report['distinct_sampled_rgb'] < 8: raise AssertionError('GPU readback was uniform') if hashlib.sha256((instance / 'mods' / mod.name).read_bytes()).hexdigest() != original_hash: raise AssertionError('Runtime original mod differs from the intended build') screenshot = instance / 'client-graphics-private.png' if not screenshot.is_file() or hashlib.sha256(screenshot.read_bytes()).hexdigest() != report['private_png_sha256']: raise AssertionError('Private screenshot evidence is missing or changed') report.update(profile=profile, preferred_backend=args.backend or build_pack.PROFILES[profile].get('backend', 'opengl'), launcher_exit_code=run.returncode, backend_attempts=attempts) results.append(report) print(json.dumps(report), flush=True) output = root / 'dist/client-graphics-smoke.json' output.write_text(json.dumps({'schema': 1, 'platform': platform.platform(), 'architecture': platform.machine(), 'minecraft': '26.3', 'original_mod_sha256': original_hash, 'results': results, 'limits': ['Short scene startup and nonuniform framebuffer readback only.', 'World mode uses the ordinary limited demo; world files remain private.', 'No exhaustive gameplay, visual-correctness, FPS or M2 Pro performance claim.', 'Vulkan preference can fall back; inspect the observed backend.', 'PNG images, assets and full logs remain in the private runtime directory.']}, indent=2) + '\n') print('Client graphics startup/readback checks passed.', flush=True) if __name__ == '__main__': main()