--- historical/validate.py +++ recovery/validate.py @@ -1 +1 @@ -"""EXPERIMENTAL G1 runtime validator; importable offline, no launch or writer. +"""EXPERIMENTAL modifier-aware OFFLINE G1 validator; importable offline, no launch or writer. @@ -43 +43 @@ - need(o['dimensions']==[800,600] and all(o[k] for k in ('fx','wlr','fbo','rbo')),'existing physical object') + need(o['dimensions']==[800,600] and all(o[k] for k in ('fx','wlr','fbo','rbo','image')) and type(o['tex']) is int and o['tex'] >= 0,'existing physical object') @@ -46 +46,41 @@ - need(len(o['modifier'])==16 and all(len(p)==2 and p[0]>=800*4 and p[1]>=0 for p in o['planes']),'dmabuf fields') + return validate_planes(o) + + +AMD_G1_MODIFIER = '020000001046bb04' +UINT32_MAX = (1 << 32) - 1 + + +def validate_planes(o): + """Bounded metadata sanity, not a proof of allocation extent or DCC layout. + + drm_fourcc.h SHA992f3380...: packed RGB has one image plane; + AMD DCC without RETILE adds one auxiliary plane. Only the observed AMD + modifier is allowlisted. No DCC size/alignment formula is inferred. + """ + modifier = o['modifier'] + need(isinstance(modifier, str) and len(modifier) == 16 + and all(c in '0123456789abcdef' for c in modifier), 'modifier encoding') + need(modifier in ('0000000000000000', AMD_G1_MODIFIER), 'unknown modifier') + planes = o['planes'] + need(len(planes) == (2 if modifier == AMD_G1_MODIFIER else 1), 'modifier plane count') + for p in planes: + need(isinstance(p, list) and len(p) == 2 + and all(type(n) is int and 0 <= n <= UINT32_MAX for n in p), + 'pitch/offset uint32 fields') + need(p[0] > 0 and p[1] + p[0] <= UINT32_MAX, 'nonzero pitch/offset overflow') + pitch, offset = planes[0] + need(pitch >= WIDTH * 4 and pitch % 4 == 0, 'packed image stride') + image_end = offset + pitch * HEIGHT + need(image_end <= UINT32_MAX, 'image extent overflow') + if modifier == AMD_G1_MODIFIER: + aux_pitch, aux_offset = planes[1] + # This fixture only accepts a single-allocation, image-before-aux layout. + # Exported FD identity/allocation lengths are absent: this is an explicit + # bounded sanity restriction, not a universal DRM modifier requirement. + need(aux_offset >= image_end and aux_offset > offset + and planes[0] != planes[1], 'auxiliary offset/duplicate sanity') + return dict(layout='AMD_GFX11_DCC_NO_RETILE', image_stride='PASS', + auxiliary_fields='PLAUSIBLE_ONLY', auxiliary_extent='NOT_PROVEN', + allocation_bounds='NOT_PROVEN', fd_identity='NOT_OBSERVED') + return dict(layout='LINEAR_PACKED', image_stride='PASS', + allocation_bounds='NOT_PROVEN') @@ -151,0 +192,51 @@ + + +def validate_g1_envelope(rows, samples, context): + """Additional exact G1 native protocol checks, independent of uniform equality. + + A successful envelope never substitutes for validate_epoch/validate_writes. + In particular the observed halfpixel mismatch remains a strict rejection. + """ + writes = [r for r in rows if r['kind'] == 'write'] + copies = [r for r in rows if r['kind'] == 'copy'] + need(len(writes) == 11 and len(copies) == 2, 'G1 eleven writes/two copies') + need([r['sequence'] for r in writes] == list(range(1, 12)), 'G1 ordered writes') + need([r['stage'] for r in writes] == list(range(6)) + [-1] * 5, 'G1 stage sequence') + for r in writes: + need(r['fbo'] == r['read_fbo'] and r['context'] == context + and r['viewport'] == [0, 0, WIDTH, HEIGHT], 'G1 draw bindings/context') + need(r['texture'] > 0 and r['program'] > 0 and r['color_mask'] == [1]*4 + and r['stencil'] == r['scissor_enabled'] == 0, 'G1 raster state') + need(r['sampler'] in ([9729,9729,33071,33071], [9728,9728,33071,33071]), + 'G1 effective sampler') + uniforms = r['uniforms'] + names = [u['name'] for u in uniforms] + need(len(names) == len(set(names)) and all(n in names for n in ('tex','proj','tex_proj')), + 'G1 unique sampler/matrix uniforms') + u = {u['name']:u for u in uniforms} + need(u['tex']['type'] == 35678 and u['tex']['value'] == [0], 'G1 sampler texture unit') + need(all(u[n]['type'] == 35675 and len(u[n]['value']) == 9 for n in ('proj','tex_proj')), + 'G1 matrix type/size') + need(all(type(b) is int and 0 <= b <= UINT32_MAX + for x in uniforms for b in x['value']), 'G1 uniform bit encoding') + if r['stage'] >= 0: + need(u['radius']['type'] == 5126 and u['halfpixel']['type'] == 35664 + and len(u['halfpixel']['value']) == 2, 'G1 blur uniform types') + else: + need(u['alpha']['value'] == [1065353216] and u['discard_transparent']['value'] == [0], + 'G1 copy/composition uniforms') + for c, seq, src in zip(copies, (7,8), (samples[6]['object'], samples[0]['object'])): + validate_object(c['src'], 'main') + validate_object(c['dst'], 'main') + w = writes[seq-1] + need(object_identity(c['src']) == object_identity(src) + and w['fbo'] == c['dst']['fbo'] and w['texture'] == c['src']['tex'] + and w['region'] == c['region'] == [[0,0,WIDTH,HEIGHT]], 'G1 copy continuity') + need(rows.index(w) < rows.index(c), 'G1 copy follows raster write') + need(rows.index(copies[0]) < rows.index(samples[7]) < rows.index(writes[7]) + and rows.index(writes[-1]) < rows.index(samples[8]), 'G1 copy/sample order') + need(writes[8]['region'] == [[0,0,480,600]] + and writes[9]['region'] == writes[10]['region'] == [[480,0,800,600]] + and all(w['fbo'] == samples[8]['object']['fbo'] for w in writes[8:]), + 'G1 final composition regions/target') + return dict(writes=11, copies=2, status='STRUCTURAL_ONLY') --- historical/test_fixture.py +++ recovery/test_fixture.py @@ -108,22 +107,0 @@ -class Controller(unittest.TestCase): - def test_durable_one_shot_arm(self): - import runner - with tempfile.TemporaryDirectory() as tmp: - d=Path(tmp) - runner.arm(d,1,'A');self.assertEqual((d/'epoch-1.arm').read_bytes(),b'A\n') - with self.assertRaises(v.Rejected):runner.arm(d,1,'A') - with self.assertRaises(v.Rejected):runner.arm(d,2,'B') - with self.assertRaises(v.Rejected):runner.arm(d,4,'A') - with self.assertRaises(v.Rejected):runner.arm(d,2,'A') - def test_real_SHM_validator_mismatch(self): - import runner - with tempfile.TemporaryDirectory() as tmp: - d=Path(tmp);log=[] - for i,colors in enumerate(('00101010,00202020','00303030,00404040','00101010,00202020'),1): - cs=[int(x,16) for x in colors.split(',')];raw=b''.join(struct.pack('