swayfx-mosaic/tooling/probes/step20c-corec-v2/graphics/gpu_handler.py

83 lines
6.2 KiB
Python

"""Narrow wiring of frozen G2 adapter to graphics Session. No native execution at import."""
import importlib,sys,json,re
from pathlib import Path
from engine import Session
from gate import need,sha
def validate_source_binding(lab,review):
need(review.get('gpu_source_review')=='ACCEPTED' and review.get('gl_observability_preflight')=='ACCEPTED' and review.get('native_gl_status')=='NOT_RUN' and review.get('build_review')=='ACCEPTED' and review.get('pair')==3,'G2 independent source/GL/build3 acceptance missing')
manifest=Path(review.get('gpu_source_manifest',''));need(manifest.is_absolute() and manifest.resolve()==manifest and manifest.is_relative_to(lab),'G2 canonical reviewed source manifest path')
expected=review.get('gpu_source_manifest_sha256','')
need(re.fullmatch('[0-9a-f]{64}',expected) and expected==sha(manifest),'G2 exact reviewed source freeze')
m=json.loads(manifest.read_text());root=lab/'gpu-kit'
# WHY/CONTRACT/INVARIANT: external source remains frozen; its adapter is
# imported only after actual byte validation, never by a status string alone.
files=m['files']
for rel,h in files.items():
p=lab/rel;need(not Path(rel).is_absolute() and p.resolve().is_relative_to(lab) and sha(p)==h['sha256'] and p.stat().st_size==h['bytes'],'G2 frozen source changed')
need({str(p.relative_to(root)) for p in root.rglob('*') if p.is_file()}=={str(Path(rel).relative_to('gpu-kit')) for rel in files if Path(rel).parts[0]=='gpu-kit'},'G2 source addition/removal')
for key in ('gpu_source_review','gl_observability_preflight','build_review'):
path=Path(review[key+'_receipt']);need(path.resolve().is_relative_to(lab) and sha(path)==review[key+'_receipt_sha256'],'G2 review receipt bytes')
binding=review['binding'];client=Path(binding['client']);need(client.resolve().is_relative_to(lab) and sha(client)==binding['client_sha256'],'G2 reviewed client bytes')
gatefile=Path(review['gate_file']);need(gatefile.resolve().is_relative_to(lab) and sha(gatefile)==review['gate_file_sha256'],'G2 native external gate bytes')
# WHY: the frozen adapter's legacy PASS admits instrumentation capability,
# not an observation made before its first native epoch. CONTRACT/INVARIANT:
# require explicit scope and retain native NOT_RUN until measured metadata.
native_gate=json.loads(gatefile.read_text())
need(native_gate.get('gl_observability')=='PASS' and native_gate.get('gl_observability_scope')=='PREFLIGHT_CAPABILITY_ONLY' and native_gate.get('native_gl_status')=='NOT_RUN','G2 legacy PASS must be scoped preflight only')
def modules(lab):
path=str(lab/'gpu-kit');sys.path.insert(0,path)
try:
# These names have no graphics-kit peer; source freeze includes both.
protocol=importlib.import_module('protocol');scenario=importlib.import_module('scenario')
need(Path(protocol.__file__).resolve()==lab/'gpu-kit/protocol.py' and Path(scenario.__file__).resolve()==lab/'gpu-kit/scenario.py','G2 module origin')
return scenario
finally:sys.path.remove(path)
class CompositorEnvironment:
def __init__(self,session):self.session=session
def update(self,**fields):
need(set(fields)=={'MOSAIC_G2_DIR','MOSAIC_G2_NONCE','WLR_RENDERER'},'G2 compositor environment scope')
need(fields['MOSAIC_G2_DIR']==str(self.session.lab/'gpu-work/acquisition') and re.fullmatch('[0-9a-f]{64}',fields['MOSAIC_G2_NONCE']) and fields['WLR_RENDERER']=='gles2','G2 acquisition environment')
self.session.compositor_environment=fields
class AdapterSession:
"""Compatibility view of pair#3, without changing the actual Session spec.
WHY: frozen adapter calls its static SceneFX branch 'core'. CONTRACT: real
identity/admission remain gpu; no other binary or environment is translated.
"""
def __init__(self,session):
need(session.spec['id']=='G2' and session.spec['binary']=='gpu','G2 real Session identity')
self.session=session;self.spec=dict(session.spec,binary='core');self.env=CompositorEnvironment(session)
def __getattr__(self,name):return getattr(self.session,name)
def debit(self,*kinds):
need(kinds==('mutation',),'unexpected direct G2 adapter debit')
# Each explicit epoch reservation precedes arm, without retry/refund.
self.session.debit('mutation','hook')
def spawn(self,name,argv,debug=False):
need(name in ('g2-reference','g2-background','g2-glass'),'G2 client role')
return self.session.spawn(name,argv,True)
class GPUSceneSession(Session):
def close_client(self,name,command='close'):
need(name in ('g2-reference','g2-background','g2-glass') and command=='close','G2 scientific closure role')
try:
super().close_client(name,command)
proof=self.closed[-1];raw=self.log(name)
mode='background' if name=='g2-background' else 'glass' if name=='g2-glass' else 'reference'
need(re.search(rf'EXIT ns=\d+ mode={mode} error=0 commits=\d+',raw),'G2 exact client role/raw error')
role='zwlr_layer_surface_v1' if mode=='background' else 'xdg_toplevel'
need(re.search(rf'{role}#\d+\.destroy\(\)',raw) and re.search(r'wl_surface#\d+\.destroy\(\)',raw),'G2 native role destruction')
proof.update(role=role,scientific_client=True,meaning='layer closure without invented XDG ownership' if mode=='background' else 'G2 XDG closure')
except Exception as error:
if self.closed and self.closed[-1]['pid']==self.proc[name].pid:self.closed[-1].update(status='INCONCLUSIVE',failure=str(error))
raise
def run(s):
review=s.auth['prospective'];validate_source_binding(s.lab,review)
binding=dict(review['binding'],nonce=s.auth['token']*2)
need(binding['source_manifest_sha256']==s.auth['manifest_sha256'] and binding['binary']==s.auth['binary'] and binding['gate_file']==review['gate_file'],'G2 exact reviewed reservation/binary/gate binding')
result=modules(s.lab).run(AdapterSession(s),dict(binding,G2_ledger_reserved=True))
need(result['native_source_A_Areturn_exact'] and result['whole_H1_A_Areturn']['equal'] and all(v['equal'] for v in result['whole_H2_A_B_Areturn']),'G2 measured return mismatch')
return 'PARTIALLY_FEASIBLE'