b
This commit is contained in:
parent
b653d77d4e
commit
83b874c2a0
9 changed files with 1831 additions and 183 deletions
39
tests/KERNEL_HASHES_V24_3_0.json
Normal file
39
tests/KERNEL_HASHES_V24_3_0.json
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"version": "7d56b1b4e3b54eff64b84e98607abb32eb23ae3ab60e1cd6f66f3223993d8c9f",
|
||||
"DIRECT_F32_WGSL": "7146fb3a0969a4f29b3e47d194e5263f8f7da017d84dcf98bddcb29d3c057922",
|
||||
"ACTIVE_PREPARE_WGSL": "27bb3af8310bd0784888f2a648896e1fcf5872b4a9a3ade883ebe95a4868fa6e",
|
||||
"DIRECT_ACTIVE_INIT_WGSL": "a57887e12e91ecdc0272c97e2097268f4b5f05cb467e8a77adfc5263331b2b9b",
|
||||
"DIRECT_ACTIVE_CONTINUE_WGSL": "b0fbfcb9ffccf37b96947ec21c883ad4ce984bbb331c7a3b59a54cdc3e300f93",
|
||||
"ACTIVE_COMPARE_WGSL": "81c37558fd8937fd0560ccb41f73ed66ac5d98d023153ed0b82d8b5a075c3de9",
|
||||
"DIRECT_ACCURATE_SEED_WGSL": "247e1ff1c3d400daf358144b55c6f50c99d337b4e886e0b957e371d39f9c87cf",
|
||||
"DIRECT_DS_CORRECT_WGSL": "e31fa2f8347acc5ea2eb11bbcb3b05a36a3ba72cc1446ded141b1b4207b873e3",
|
||||
"DIRECT_DS_QUEUE_BUILD_WGSL": "95cfcf9cb80e53bd112b0868c035564cb812bdd957de583e2d3ee052bceb1a15",
|
||||
"DIRECT_DS_CORRECT_QUEUE_WGSL": "bb76e1ae09c7494a53e2ae4cad46807f2c671c5afa5bf5649981e1ab60cc2f3e",
|
||||
"FAST_PERTURB_WGSL": "2cc5841740456f10ed3f64005e72ac6ff87d2c38926260a1fcb1521a389013a0",
|
||||
"FAST_PERTURB_POSTSTATS_WGSL": "3680d561d80af6327640d9b5caa127ad67f6a6fc9e499af6dbb98ccdaa261d0c",
|
||||
"DEEP_PERTURB_WGSL": "a631d814fd1c1aa3d4f8af31dcbabaebc5795355e9d72a223a000beb16f96a65",
|
||||
"DEEP_PERTURB_POSTSTATS_WGSL": "364d916da3d90b049ac24423a8112dd587ebd756fa97c99a6717f869c6b6cfa1",
|
||||
"DEEP_ACTIVE_INIT_WGSL": "756373375ad9b21a884ac6906ecf72990612a86ecfde77caf5150fb37cf75604",
|
||||
"DEEP_ACTIVE_RESUME_INIT_WGSL": "a25c0b74bc66b7b91269bc6195ddde8b295f659ea72ec415fcf3fda3d66c126e",
|
||||
"DEEP_ACTIVE_CONTINUE_WGSL": "afe49e748e34d78c01090015c0e2ce5971c0ec6ab7587bba6c25631266acb4f0",
|
||||
"PERTURB_CERTIFIED_INTERIOR_WGSL": "3bd61a7f5cf96e4e52797f5f00a20c848a01fd3ff8eca9a939e8ae87f37568a5",
|
||||
"DEEP_BUCKET_HIST_WGSL": "3458f908fa239b16667e5c82dae25274d5493d647595230574a3d65622a54aaf",
|
||||
"DEEP_BUCKET_HIST_STATS_WGSL": "b464d503703646e3c990e10a0cb40dacdc3677447b7a35e03c80a50bfca23824",
|
||||
"DEEP_BUCKET_PREFIX_WGSL": "e8fb3f566d69ef87a61f1aa61f4c56ec26614711d7897afa2f8bfdcf5088c3da",
|
||||
"DEEP_BUCKET_SCATTER_WGSL": "7575c4fc5f4d5674dfc3997189212ffc6fbe240a9d8b8b3f8ef883cd4eae47a1",
|
||||
"DEEP_CORRECT_WGSL": "112d09df6e7fa9b7aab9e43da2f38c9b0aad45e44296f40054d0e9a7c6077b88",
|
||||
"DEEP_CORRECT_QUEUE_WGSL": "1580c6bab7d1aa2c4eb2c7e8d6f3cc4d32b90b86b9264561269e1857d2826bae",
|
||||
"UNKNOWN_STATS_WGSL": "df1967bcdacf29831403fa53aadaae17ed138b36d1988cf20f6a6ed3e43e519a",
|
||||
"SYMMETRY_COPY_WGSL": "658e1cf2b9f40d8e759abe2269c041f582a80727cb24e2f48a405cb8676d70e1",
|
||||
"FAILURE_TILE_MAP_WGSL": "8308f57151b119363ad456a7e1255c5445ed5e022ccf53e923a4b13ab2a1ca91",
|
||||
"COLOR_WGSL": "4ef141430a5255cc8b78459b1a50fdd2ff31cf37eeb872a957d43794c59b09a3",
|
||||
"AA_RESOLVE_WGSL": "f353adafc837c170da1627f8b0cfd924d9748954376e4a427190917da4c92342",
|
||||
"PRESENT_WGSL": "651bf13de25b023c3f0ab0d0287b1d27cfd8e11677aca53629ce0a8526c7c5bc",
|
||||
"BLA_GPU_SHADOW_WGSL": "e830339a150dd5722ca7c58674193174606adaf488bfd817408f2eeb4583514f",
|
||||
"BLA_GPU_CANARY_WGSL": "3c219f657b2890b40f7cfa0297e13a670819d4fed333fcb30cb37196c5755f55",
|
||||
"BLA_GPU_CANARY_APPLY_WGSL": "d02bb3ef007680a687960125ee9dded1fc4b8a4b091a6d924408a2e1f94a05e1",
|
||||
"BLA_GPU_FAST_CANDIDATE_WGSL": "2a1d2d6ee1fe2ecc55822e58131519f1385d82bcdbd7fc852dc2e39d67ff0019",
|
||||
"BLA_GPU_FAST_REPLAY_CANDIDATE_WGSL": "f55368ed55cda77af550ed2bf38b4027b21e08b6c17d67997e61fcbea17a6c84",
|
||||
"BLA_GPU_FAST_FRAME_WGSL": "1d4f2c2105f0c50a3b5fb1368b262cfe6e0114e20333acdd1b6d8e8093434290",
|
||||
"BLA_GPU_FAST_FRAME_POSTSTATS_WGSL": "6e1d0ac58a1b785075eddb525f565ca8349f50bab2189a537f62bec6a987f6ea"
|
||||
}
|
||||
31
tests/OPTIMIZATION_BENCHMARK.json
Normal file
31
tests/OPTIMIZATION_BENCHMARK.json
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"date": "2026-08-25",
|
||||
"scope": "BigInt reference-worker recurrence only; not a browser, GPU, canvas, or end-to-end benchmark",
|
||||
"runtime": "Node worker model",
|
||||
"corpus": {
|
||||
"points": 240,
|
||||
"iterations": 700,
|
||||
"precisionBits": "192..320",
|
||||
"runs": 7
|
||||
},
|
||||
"equivalence": {
|
||||
"checksumMismatch": 0,
|
||||
"separateStateRegressionCases": 2000,
|
||||
"separateStateRegressionMismatch": 0
|
||||
},
|
||||
"median": {
|
||||
"oldMs": 201.5509,
|
||||
"newMs": 115.3558,
|
||||
"speedup": 1.7472,
|
||||
"timeReduction": 0.4277
|
||||
},
|
||||
"runs": [
|
||||
{"oldMs": 222.9260, "newMs": 137.0568},
|
||||
{"oldMs": 206.2790, "newMs": 113.4711},
|
||||
{"oldMs": 218.0533, "newMs": 146.6120},
|
||||
{"oldMs": 201.5509, "newMs": 120.1586},
|
||||
{"oldMs": 163.7775, "newMs": 115.3558},
|
||||
{"oldMs": 166.6713, "newMs": 111.5755},
|
||||
{"oldMs": 172.1890, "newMs": 107.0833}
|
||||
]
|
||||
}
|
||||
55
tests/edge_cdp_gate.mjs
Normal file
55
tests/edge_cdp_gate.mjs
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
import process from 'node:process';
|
||||
|
||||
const port=Number(process.argv[2]||9333);
|
||||
const url=process.argv[3]||'file:///C:/Users/%E3%81%82/Desktop/mandelbrot/index.html?frontier-gate=reset';
|
||||
const timeoutMs=Number(process.argv[4]||300000);
|
||||
const sleep=ms=>new Promise(resolve=>setTimeout(resolve,ms));
|
||||
|
||||
async function endpoint(path,options){
|
||||
const response=await fetch(`http://127.0.0.1:${port}${path}`,options);
|
||||
if(!response.ok)throw new Error(`CDP HTTP ${response.status}: ${await response.text()}`);
|
||||
return response.json();
|
||||
}
|
||||
|
||||
const deadline=Date.now()+timeoutMs;
|
||||
let version;
|
||||
while(Date.now()<deadline){
|
||||
try{version=await endpoint('/json/version');break}catch{await sleep(100)}
|
||||
}
|
||||
if(!version)throw new Error('Edge remote debugging endpoint did not start');
|
||||
|
||||
let target;
|
||||
try{target=await endpoint(`/json/new?${encodeURIComponent(url)}`,{method:'PUT'})}
|
||||
catch{const targets=await endpoint('/json/list');target=targets.find(item=>item.type==='page')}
|
||||
if(!target?.webSocketDebuggerUrl)throw new Error('No debuggable page target');
|
||||
|
||||
const ws=new WebSocket(target.webSocketDebuggerUrl);
|
||||
await new Promise((resolve,reject)=>{ws.addEventListener('open',resolve,{once:true});ws.addEventListener('error',reject,{once:true})});
|
||||
let sequence=0;
|
||||
const pending=new Map();
|
||||
ws.addEventListener('message',event=>{
|
||||
const message=JSON.parse(event.data);
|
||||
if(!message.id)return;
|
||||
const waiter=pending.get(message.id);if(!waiter)return;
|
||||
pending.delete(message.id);
|
||||
if(message.error)waiter.reject(new Error(JSON.stringify(message.error)));else waiter.resolve(message.result);
|
||||
});
|
||||
function command(method,params={}){
|
||||
const id=++sequence;
|
||||
return new Promise((resolve,reject)=>{pending.set(id,{resolve,reject});ws.send(JSON.stringify({id,method,params}))});
|
||||
}
|
||||
|
||||
await command('Runtime.enable');
|
||||
await command('Page.enable');
|
||||
await command('Page.navigate',{url});
|
||||
let result;
|
||||
while(Date.now()<deadline){
|
||||
const evaluated=await command('Runtime.evaluate',{expression:`JSON.stringify({gate:document.documentElement.getAttribute('data-frontier-gate'),body:document.body?.textContent||'',href:location.href})`,returnByValue:true});
|
||||
const value=JSON.parse(evaluated.result.value);
|
||||
if(value.gate){result=value;break}
|
||||
await sleep(250);
|
||||
}
|
||||
try{await command('Browser.close')}catch{}
|
||||
ws.close();
|
||||
if(!result)throw new Error('Frontier gate timed out');
|
||||
process.stdout.write(JSON.stringify(result));
|
||||
306
tests/optimization_regression.mjs
Normal file
306
tests/optimization_regression.mjs
Normal file
|
|
@ -0,0 +1,306 @@
|
|||
import assert from 'node:assert/strict';
|
||||
import crypto from 'node:crypto';
|
||||
import fs from 'node:fs/promises';
|
||||
import vm from 'node:vm';
|
||||
import {fileURLToPath} from 'node:url';
|
||||
import {correctnessCases,performanceCases,interactionStabilityViews,productionPerformanceThresholds,evaluateProductionPerformance,runCorrectnessCorpus,runPerformanceCorpus,runInteractionStabilityCorpus} from './optimization_webgpu_corpus.mjs';
|
||||
|
||||
const root=fileURLToPath(new URL('../',import.meta.url));
|
||||
const html=await fs.readFile(new URL('../index.html',import.meta.url),'utf8');
|
||||
const scripts=[...html.matchAll(/<script[^>]*>([\s\S]*?)<\/script>/g)].map(m=>m[1]);
|
||||
assert.equal(scripts.length,2);
|
||||
for(const code of scripts)new vm.Script(code);
|
||||
const precisionWorker=scripts[1].match(/function precisionFallbackWorkerSource\(\)\{return String\.raw`([\s\S]*?)`\}/);
|
||||
assert.ok(precisionWorker);
|
||||
new vm.Script(precisionWorker[1]);
|
||||
|
||||
const context={globalThis:null};context.globalThis=context;vm.createContext(context);
|
||||
new vm.Script(scripts[0]).runInContext(context);
|
||||
const kernels=context.MANDEL_WEBGPU_KERNELS;
|
||||
const expected=JSON.parse(await fs.readFile(new URL('./KERNEL_HASHES_V24_3_0.json',import.meta.url),'utf8'));
|
||||
const actual={};
|
||||
for(const [key,value] of Object.entries(kernels)){
|
||||
if(typeof value==='string')actual[key]=crypto.createHash('sha256').update(value).digest('hex');
|
||||
}
|
||||
assert.deepEqual(actual,expected);
|
||||
assert.equal(correctnessCases.length,12);
|
||||
assert.equal(performanceCases.length,6);
|
||||
assert.equal(interactionStabilityViews.length,3);
|
||||
assert.ok(correctnessCases.some(x=>x.id==='reported-black-regression'&&x.fixed&&x.frontierCheck));
|
||||
assert.ok(correctnessCases.some(x=>x.id==='moderate-1e5-fast'));
|
||||
assert.ok(correctnessCases.some(x=>x.id==='moderate-1e5-accurate'));
|
||||
assert.ok(correctnessCases.some(x=>x.id==='moderate-1e8-fast'));
|
||||
assert.ok(correctnessCases.some(x=>x.id==='moderate-1e8-accurate'));
|
||||
assert.ok(performanceCases.some(x=>x.id==='fast-1e14-800x600'&&x.absoluteP95Ms<2000));
|
||||
assert.equal(productionPerformanceThresholds.targetP50Reduction,.20);
|
||||
assert.equal(productionPerformanceThresholds.targetP95Reduction,.15);
|
||||
assert.equal(typeof runCorrectnessCorpus,'function');
|
||||
assert.equal(typeof runPerformanceCorpus,'function');
|
||||
assert.equal(typeof runInteractionStabilityCorpus,'function');
|
||||
assert.equal(evaluateProductionPerformance({records:[{id:'target',target:true,summary:{recovery:{p50:79,p95:84}}}]},{records:[{id:'target',summary:{recovery:{p50:100,p95:100}}}]}).pass,true);
|
||||
assert.equal(evaluateProductionPerformance({records:[{id:'target',target:true,summary:{recovery:{p50:90,p95:90}}}]},{records:[{id:'target',summary:{recovery:{p50:100,p95:100}}}]}).pass,false);
|
||||
const corpusSource=await fs.readFile(new URL('./optimization_webgpu_corpus.mjs',import.meta.url),'utf8');
|
||||
assert.match(corpusSource,/assert\.equal\(result\.numericComplete,true/);
|
||||
assert.match(corpusSource,/assert\.equal\(numeric,0,testCase\.id\+' final numeric UNKNOWN'/);
|
||||
assert.match(corpusSource,/assert\.equal\(result\.state\.historyReady,true/);
|
||||
assert.match(corpusSource,/assert\.equal\(compile\.productionEligible,expectProduction\)/);
|
||||
assert.match(corpusSource,/assert\.equal\(compile\.candidateEnabled,true\)/);
|
||||
assert.match(corpusSource,/await t\.waitForNumericComplete\(\{timeout\}\)/);
|
||||
|
||||
assert.match(kernels.DIRECT_ACCURATE_SEED_WGSL,/if\(n>=p\.lateThreshold\)\{fieldMeta\[out\]=pack_unknown/);
|
||||
assert.match(kernels.DIRECT_DS_CORRECT_WGSL,/var zr2=DS\(0\.0,0\.0\);var zi2=DS\(0\.0,0\.0\)/);
|
||||
assert.match(kernels.DIRECT_DS_QUEUE_BUILD_WGSL,/atomicAdd\(&queueStats\[2\],1u\)/);
|
||||
assert.match(kernels.DIRECT_DS_CORRECT_QUEUE_WGSL,/atomicAdd\(&queueStats\[6\],1u\)/);
|
||||
assert.match(kernels.DIRECT_DS_CORRECT_QUEUE_WGSL,/let zri=ds_mul\(zr,zi\)/);
|
||||
assert.match(html,/accurateQueuedPixels/);
|
||||
assert.match(html,/q\.selected===q\.enqueued&&q\.enqueued===q\.dispatchCount&&q\.dispatchCount===q\.processed/);
|
||||
assert.match(html,/accurateQueueFallbacks/);
|
||||
assert.match(html,/encodeDeepBucketHistogram\(e/);
|
||||
assert.match(html,/q\.selected===q\.enqueued&&q\.enqueued===q\.dispatchCount&&q\.dispatchCount===q\.processed/);
|
||||
assert.match(html,/reusePreview/);
|
||||
assert.match(html,/canUseStableReprojection\(\)\|\|fastNeedsExtended\(snapshot\(\),canvas\.width\)\)return\[finalIter\]/);
|
||||
assert.match(html,/numericInFlightBudgetMs/);
|
||||
assert.match(html,/const ADAPTIVE_ITER_QUANTUM=64/);
|
||||
assert.match(html,/function pixelPrecisionBits\(snap=snapshot\(\),w=canvas\.width,guard=32\)/);
|
||||
assert.match(html,/pixelLog2=log2FixedAt\(snap\.span,snap\.bits\)-Math\.log2\(Math\.max\(1,w\)\)/);
|
||||
assert.match(html,/targetBits=pixelPrecisionBits\(snap,width,40\)/);
|
||||
assert.match(html,/function fastReferenceBits\(snap,w=canvas\.width\)\{return pixelPrecisionBits\(snap,w,32\)\}/);
|
||||
assert.match(html,/const bits=baseBits\+attempt\*32,a=pixel\(s,indices\[i\],bits\),b=pixel\(s,indices\[i\],bits\+32\)/);
|
||||
assert.match(html,/for\(let attempt=0;attempt<4&&!accepted\[i\];attempt\+\+\)/);
|
||||
assert.match(html,/for\(let i=0;i<meta\.length;i\+\+\)/);
|
||||
assert.match(html,/for\(let start=0;start<indices\.length;start\+=chunkSize\)/);
|
||||
assert.doesNotMatch(html,/UNRESOLVED_BLACK_MIN_ZOOM_EXP|colorUnresolvedInsteadOfBlack|guardedFastDeep|fast-quality-floor-before-1e100/);
|
||||
assert.match(html,/Math\.ceil\(raw\/quantum\)\*quantum/);
|
||||
assert.match(html,/this\.blaFastDisabled=true;this\.blaFastOptIn=false/);
|
||||
assert.doesNotMatch(html,/deep-stable-bootstrap|forceStableDeep/);
|
||||
assert.match(html,/A FAST frame is not publishable while any numeric UNKNOWN remains/);
|
||||
assert.match(html,/if\(initialFailed>0\)\{const mr=await recoverNumericalUnknownTiles/);
|
||||
assert.match(html,/if\(numericalFailureCount\(stats\)>0\)\{const pf=await recoverResidualPrecision/);
|
||||
assert.match(html,/if\(isFinal\)\{const remaining=numericalFailureCount.*frameを公開しません/);
|
||||
assert.match(html,/viewRe:snap\.re,viewIm:snap\.im/);
|
||||
assert.match(html,/function referenceOriginMatchesView\(/);
|
||||
assert.match(html,/!referenceOriginMatchesView\(src,snap\)/);
|
||||
assert.match(html,/stabilityPolicy:/);
|
||||
assert.match(html,/fastBackgroundDeepOnFailureOnly:true,deepProductionActive:false,deepCorrectionDispatchWork:PIXEL_FRONTIER_WORK/);
|
||||
const fastStableStart=html.indexOf('}else if(isFinal&&fastExtended){');
|
||||
const fastStableSource=html.slice(fastStableStart,html.indexOf('}else if(isFinal){',fastStableStart));
|
||||
assert.doesNotMatch(fastStableSource,/scheduleFastNumericRecovery/);
|
||||
assert.match(fastStableSource,/recoverNumericalUnknownTiles/);
|
||||
assert.match(fastStableSource,/recoverResidualPrecision/);
|
||||
assert.match(html,/ensureAccuratePipelines/);
|
||||
assert.match(html,/ensureCorrectionPipelines/);
|
||||
assert.match(html,/precisionFallbackWorkerSource/);
|
||||
assert.match(html,/recoverResidualPrecision/);
|
||||
assert.match(html,/estimatedNetMs/);
|
||||
assert.match(kernels.BLA_GPU_FAST_REPLAY_CANDIDATE_WGSL,/fn baseline_from\(s0:S,pre:u32\)->Result/);
|
||||
assert.match(kernels.BLA_GPU_FAST_REPLAY_CANDIDATE_WGSL,/var anchor=s;loop/);
|
||||
assert.match(kernels.BLA_GPU_FAST_REPLAY_CANDIDATE_WGSL,/anchor=s;\}\}/);
|
||||
assert.doesNotMatch(kernels.BLA_GPU_FAST_REPLAY_CANDIDATE_WGSL,/baseline\(g,st\)/);
|
||||
assert.equal((kernels.BLA_GPU_FAST_REPLAY_CANDIDATE_WGSL.match(/baseline_from\(anchor,st\)/g)||[]).length,7);
|
||||
assert.ok(kernels.BLA_GPU_FAST_FRAME_WGSL.includes('baseline_from(anchor,st)'));
|
||||
assert.match(kernels.ACTIVE_PREPARE_WGSL,/indirect\[0\]=\(n\+63u\)\/64u/);
|
||||
assert.match(kernels.DIRECT_ACTIVE_CONTINUE_WGSL,/struct DirectState\{zr:f32,zi:f32,n:u32/);
|
||||
assert.match(kernels.DIRECT_ACTIVE_CONTINUE_WGSL,/atomicLoad\(&countIn\[0\]\)/);
|
||||
assert.match(kernels.DEEP_ACTIVE_CONTINUE_WGSL,/struct DeepState\{d:vec2<f32>,w:vec2<f32>,scaleExp:i32,n:u32,m:u32,errScaled:f32\}/);
|
||||
assert.match(kernels.DEEP_ACTIVE_INIT_WGSL,/states\[local\]=DeepState/);
|
||||
assert.match(kernels.DEEP_ACTIVE_CONTINUE_WGSL,/let out=p\.outputBase\+\(local\/p\.tileW\)\*p\.outputStride/);
|
||||
assert.match(kernels.DEEP_ACTIVE_CONTINUE_WGSL,/if\(s\.m>p\.refLen\)/);
|
||||
assert.match(kernels.DEEP_ACTIVE_CONTINUE_WGSL,/if\(s\.m>=p\.refLen\)/);
|
||||
assert.match(kernels.PERTURB_CERTIFIED_INTERIOR_WGSL,/struct I\{lo:f32,hi:f32\}/);
|
||||
assert.match(kernels.PERTURB_CERTIFIED_INTERIOR_WGSL,/fn outward\(/);
|
||||
assert.match(kernels.PERTURB_CERTIFIED_INTERIOR_WGSL,/lhs\.hi<rhs\.lo/);
|
||||
assert.match(kernels.PERTURB_CERTIFIED_INTERIOR_WGSL,/bulb\.hi<0\.0625/);
|
||||
assert.match(kernels.PERTURB_CERTIFIED_INTERIOR_WGSL,/if\(p\.refLen<1u\)\{proven\[i\]=0u;return;\}/);
|
||||
assert.match(kernels.PERTURB_CERTIFIED_INTERIOR_WGSL,/let ref=refs\[1u\]/);
|
||||
assert.match(html,/runDirectActiveShadow/);
|
||||
assert.match(html,/dispatchWorkgroupsIndirect\(indirect,0\)/);
|
||||
assert.match(html,/direct-active-shadow-resume/);
|
||||
assert.match(html,/resumedFromPreview:previewIter>0/);
|
||||
assert.match(html,/runDeepActiveShadow/);
|
||||
assert.match(html,/computeDeepActiveFrame/);
|
||||
assert.match(html,/workPerDispatch=PIXEL_FRONTIER_WORK,maxPassesPerSubmit=1/);
|
||||
assert.match(html,/const workBudget=deep\?4000000:48000000/);
|
||||
assert.match(html,/const PIXEL_FRONTIER_PRODUCTION=false,PIXEL_FRONTIER_WORK=4000000,PIXEL_FRONTIER_MAX_ITER=150000/);
|
||||
assert.match(html,/PIXEL_FRONTIER_CANDIDATE=.*frontier-gate/);
|
||||
assert.match(html,/PIXEL_FRONTIER_ENABLED=PIXEL_FRONTIER_PRODUCTION\|\|PIXEL_FRONTIER_CANDIDATE/);
|
||||
assert.match(html,/function operationLimitFrontier\(meta,w,h\)/);
|
||||
assert.match(html,/function pixelFrontierIterationFloor\(snap,w,initialIter\)/);
|
||||
assert.match(html,/iter>=minimumIter&&stableRounds>=2/);
|
||||
assert.match(html,/count\*iter/);
|
||||
assert.match(html,/pixel frontier queue invariant failed/);
|
||||
assert.match(html,/compareCurrentToFrontierBaseline/);
|
||||
assert.match(html,/productionEligible:PIXEL_FRONTIER_PRODUCTION/);
|
||||
assert.match(kernels.DEEP_CORRECT_QUEUE_WGSL,/bitcast<u32>\(p\._numeric2\)\+localQi/);
|
||||
assert.match(html,/const maxBatch=Math\.max\(1,Math\.floor\(PIXEL_FRONTIER_WORK\/Math\.max\(1,iter\)\)\);let offset=0/);
|
||||
assert.match(html,/this\.deepParams\(f\.w,f\.h,f\.w,f\.h,0,0,iter,snap,\.5,\.5,0,refX,refY,2,f\.w,0,offset\)/);
|
||||
assert.match(html,/maxPixels=Math\.max\(1,Math\.floor\(4000000\/Math\.max\(1,iter\)\)\),tileW=Math\.min\(f\.w,maxPixels\)/);
|
||||
assert.match(html,/correctUnknownFrame\(snap,iter,token,referencePixel,numericalFailureCount\(stats\)\)/);
|
||||
assert.match(html,/ensureDeepActiveWorkspace/);
|
||||
assert.doesNotMatch(html,/return this\.computeDeepActiveFrame\(snap,iter,token,forceStrict,referencePixel\)/);
|
||||
assert.match(html,/return this\.computePerturbFrameTiled\(snap,iter,true,token,forceStrict,referencePixel,false,colorStyle,colorKey\)/);
|
||||
assert.match(html,/state\.gpuInitFailed=true;markDirty\(false\);setTimeout/);
|
||||
assert.match(html,/deep-active-shadow-resume/);
|
||||
assert.match(html,/deep-active-compare-shadow/);
|
||||
assert.match(html,/runtime\.deepActiveShadowLatest=result/);
|
||||
assert.match(html,/runCertifiedInteriorShadow/);
|
||||
assert.match(html,/precisionFallback\.request\(snap,iter,w,h,gpu\.provenIndices,FIELD_INTERIOR_PROVEN\)/);
|
||||
assert.match(html,/falsePositive===0&&inconclusive===0/);
|
||||
assert.match(html,/oracleBits:\[oracleBits,oracleBits\+32\]/);
|
||||
assert.match(html,/productionEligible:false/);
|
||||
assert.match(html,/waitForPrimary\(/);
|
||||
assert.match(html,/waitForFinal\(/);
|
||||
assert.match(html,/waitForNumericComplete\(/);
|
||||
assert.match(html,/fieldHashes\(\)/);
|
||||
assert.match(html,/readFieldAll\(\)/);
|
||||
assert.match(html,/generationMetrics:\[\]/);
|
||||
assert.match(html,/primaryNumericalFailures/);
|
||||
assert.match(html,/numericQuiescentMs/);
|
||||
assert.match(html,/historyCommitMs/);
|
||||
assert.match(html,/SYMMETRY_COPY_WGSL/);
|
||||
assert.match(html,/canUseRealAxisSymmetry/);
|
||||
assert.match(html,/encodeSymmetryCopy/);
|
||||
assert.match(html,/FAILURE_TILE_MAP_WGSL/);
|
||||
assert.match(html,/readNumericalFailureTiles/);
|
||||
assert.match(html,/tileReferencePool=Array\.from\(\{length:3\}/);
|
||||
assert.match(html,/Promise\.all\(batch\.map/);
|
||||
assert.match(html,/if\(p\.key===key\)return p\.promise/);
|
||||
assert.match(html,/prefetchFinalReference/);
|
||||
assert.match(html,/this\.exportWs=\[\]/);
|
||||
assert.match(html,/exportRingDepth\(tile=this\.exportTileSize\(\)\)/);
|
||||
assert.match(html,/Promise\.allSettled\(batch\.map\(item=>item\.promise\)\)/);
|
||||
assert.match(html,/if\(failed\)throw failed\.reason/);
|
||||
assert.match(html,/performance\.now\(\)-lastYield<24/);
|
||||
assert.doesNotMatch(html,/await png\.rows\(band\);await new Promise\(requestAnimationFrame\)/);
|
||||
assert.match(html,/frameReadback\(kind,size\)/);
|
||||
assert.match(html,/length:3.*kind\+'-readback-'/);
|
||||
const statsReadbackSource=html.slice(html.indexOf('async readUnresolvedStats'),html.indexOf('async readUnresolved(){'));
|
||||
assert.match(statsReadbackSource,/this\.frameReadback\('unknown-stats'/);
|
||||
assert.doesNotMatch(statsReadbackSource,/destroy\(r\)/);
|
||||
assert.match(html,/cachedBindGroup\(pipeline,entries\)/);
|
||||
assert.match(html,/cachedTextureView\(texture\)/);
|
||||
assert.match(html,/this\.cachedBindGroup\(this\.direct/);
|
||||
assert.match(html,/this\.cachedBindGroup\(this\.present/);
|
||||
assert.match(html,/this\.clearBindGroupCache\(\)/);
|
||||
const historyCommitSource=html.slice(html.indexOf('commitHistory(view='),html.indexOf('invalidateHistory(){'));
|
||||
assert.match(historyCommitSource,/f\.history=f\.front/);
|
||||
assert.doesNotMatch(historyCommitSource,/copyTextureToTexture/);
|
||||
assert.match(html,/colorTarget\(f=this\.frame\)/);
|
||||
{
|
||||
const roles={front:'a',back:'b',history:'c',spare:'c'};
|
||||
const commit=()=>{roles.history=roles.front};
|
||||
const render=()=>{if(roles.back===roles.history){const old=roles.history;roles.back=roles.spare;roles.spare=old}assert.notEqual(roles.back,roles.history);assert.notEqual(roles.back,roles.front);[roles.front,roles.back]=[roles.back,roles.front]};
|
||||
for(let i=0;i<1000;i++){if(i%7===0||i%11===0)commit();else render();assert.equal(new Set([roles.front,roles.back,roles.history,roles.spare]).size,3)}
|
||||
}
|
||||
const recoverySource=html.slice(html.indexOf('async function recoverNumericalUnknownTiles'),html.indexOf('async function recoverResidualPrecision'));
|
||||
assert.match(recoverySource,/readNumericalFailureTiles/);
|
||||
assert.match(recoverySource,/const currentMeta=await r\.readMetaAll\(\)/);
|
||||
assert.match(recoverySource,/Uint32Array\.from\(tileIndices\)/);
|
||||
assert.match(html,/p\.unknownOnly==2u && reason!=0u/);
|
||||
assert.match(html,/fast-coverage-repair-and-color/);
|
||||
assert.match(html,/reprojectionSafe\(rawHistory,2\.25,\.45\)/);
|
||||
assert.match(html,/scheduleFastNumericRecovery/);
|
||||
assert.match(html,/runFastNumericRecovery/);
|
||||
assert.match(html,/numericFrameComplete\(\)/);
|
||||
assert.match(html,/requestBuild\(\{ctx,snap,iter,width,height,refPixel,safety=1\/64\}\)/);
|
||||
assert.match(html,/type:'build'/);
|
||||
assert.match(html,/buildOnly=d\.type==='build'/);
|
||||
assert.equal((await fs.readdir(root)).filter(name=>name.startsWith('index.baseline')&&name.endsWith('.html')).length,0);
|
||||
|
||||
let randomState=0x12345678;
|
||||
function randomU32(){randomState=(Math.imul(randomState,1664525)+1013904223)>>>0;return randomState}
|
||||
function roundShift(value,bits){const negative=value<0n,absolute=negative?-value:value,half=1n<<(BigInt(bits)-1n),rounded=(absolute+half)>>BigInt(bits);return negative?-rounded:rounded}
|
||||
function orbitOld(bits,re,im,iterations){const bailout=16n*(1n<<BigInt(bits));let zr=0n,zi=0n;const states=[];for(let n=0;n<iterations;n++){const zr2=roundShift(zr*zr,bits),zi2=roundShift(zi*zi,bits);zi=roundShift(2n*zr*zi,bits)+im;zr=zr2-zi2+re;const mag=roundShift(zr*zr,bits)+roundShift(zi*zi,bits);states.push([zr,zi,mag]);if(mag>bailout)return{escape:n+1,states}}return{escape:0,states}}
|
||||
function orbitNew(bits,re,im,iterations){const bailout=16n*(1n<<BigInt(bits));let zr=0n,zi=0n,zr2=0n,zi2=0n;const states=[];for(let n=0;n<iterations;n++){zi=roundShift(2n*zr*zi,bits)+im;zr=zr2-zi2+re;zr2=roundShift(zr*zr,bits);zi2=roundShift(zi*zi,bits);const mag=zr2+zi2;states.push([zr,zi,mag]);if(mag>bailout)return{escape:n+1,states}}return{escape:0,states}}
|
||||
|
||||
for(let sample=0;sample<2000;sample++){
|
||||
const bits=80+(randomU32()%177),one=1n<<BigInt(bits);
|
||||
const re=(BigInt(randomU32()%7000001)-3500000n)*one/1000000n;
|
||||
const im=(BigInt(randomU32()%4000001)-2000000n)*one/1000000n;
|
||||
const iterations=20+(randomU32()%180);
|
||||
assert.deepEqual(orbitNew(bits,re,im,iterations),orbitOld(bits,re,im,iterations));
|
||||
}
|
||||
|
||||
const f=Math.fround;
|
||||
function ds(h,l=0){return{h:f(h),l:f(l)}}
|
||||
function quick(a,b){const q=f(a+b),e=f(b-f(q-a));return ds(q,e)}
|
||||
function sum(a,b){const q=f(a+b),bb=f(q-a),e=f(f(a-f(q-bb))+f(b-bb));return ds(q,e)}
|
||||
function product(a,b){const q=f(a*b),ca=f(4097*a),ah=f(ca-f(ca-a)),al=f(a-ah),cb=f(4097*b),bh=f(cb-f(cb-b)),bl=f(b-bh);let e=f(f(ah*bh)-q);e=f(e+f(ah*bl));e=f(e+f(al*bh));e=f(e+f(al*bl));return ds(q,e)}
|
||||
function add(a,b){const q=sum(a.h,b.h);return quick(q.h,f(f(q.l+a.l)+b.l))}
|
||||
function neg(a){return ds(-a.h,-a.l)}
|
||||
function sub(a,b){return add(a,neg(b))}
|
||||
function mul(a,b){const q=product(a.h,b.h),e=f(f(f(q.l+f(a.h*b.l))+f(a.l*b.h))+f(a.l*b.l));return quick(q.h,e)}
|
||||
function scale(a,b){const q=product(a.h,b);return quick(q.h,f(q.l+f(a.l*b)))}
|
||||
function sameDs(a,b){return Object.is(a.h,b.h)&&Object.is(a.l,b.l)}
|
||||
function dsOrbit(cr,ci,iterations,carrySquares){let zr=ds(0),zi=ds(0),zr2=ds(0),zi2=ds(0);const states=[];for(let n=0;n<iterations;n++){if(!carrySquares){zr2=mul(zr,zr);zi2=mul(zi,zi)}const zri=mul(zr,zi);zr=add(sub(zr2,zi2),cr);zi=add(scale(zri,2),ci);const nextZr2=mul(zr,zr),nextZi2=mul(zi,zi),mag=add(nextZr2,nextZi2);states.push({zr,zi,mag});zr2=nextZr2;zi2=nextZi2}return states}
|
||||
|
||||
for(let sample=0;sample<600;sample++){
|
||||
const cr=ds(f((randomU32()/0xffffffff)*3.5-2.5),f((randomU32()/0xffffffff-.5)*1e-7));
|
||||
const ci=ds(f((randomU32()/0xffffffff)*2.4-1.2),f((randomU32()/0xffffffff-.5)*1e-7));
|
||||
const iterations=8+(randomU32()%64),oldStates=dsOrbit(cr,ci,iterations,false),newStates=dsOrbit(cr,ci,iterations,true);
|
||||
assert.equal(newStates.length,oldStates.length);
|
||||
for(let i=0;i<oldStates.length;i++){
|
||||
assert.ok(sameDs(newStates[i].zr,oldStates[i].zr));
|
||||
assert.ok(sameDs(newStates[i].zi,oldStates[i].zi));
|
||||
assert.ok(sameDs(newStates[i].mag,oldStates[i].mag));
|
||||
}
|
||||
}
|
||||
|
||||
function directChunkOrbit(cr,ci,iterations,chunk){let zr=f(0),zi=f(0),n=0,escape=0,mag=f(0);while(n<iterations&&!escape){const stop=Math.min(iterations,n+chunk);while(n<stop){const zr2=f(zr*zr),zi2=f(zi*zi);zi=f(f(f(2*zr)*zi)+ci);zr=f(f(zr2-zi2)+cr);n++;mag=f(f(zr*zr)+f(zi*zi));if(mag>4){escape=n;break}}}return{zr,zi,n,escape,mag}}
|
||||
for(let sample=0;sample<1000;sample++){
|
||||
const cr=f((randomU32()/0xffffffff)*3.5-2.5),ci=f((randomU32()/0xffffffff)*2.4-1.2),iterations=64+(randomU32()%900),chunk=[64,128,192,256][randomU32()%4];
|
||||
assert.deepEqual(directChunkOrbit(cr,ci,iterations,chunk),directChunkOrbit(cr,ci,iterations,iterations));
|
||||
}
|
||||
|
||||
function deepChunkState(reference,d,scaleExp,iterations,chunk){let w=[f(0),f(0)],n=0,m=0,err=f(Math.pow(2,-24)*Math.max(Math.abs(d[0]),Math.abs(d[1])));while(n<iterations){const stop=Math.min(iterations,n+chunk);while(n<stop){const r=reference[m],delta=[f(w[0]*Math.pow(2,scaleExp)),f(w[1]*Math.pow(2,scaleExp))],sq=[f(f(w[0]*w[0])-f(w[1]*w[1])),f(f(2*w[0])*w[1])],linear=[f(2*f(f(r[0]*w[0])-f(r[1]*w[1]))),f(2*f(f(r[0]*w[1])+f(r[1]*w[0])))],refAbs=Math.max(Math.abs(r[0]),Math.abs(r[1])),wAbs=Math.max(Math.abs(w[0]),Math.abs(w[1])),dAbs=Math.max(Math.abs(d[0]),Math.abs(d[1])),deltaAbs=Math.max(Math.abs(delta[0]),Math.abs(delta[1])),sqAbs=Math.max(Math.abs(f(sq[0]*Math.pow(2,scaleExp))),Math.abs(f(sq[1]*Math.pow(2,scaleExp))));err=f(f(f(2*refAbs)+f(2*deltaAbs))*err+f(Math.pow(2,-24)*f(f(f(2*refAbs)*wAbs)+sqAbs+dAbs+1e-30)));w=[f(f(linear[0]+f(sq[0]*Math.pow(2,scaleExp)))+d[0]),f(f(linear[1]+f(sq[1]*Math.pow(2,scaleExp)))+d[1])];m++;n++;const mm=Math.max(Math.abs(w[0]),Math.abs(w[1]),Math.abs(d[0]),Math.abs(d[1]));if(mm>65536){w=[f(w[0]/65536),f(w[1]/65536)];d=[f(d[0]/65536),f(d[1]/65536)];err=f(err/65536);scaleExp+=16}}}return{w,d,scaleExp,n,m,err}}
|
||||
for(let sample=0;sample<1000;sample++){
|
||||
const iterations=32+(randomU32()%480),reference=Array.from({length:iterations+1},()=>[f((randomU32()/0xffffffff-.5)*2),f((randomU32()/0xffffffff-.5)*2)]),d=[f((randomU32()/0xffffffff-.5)*1e-3),f((randomU32()/0xffffffff-.5)*1e-3)],scaleExp=-20-(randomU32()%60),chunk=1+(randomU32()%256);
|
||||
assert.deepEqual(deepChunkState(reference,[...d],scaleExp,iterations,chunk),deepChunkState(reference,[...d],scaleExp,iterations,iterations));
|
||||
}
|
||||
|
||||
for(let sample=0;sample<500;sample++){
|
||||
const w=64+(randomU32()%512),h=32+(randomU32()%256),iterations=350+(randomU32()%5000),maxPixels=Math.max(1,Math.floor(4000000/iterations)),tileW=Math.min(w,maxPixels),rows=Math.max(1,Math.min(128,Math.floor(maxPixels/tileW))),coverage=new Uint8Array(w*h);
|
||||
for(let y=0;y<h;y+=rows){const th=Math.min(rows,h-y);for(let x=0;x<w;x+=tileW){const tw=Math.min(tileW,w-x);assert.ok(tw*th*iterations<=4000000);for(let yy=0;yy<th;yy++)for(let xx=0;xx<tw;xx++)coverage[(y+yy)*w+x+xx]++}}
|
||||
for(const count of coverage)assert.equal(count,1);
|
||||
}
|
||||
|
||||
function adaptiveBudget(screenBits,q,base=350,quantum=64){const raw=48*Math.max(0,q)*Math.max(0,screenBits),bonus=raw>0?Math.ceil(raw/quantum)*quantum:0;return Math.min(12000,Math.max(base,base+bonus))}
|
||||
for(const q of [.72,1,1.25,1.5]){
|
||||
let prior=0;
|
||||
for(let i=0;i<=2000;i++){
|
||||
const screenBits=i/20,value=adaptiveBudget(screenBits,q);
|
||||
assert.ok(value>=350+Math.floor(48*q*screenBits));
|
||||
assert.equal((value-350)%64,0);
|
||||
assert.ok(value>=prior);prior=value;
|
||||
}
|
||||
}
|
||||
assert.equal(adaptiveBudget(Math.log2(800)+12*Math.LOG2E*Math.LN10,1),adaptiveBudget(Math.log2(800)+12.05*Math.LOG2E*Math.LN10,1));
|
||||
|
||||
function frontierModel(meta,w,h){const out=[];for(let y=0;y<h;y++)for(let x=0;x<w;x++){const i=y*w+x,m=meta[i]>>>0;if(((m>>>28)&3)!==0||((m>>>20)&255)!==6)continue;let edge=false;for(let oy=-1;oy<=1&&!edge;oy++)for(let ox=-1;ox<=1;ox++){if(!ox&&!oy)continue;const xx=x+ox,yy=y+oy;if(xx>=0&&xx<w&&yy>=0&&yy<h&&((meta[yy*w+xx]>>>28)&3)===1){edge=true;break}}if(edge)out.push(i)}return out}
|
||||
const opLimit=(6<<20)|350,escaped=(1<<28)|12,interior=(3<<28)|350,frontierFixture=new Uint32Array(25).fill(interior);frontierFixture[12]=escaped;for(const i of [6,7,8,11,13,16,17,18])frontierFixture[i]=opLimit;frontierFixture[0]=opLimit;
|
||||
assert.deepEqual(frontierModel(frontierFixture,5,5),[6,7,8,11,13,16,17,18]);
|
||||
for(let sample=0;sample<500;sample++){const iter=1+(randomU32()%150000),count=1+(randomU32()%200000),chunk=Math.max(1,Math.floor(4000000/iter));for(let start=0;start<count;start+=chunk)assert.ok(Math.min(chunk,count-start)*iter<=4000000)}
|
||||
|
||||
function pixelBitsAt(spanLog2,width,sourceBits=512,guard=32){const pixelLog2=spanLog2-Math.log2(Math.max(1,width)),need=Math.ceil(Math.max(0,-pixelLog2))+Math.max(16,guard|0);return Math.max(96,Math.min(sourceBits+64,need))}
|
||||
assert.equal(pixelBitsAt(Math.log2(3.4)-8*Math.LOG2E*Math.LN10,1920),96);
|
||||
assert.ok(pixelBitsAt(Math.log2(3.4)-100*Math.LOG2E*Math.LN10,1920)>350);
|
||||
assert.ok(pixelBitsAt(-400,3840)>pixelBitsAt(-400,960));
|
||||
assert.equal(pixelBitsAt(-400,1920,256),320);
|
||||
|
||||
export const result={
|
||||
syntaxScripts:scripts.length,
|
||||
precisionWorkerSyntax:true,
|
||||
kernelHashes:Object.keys(actual).length,
|
||||
bigintOrbitCases:2000,
|
||||
dsOrbitCases:600,
|
||||
directActiveChunkCases:1000,
|
||||
deepActiveChunkCases:1000,
|
||||
boundedCorrectionTileCases:500,
|
||||
adaptiveIterationCases:8004,
|
||||
pixelPrecisionCases:4,
|
||||
frontierAdjacencyCases:1,
|
||||
frontierWorkBoundCases:500,
|
||||
webGpuCorrectnessCases:correctnessCases.length,
|
||||
webGpuPerformanceCases:performanceCases.length,
|
||||
webGpuStabilityViews:interactionStabilityViews.length,
|
||||
status:'pass'
|
||||
};
|
||||
122
tests/optimization_webgpu_corpus.mjs
Normal file
122
tests/optimization_webgpu_corpus.mjs
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
import assert from 'node:assert/strict';
|
||||
|
||||
export const correctnessCases=[
|
||||
{id:'reset',re:'-0.5',im:'0',span:'3.4',bits:256,baseIter:750,adaptive:false,processMode:'validate',renderMode:'fast',activeDirect:true,certified:true,frontierCheck:true},
|
||||
{id:'cusp-low',re:'0.25',im:'0',span:'0.85',bits:256,baseIter:900,adaptive:false,processMode:'validate',renderMode:'accurate',certified:true},
|
||||
{id:'seahorse-low',re:'-0.743643887037151',im:'0.13182590420533',span:'0.1',bits:320,baseIter:1200,adaptive:false,processMode:'validate',renderMode:'accurate'},
|
||||
{id:'moderate-1e5-fast',re:'-0.743643887037151',im:'0.13182590420533',span:'0.000034',bits:384,baseIter:350,adaptive:true,processMode:'standard',renderMode:'fast',frontierCheck:true},
|
||||
{id:'moderate-1e5-accurate',re:'-0.743643887037151',im:'0.13182590420533',span:'0.000034',bits:384,baseIter:350,adaptive:true,processMode:'standard',renderMode:'accurate',frontierCheck:true},
|
||||
{id:'moderate-1e8-fast',re:'-0.743643887037151',im:'0.13182590420533',span:'0.000000034',bits:384,baseIter:350,adaptive:true,processMode:'standard',renderMode:'fast',frontierCheck:true},
|
||||
{id:'moderate-1e8-accurate',re:'-0.743643887037151',im:'0.13182590420533',span:'0.000000034',bits:384,baseIter:350,adaptive:true,processMode:'standard',renderMode:'accurate',frontierCheck:true},
|
||||
{id:'seahorse-deep',re:'-0.743643887037151',im:'0.13182590420533',span:'0.00000000000034',bits:448,baseIter:2900,adaptive:false,processMode:'validate',renderMode:'accurate',activeDeep:true,frontierCheck:true},
|
||||
{id:'interior-heavy',re:'0',im:'0',span:'0.5',bits:320,baseIter:1500,adaptive:false,processMode:'validate',renderMode:'accurate',certified:true},
|
||||
{id:'real-axis-boundary',re:'-0.75',im:'0',span:'0.02',bits:384,baseIter:3000,adaptive:false,processMode:'validate',renderMode:'accurate',activeDeep:true,certified:true,frontierCheck:true},
|
||||
{id:'misiurewicz-hard',re:'-0.10109636384562',im:'0.95628651080914',span:'0.00000002',bits:384,baseIter:3000,adaptive:false,processMode:'validate',renderMode:'accurate',activeDeep:true,frontierCheck:true},
|
||||
{id:'reported-black-regression',re:'-29466147000382485924219538765424656674342940730553342389512209954887705938978413587',im:'5179018789925933872641942859702187326563010594882200888329237785122225251258352',span:'250637324516887125119843167990565159991251418774166207381437546036409',bits:273,baseIter:350,adaptive:true,processMode:'standard',renderMode:'accurate',fixed:true,frontierCheck:true}
|
||||
];
|
||||
|
||||
export const performanceCases=[
|
||||
{id:'accurate-320x220-750',viewport:{width:320,height:220},view:correctnessCases[2],iterations:750},
|
||||
{id:'bla-654x690-2900',viewport:{width:654,height:690},view:correctnessCases[7],iterations:2900},
|
||||
{id:'fast-1e14-800x600',viewport:{width:800,height:600},view:{id:'fast-1e14',re:'-0.743643887037151',im:'0.13182590420533',span:'0.000000000000034',bits:448,baseIter:350,adaptive:true,processMode:'standard',renderMode:'fast'},target:true,absoluteP50Ms:1000,absoluteP95Ms:1500},
|
||||
{id:'accurate-1e14-800x600',viewport:{width:800,height:600},view:{id:'accurate-1e14',re:'-0.743643887037151',im:'0.13182590420533',span:'0.000000000000034',bits:448,baseIter:350,adaptive:true,processMode:'standard',renderMode:'accurate'},target:true,absoluteP50Ms:1500,absoluteP95Ms:2000},
|
||||
{id:'hd-reset-1500',viewport:{width:1920,height:1080},view:correctnessCases[0],iterations:1500},
|
||||
{id:'hd-boundary-3000',viewport:{width:1920,height:1080},view:correctnessCases[9],iterations:3000}
|
||||
];
|
||||
|
||||
export const productionPerformanceThresholds={targetP50Reduction:.20,targetP95Reduction:.15,nonTargetP50Regression:.05,nonTargetP95Regression:.10};
|
||||
|
||||
export const interactionStabilityViews=[
|
||||
{id:'near-a',re:'-0.743643887037151',im:'0.13182590420533',span:'0.0000000000034',bits:448,baseIter:350,adaptive:true,processMode:'standard',renderMode:'fast'},
|
||||
{id:'near-b',re:'-0.743643887037151',im:'0.13182590420533',span:'0.000000000003030253189',bits:448,baseIter:350,adaptive:true,processMode:'standard',renderMode:'fast'},
|
||||
{id:'near-a-repeat',re:'-0.743643887037151',im:'0.13182590420533',span:'0.0000000000034',bits:448,baseIter:350,adaptive:true,processMode:'standard',renderMode:'fast'}
|
||||
];
|
||||
|
||||
function numericalReasonTotal(reasons={}){return (reasons.errorBound||0)+(reasons.escapeUncertain||0)+(reasons.referenceEnd||0)+(reasons.rebaseGap||0)+(reasons.range||0)}
|
||||
function operationLimit(reasons={}){return reasons.operationLimit||0}
|
||||
|
||||
async function evaluateCase(page,testCase,options){
|
||||
return page.evaluate(async({testCase,options})=>{
|
||||
const t=globalThis.__MANDEL_TEST__;if(!t)throw new Error('__MANDEL_TEST__ is unavailable');
|
||||
await t.setView(testCase);await t.waitForFinal({timeout:options.timeout});
|
||||
let numericComplete=true,numericError='';try{await t.waitForNumericComplete({timeout:options.timeout})}catch(error){numericComplete=false;numericError=String(error&&error.message||error)}
|
||||
const state=t.state(),hashes=await t.fieldHashes(),diagnostics=t.gpuDiagnostics();
|
||||
let activeDirect=null,activeDeep=null,certified=null,frontier=null;
|
||||
if(testCase.activeDirect)activeDirect=await t.runActiveDirectShadow({chunkSize:128});
|
||||
if(testCase.activeDeep)activeDeep=await t.runActiveDeepShadow({width:options.shadowWidth,height:options.shadowHeight,chunkSize:128,strict:true});
|
||||
if(testCase.certified)certified=await t.runCertifiedInteriorShadow({width:options.oracleWidth,height:options.oracleHeight,samples:options.oracleSamples});
|
||||
if(testCase.frontierCheck)frontier=await t.compareCurrentToFrontierBaseline({strict:true});
|
||||
return{state,hashes,diagnostics,numericComplete,numericError,activeDirect,activeDeep,certified,frontier};
|
||||
},{testCase,options});
|
||||
}
|
||||
|
||||
function auditCase(testCase,result,expected){
|
||||
const reasons=result.state.unknownReasons||{},numeric=numericalReasonTotal(reasons),op=operationLimit(reasons),coverage=Math.max(0,(result.state.unresolved||0)-numeric-op),errors=(result.diagnostics?.compilation||[]).flatMap(x=>x.messages||[]).filter(x=>x.type==='error');
|
||||
assert.equal(result.state.kernelVersion,'24.3.0-optimized-unknown-pipeline',testCase.id+' kernel version');
|
||||
assert.equal(coverage,0,testCase.id+' coverage UNKNOWN');
|
||||
assert.equal(errors.length,0,testCase.id+' WGSL compilation errors');
|
||||
assert.equal(result.diagnostics?.uncapturedErrors?.length||0,0,testCase.id+' uncaptured GPU errors');
|
||||
assert.equal(result.diagnostics?.lossReason||'','',testCase.id+' device loss');
|
||||
assert.equal(result.numericComplete,true,testCase.id+' numeric completion: '+result.numericError);
|
||||
assert.equal(numeric,0,testCase.id+' final numeric UNKNOWN');
|
||||
assert.equal(result.state.historyReady,true,testCase.id+' completed history commit');
|
||||
if(result.activeDirect)assert.equal(result.activeDirect.gatePassed,true,testCase.id+' Direct active mismatch');
|
||||
if(result.activeDeep)assert.equal(result.activeDeep.gatePassed,true,testCase.id+' Deep active mismatch');
|
||||
if(result.certified)assert.equal(result.certified.gatePassed,true,testCase.id+' certified interior oracle mismatch');
|
||||
if(result.frontier)assert.equal(result.frontier.gatePassed,true,testCase.id+' production frontier mismatch');
|
||||
assert.equal(result.state.frontierConverged,true,testCase.id+' frontier convergence');
|
||||
assert.ok((result.state.frontierMaxDispatchWork||0)<=4000000,testCase.id+' frontier TDR work bound');
|
||||
if(expected){assert.equal(result.hashes.metaSha256,expected.metaSha256,testCase.id+' meta hash');assert.equal(result.hashes.smoothSha256,expected.smoothSha256,testCase.id+' smooth hash')}
|
||||
return{coverageUnknown:coverage,numericalUnknown:numeric,operationLimit:op};
|
||||
}
|
||||
|
||||
export async function runCorrectnessCorpus(page,{timeout=180000,viewport={width:480,height:320},shadowWidth=160,shadowHeight=112,oracleWidth=320,oracleHeight=220,oracleSamples=289,expectedHashes={},expectProduction=false}={}){
|
||||
if(page.setViewportSize)await page.setViewportSize(viewport);
|
||||
const compile=await page.evaluate(()=>globalThis.__MANDEL_TEST__.compileActiveShadow()),records=[];
|
||||
assert.equal(compile.productionEligible,expectProduction);
|
||||
assert.equal(compile.candidateEnabled,true);
|
||||
assert.equal(compile.pixelFrontier,true);
|
||||
assert.equal(compile.frontierWorkLimit,4000000);
|
||||
for(const testCase of correctnessCases){const started=Date.now(),result=await evaluateCase(page,testCase,{timeout,shadowWidth,shadowHeight,oracleWidth,oracleHeight,oracleSamples}),audit=auditCase(testCase,result,expectedHashes[testCase.id]);records.push({id:testCase.id,elapsedMs:Date.now()-started,audit,...result})}
|
||||
const adapter=await page.evaluate(()=>globalThis.__MANDEL_TEST__.gpuDiagnostics()?.adapterInfo||{});
|
||||
return{version:'24.3.0',kind:'correctness',date:new Date().toISOString(),expectProduction,compile,adapter,records};
|
||||
}
|
||||
|
||||
function percentile(values,p){const sorted=[...values].sort((a,b)=>a-b);if(!sorted.length)return Infinity;const index=Math.min(sorted.length-1,Math.max(0,Math.ceil(sorted.length*p)-1));return sorted[index]}
|
||||
function summarizeRuns(samples){const primary=samples.map(x=>Number(x.metric?.primaryMs??x.wallMs)),recovery=samples.map(x=>Number(x.metric?.numericQuiescentMs??x.metric?.historyCommitMs??x.metric?.finalMs??x.wallMs));return{runs:samples.length,primary:{p50:percentile(primary,.50),p95:percentile(primary,.95)},recovery:{p50:percentile(recovery,.50),p95:percentile(recovery,.95)}}}
|
||||
export function evaluateProductionPerformance(candidate,baseline,{thresholds=productionPerformanceThresholds}={}){const failures=[],byId=new Map((baseline?.records||[]).map(x=>[x.id,x]));for(const record of candidate?.records||[]){const base=byId.get(record.id),summary=record.summary||summarizeRuns(record.runs||[]);if(record.absoluteP50Ms&&summary.recovery.p50>record.absoluteP50Ms)failures.push(record.id+' recovery p50 '+summary.recovery.p50+' > '+record.absoluteP50Ms);if(record.absoluteP95Ms&&summary.recovery.p95>record.absoluteP95Ms)failures.push(record.id+' recovery p95 '+summary.recovery.p95+' > '+record.absoluteP95Ms);if(!base){failures.push(record.id+' missing baseline');continue}const bs=base.summary||summarizeRuns(base.runs||[]),p50=(summary.recovery.p50-bs.recovery.p50)/Math.max(1,bs.recovery.p50),p95=(summary.recovery.p95-bs.recovery.p95)/Math.max(1,bs.recovery.p95);if(record.target){if(p50>-thresholds.targetP50Reduction)failures.push(record.id+' target p50 reduction '+p50);if(p95>-thresholds.targetP95Reduction)failures.push(record.id+' target p95 reduction '+p95)}else{if(p50>thresholds.nonTargetP50Regression)failures.push(record.id+' non-target p50 regression '+p50);if(p95>thresholds.nonTargetP95Regression)failures.push(record.id+' non-target p95 regression '+p95)}}return{pass:failures.length===0,failures}}
|
||||
|
||||
export async function runPerformanceCorpus(page,{runs=10,timeout=240000,includeLarge=false}={}){
|
||||
const cases=includeLarge?performanceCases:performanceCases.slice(0,2),records=[];
|
||||
for(const scenario of cases){if(page.setViewportSize)await page.setViewportSize(scenario.viewport);const view=scenario.iterations?{...scenario.view,baseIter:scenario.iterations,adaptive:false,processMode:'standard'}:{...scenario.view},samples=[];for(let run=0;run<runs+1;run++){const started=Date.now();await page.evaluate(async({view,timeout})=>{const t=globalThis.__MANDEL_TEST__;await t.setView(view);await t.waitForNumericComplete({timeout})},{view,timeout});const state=await page.evaluate(()=>globalThis.__MANDEL_TEST__.state()),metric=state.generationMetrics.at(-1),diagnostics=await page.evaluate(()=>globalThis.__MANDEL_TEST__.gpuDiagnostics());assert.equal(state.numericalFailures,0,scenario.id+' numerical failures');assert.equal(diagnostics?.uncapturedErrors?.length||0,0,scenario.id+' uncaptured GPU errors');assert.equal(diagnostics?.lossReason||'','',scenario.id+' device loss');if(run>0)samples.push({wallMs:Date.now()-started,metric})}records.push({id:scenario.id,viewport:scenario.viewport,target:!!scenario.target,absoluteP50Ms:scenario.absoluteP50Ms||0,absoluteP95Ms:scenario.absoluteP95Ms||0,runs:samples,summary:summarizeRuns(samples)})}
|
||||
const exports=await page.evaluate(async()=>({ss1:await globalThis.__MANDEL_TEST__.smokeExportTile({w:128,h:96,strict:true,ss:1}),ss2:await globalThis.__MANDEL_TEST__.smokeExportTile({w:128,h:96,strict:true,ss:2})}));
|
||||
assert.equal(exports.ss1.length,exports.ss1.expected);assert.equal(exports.ss2.length,exports.ss2.expected);
|
||||
const adapter=await page.evaluate(()=>globalThis.__MANDEL_TEST__.gpuDiagnostics()?.adapterInfo||{});
|
||||
return{version:'24.3.0',kind:'performance',date:new Date().toISOString(),adapter,records,exports};
|
||||
}
|
||||
|
||||
export async function runInteractionStabilityCorpus(page,{timeout=240000,expectProduction=false}={}){
|
||||
if(page.setViewportSize)await page.setViewportSize({width:800,height:600});
|
||||
const policy=await page.evaluate(()=>globalThis.__MANDEL_TEST__.stabilityPolicy());
|
||||
assert.equal(policy.adaptiveIterationQuantum,64);
|
||||
assert.equal(policy.blaFastProductionOptIn,false);
|
||||
assert.equal(policy.blaFastDisabled,true);
|
||||
assert.equal(policy.pixelFrontierProduction,expectProduction);
|
||||
assert.equal(policy.pixelFrontierCandidate,true);
|
||||
assert.equal(policy.pixelFrontierEnabled,true);
|
||||
assert.equal(policy.pixelFrontierWorkLimit,4000000);
|
||||
const records=[];
|
||||
for(const view of interactionStabilityViews){
|
||||
const result=await page.evaluate(async({view,timeout})=>{const t=globalThis.__MANDEL_TEST__;await t.setView(view);await t.waitForNumericComplete({timeout});return{state:t.state(),hashes:await t.fieldHashes(),policy:t.stabilityPolicy()}},{view,timeout});
|
||||
assert.notEqual(result.state.backend,'fast-bla',view.id+' timing-selected backend');
|
||||
assert.equal(result.state.numericalFailures,0,view.id+' numerical failures');
|
||||
records.push({id:view.id,...result});
|
||||
}
|
||||
assert.equal(records[0].state.iter,records[1].state.iter,'nearby zoom iteration envelope');
|
||||
assert.equal(records[0].hashes.metaSha256,records[2].hashes.metaSha256,'repeat meta hash');
|
||||
assert.equal(records[0].hashes.smoothSha256,records[2].hashes.smoothSha256,'repeat smooth hash');
|
||||
const adapter=await page.evaluate(()=>globalThis.__MANDEL_TEST__.gpuDiagnostics()?.adapterInfo||{});
|
||||
return{version:'24.3.0',kind:'interaction-stability',date:new Date().toISOString(),expectProduction,policy,adapter,records};
|
||||
}
|
||||
|
||||
export async function runWebGpuCorpus(page,options={}){const correctness=await runCorrectnessCorpus(page,options.correctness),stability=await runInteractionStabilityCorpus(page,options.stability),performance=await runPerformanceCorpus(page,options.performance);return{correctness,stability,performance}}
|
||||
65
tests/production_gate.mjs
Normal file
65
tests/production_gate.mjs
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs/promises';
|
||||
import {fileURLToPath} from 'node:url';
|
||||
import {correctnessCases,performanceCases,interactionStabilityViews,evaluateProductionPerformance} from './optimization_webgpu_corpus.mjs';
|
||||
|
||||
const root=fileURLToPath(new URL('../',import.meta.url));
|
||||
const artifactPath=process.argv[2];
|
||||
const phase=process.argv[3]||'preflight';
|
||||
assert.ok(artifactPath,'usage: node tests/production_gate.mjs <gate-bundle.json> [preflight|production]');
|
||||
assert.ok(phase==='preflight'||phase==='production','phase must be preflight or production');
|
||||
|
||||
const bundle=JSON.parse(await fs.readFile(artifactPath,'utf8'));
|
||||
const index=await fs.readFile(new URL('../index.html',import.meta.url),'utf8');
|
||||
const production=/const PIXEL_FRONTIER_PRODUCTION=true,PIXEL_FRONTIER_WORK=4000000/.test(index);
|
||||
assert.equal(production,phase==='production','index production flag does not match gate phase');
|
||||
assert.ok(Array.isArray(bundle.candidateRuns)&&bundle.candidateRuns.length>=2,'at least two candidate adapter runs are required');
|
||||
assert.ok(Array.isArray(bundle.baselineRuns)&&bundle.baselineRuns.length>=2,'matching baseline runs are required');
|
||||
|
||||
function adapterKey(run){const a=run?.correctness?.adapter||run?.performance?.adapter||{};return[a.vendor,a.architecture,a.device,a.description].map(x=>String(x||'')).join('|')}
|
||||
function gpuErrors(diagnostics){return(diagnostics?.compilation||[]).flatMap(x=>x.messages||[]).filter(x=>x.type==='error').length+(diagnostics?.uncapturedErrors?.length||0)+(diagnostics?.lossReason?1:0)}
|
||||
function auditCandidate(run){
|
||||
assert.equal(run?.correctness?.expectProduction,phase==='production','correctness phase mismatch');
|
||||
assert.equal(run?.correctness?.compile?.productionEligible,phase==='production','compile production eligibility mismatch');
|
||||
assert.equal(run?.correctness?.compile?.candidateEnabled,true,'candidate path was not enabled');
|
||||
assert.equal(run?.correctness?.records?.length,correctnessCases.length,'incomplete correctness corpus');
|
||||
for(const record of run.correctness.records){
|
||||
assert.equal(record.audit?.coverageUnknown,0,record.id+' coverage UNKNOWN');
|
||||
assert.equal(record.audit?.numericalUnknown,0,record.id+' numeric UNKNOWN');
|
||||
assert.equal(record.numericComplete,true,record.id+' numeric completion');
|
||||
assert.equal(record.state?.historyReady,true,record.id+' history commit');
|
||||
assert.equal(record.state?.frontierConverged,true,record.id+' frontier convergence');
|
||||
assert.ok((record.state?.frontierMaxDispatchWork||0)<=4000000,record.id+' dispatch work limit');
|
||||
if((record.audit?.operationLimit||0)>0)assert.ok(record.state.frontierIter>=record.state.frontierMinimumIter,record.id+' stopped below pixel-scale iteration floor');
|
||||
assert.equal(gpuErrors(record.diagnostics),0,record.id+' GPU diagnostics');
|
||||
if(record.frontier)assert.equal(record.frontier.gatePassed,true,record.id+' frontier oracle');
|
||||
if(record.activeDirect)assert.equal(record.activeDirect.gatePassed,true,record.id+' Direct active shadow');
|
||||
if(record.activeDeep)assert.equal(record.activeDeep.gatePassed,true,record.id+' Deep active shadow');
|
||||
if(record.certified)assert.equal(record.certified.gatePassed,true,record.id+' certified interior shadow');
|
||||
}
|
||||
assert.equal(run?.stability?.expectProduction,phase==='production','stability phase mismatch');
|
||||
assert.equal(run?.stability?.records?.length,interactionStabilityViews.length,'incomplete interaction corpus');
|
||||
const stability=run.stability.records;
|
||||
assert.equal(stability[0].hashes.metaSha256,stability[2].hashes.metaSha256,'round-trip meta instability');
|
||||
assert.equal(stability[0].hashes.smoothSha256,stability[2].hashes.smoothSha256,'round-trip smooth instability');
|
||||
assert.equal(run?.performance?.records?.length,performanceCases.length,'full performance corpus is required');
|
||||
for(const record of run.performance.records){
|
||||
assert.ok((record.runs?.length||0)>=10,record.id+' requires 10 measured runs');
|
||||
assert.ok(Number.isFinite(record.summary?.recovery?.p50)&&Number.isFinite(record.summary?.recovery?.p95),record.id+' summary missing');
|
||||
}
|
||||
}
|
||||
|
||||
const candidateKeys=new Set();
|
||||
const baselineByAdapter=new Map(bundle.baselineRuns.map(run=>[adapterKey(run),run]));
|
||||
const performance=[];
|
||||
for(const run of bundle.candidateRuns){
|
||||
auditCandidate(run);
|
||||
const key=adapterKey(run);assert.ok(key.replaceAll('|',''),'candidate adapter identity is empty');candidateKeys.add(key);
|
||||
const baseline=baselineByAdapter.get(key);assert.ok(baseline,'missing same-adapter baseline for '+key);
|
||||
const result=evaluateProductionPerformance(run.performance,baseline.performance);assert.equal(result.pass,true,result.failures.join('\n'));
|
||||
performance.push({adapter:key,...result});
|
||||
}
|
||||
assert.ok(candidateKeys.size>=2,'candidate evidence must cover at least two distinct adapters');
|
||||
|
||||
const output={pass:true,phase,adapters:[...candidateKeys],correctnessCases:correctnessCases.length,performanceCases:performanceCases.length,interactionCases:interactionStabilityViews.length,performance};
|
||||
process.stdout.write(JSON.stringify(output,null,2)+'\n');
|
||||
|
|
@ -3,7 +3,8 @@ import re, subprocess, tempfile, json
|
|||
ROOT=Path(__file__).resolve().parents[1]
|
||||
CUR=ROOT/'index.html'
|
||||
OLD=ROOT/'tests'/'KERNEL_HASHES_V24_2_54.json'
|
||||
NEW=ROOT/'tests'/'KERNEL_HASHES_V24_2_55.json'
|
||||
NEW=ROOT/'tests'/'KERNEL_HASHES_V24_3_0.json'
|
||||
CORPUS=ROOT/'tests'/'optimization_webgpu_corpus.mjs'
|
||||
|
||||
def scripts(path): return re.findall(r'<script[^>]*>(.*?)</script>',path.read_text(),re.S)
|
||||
|
||||
|
|
@ -24,9 +25,84 @@ syntax(CUR)
|
|||
old=json.loads(OLD.read_text()); cur=kernels(CUR); expected=json.loads(NEW.read_text())
|
||||
assert cur==expected
|
||||
changed=[k for k,v in old.items() if cur.get(k)!=v]
|
||||
assert changed==['version','FAST_PERTURB_WGSL'], changed
|
||||
assert {'version','DIRECT_ACCURATE_SEED_WGSL','DIRECT_DS_CORRECT_WGSL','FAST_PERTURB_WGSL'}.issubset(changed), changed
|
||||
html=CUR.read_text()
|
||||
assert "version:'24.2.55-no-black-hole-async-recovery'" in html
|
||||
assert CORPUS.exists() and 'runCorrectnessCorpus' in CORPUS.read_text() and 'runPerformanceCorpus' in CORPUS.read_text() and 'runInteractionStabilityCorpus' in CORPUS.read_text()
|
||||
assert "version:'24.3.0-optimized-unknown-pipeline'" in html
|
||||
assert 'if(n>=p.lateThreshold){fieldMeta[out]=pack_unknown' in html
|
||||
assert 'var zr2=DS(0.0,0.0);var zi2=DS(0.0,0.0)' in html
|
||||
assert 'DIRECT_DS_QUEUE_BUILD_WGSL' in html and 'DIRECT_DS_CORRECT_QUEUE_WGSL' in html
|
||||
assert 'accurateQueuedPixels' in html and 'accurateQueueFallbacks' in html
|
||||
assert 'UNKNOWN_STATS_WGSL' in html and 'encodeUnknownStats' in html
|
||||
assert 'encodeDeepBucketHistogram(e' in html and 'encodeQueuedDeepCorrection(e' in html
|
||||
assert 'q.selected===q.enqueued&&q.enqueued===q.dispatchCount&&q.dispatchCount===q.processed' in html
|
||||
assert 'reusePreview' in html and 'numericInFlightBudgetMs' in html
|
||||
assert 'canUseStableReprojection()||fastNeedsExtended(snapshot(),canvas.width))return[finalIter]' in html
|
||||
assert 'const ADAPTIVE_ITER_QUANTUM=64' in html and 'Math.ceil(raw/quantum)*quantum' in html
|
||||
assert 'function pixelPrecisionBits(snap=snapshot(),w=canvas.width,guard=32)' in html
|
||||
assert 'targetBits=pixelPrecisionBits(snap,width,40)' in html and 'fastReferenceBits(snap,w=canvas.width)' in html
|
||||
assert 'const bits=baseBits+attempt*32,a=pixel(s,indices[i],bits),b=pixel(s,indices[i],bits+32)' in html
|
||||
assert 'for(let attempt=0;attempt<4&&!accepted[i];attempt++)' in html
|
||||
assert 'for(let start=0;start<indices.length;start+=chunkSize)' in html
|
||||
assert 'UNRESOLVED_BLACK_MIN_ZOOM_EXP' not in html and 'colorUnresolvedInsteadOfBlack' not in html and 'guardedFastDeep' not in html
|
||||
assert 'this.blaFastDisabled=true;this.blaFastOptIn=false' in html
|
||||
assert 'deep-stable-bootstrap' not in html and 'forceStableDeep' not in html
|
||||
assert 'A FAST frame is not publishable while any numeric UNKNOWN remains' in html
|
||||
assert 'if(initialFailed>0){const mr=await recoverNumericalUnknownTiles' in html
|
||||
assert 'if(numericalFailureCount(stats)>0){const pf=await recoverResidualPrecision' in html
|
||||
assert "if(isFinal){const remaining=numericalFailureCount" in html and 'frameを公開しません' in html
|
||||
assert 'viewRe:snap.re,viewIm:snap.im' in html and 'referenceOriginMatchesView(src,snap)' in html
|
||||
assert 'fastBackgroundDeepOnFailureOnly:true,deepProductionActive:false,deepCorrectionDispatchWork:PIXEL_FRONTIER_WORK' in html
|
||||
assert 'ensureAccuratePipelines' in html and 'ensureCorrectionPipelines' in html
|
||||
assert 'precisionFallbackWorkerSource' in html and 'recoverResidualPrecision' in html
|
||||
assert 'estimatedNetMs' in html and "reason:enabled?'probe-pass':!operationGate?'probe-cost':'probe-net-time'" in html
|
||||
replay=cur['BLA_GPU_FAST_REPLAY_CANDIDATE_WGSL']
|
||||
assert 'fn baseline_from(s0:S,pre:u32)->Result' in replay and 'var anchor=s;loop' in replay
|
||||
assert 'baseline(g,st)' not in replay and replay.count('baseline_from(anchor,st)')==7
|
||||
assert 'anchor=s;}}' in replay and 'baseline_from(anchor,st)' in cur['BLA_GPU_FAST_FRAME_WGSL']
|
||||
assert 'SYMMETRY_COPY_WGSL' in html and 'canUseRealAxisSymmetry' in html and 'encodeSymmetryCopy' in html
|
||||
assert 'FAILURE_TILE_MAP_WGSL' in html and 'readNumericalFailureTiles' in html
|
||||
assert "tileReferencePool=Array.from({length:3}" in html and 'Promise.all(batch.map' in html
|
||||
assert 'if(p.key===key)return p.promise' in html and 'prefetchFinalReference' in html
|
||||
assert 'this.exportWs=[]' in html and 'exportRingDepth(tile=this.exportTileSize())' in html
|
||||
assert 'Promise.allSettled(batch.map(item=>item.promise))' in html and 'if(failed)throw failed.reason' in html and 'performance.now()-lastYield<24' in html
|
||||
assert 'await png.rows(band);await new Promise(requestAnimationFrame)' not in html
|
||||
assert 'frameReadback(kind,size)' in html and "this.frameReadback('unknown-stats'" in html
|
||||
stats_readback=html[html.index('async readUnresolvedStats'):html.index('async readUnresolved(){')]
|
||||
assert 'destroy(r)' not in stats_readback
|
||||
assert 'cachedBindGroup(pipeline,entries)' in html and 'cachedTextureView(texture)' in html
|
||||
assert 'this.cachedBindGroup(this.direct' in html and 'this.cachedBindGroup(this.present' in html
|
||||
history_commit=html[html.index('commitHistory(view='):html.index('invalidateHistory(){')]
|
||||
assert 'f.history=f.front' in history_commit and 'copyTextureToTexture' not in history_commit
|
||||
assert 'colorTarget(f=this.frame)' in html and 'spare:history' in html
|
||||
assert 'ACTIVE_PREPARE_WGSL' in html and 'DIRECT_ACTIVE_CONTINUE_WGSL' in html
|
||||
assert 'DEEP_ACTIVE_CONTINUE_WGSL' in html and 'PERTURB_CERTIFIED_INTERIOR_WGSL' in html
|
||||
assert 'runDirectActiveShadow' in html and 'dispatchWorkgroupsIndirect(indirect,0)' in html
|
||||
assert 'direct-active-shadow-resume' in html and 'resumedFromPreview:previewIter>0' in html
|
||||
assert 'runDeepActiveShadow' in html and 'deep-active-shadow-resume' in html
|
||||
assert 'deep-active-compare-shadow' in html and 'runtime.deepActiveShadowLatest=result' in html
|
||||
assert 'computeDeepActiveFrame' in html and 'workPerDispatch=PIXEL_FRONTIER_WORK,maxPassesPerSubmit=1' in html
|
||||
assert 'const workBudget=deep?4000000:48000000' in html
|
||||
assert 'maxPixels=Math.max(1,Math.floor(4000000/Math.max(1,iter))),tileW=Math.min(f.w,maxPixels)' in html
|
||||
assert 'PIXEL_FRONTIER_PRODUCTION=false,PIXEL_FRONTIER_WORK=4000000,PIXEL_FRONTIER_MAX_ITER=150000' in html
|
||||
assert 'PIXEL_FRONTIER_ENABLED=PIXEL_FRONTIER_PRODUCTION||PIXEL_FRONTIER_CANDIDATE' in html
|
||||
assert 'function operationLimitFrontier(meta,w,h)' in html and 'refineOperationLimitIndices' in html
|
||||
assert 'function pixelFrontierIterationFloor(snap,w,initialIter)' in html and 'iter>=minimumIter&&stableRounds>=2' in html
|
||||
assert 'pixel frontier queue invariant failed' in html and 'compareCurrentToFrontierBaseline' in html
|
||||
assert 'correctUnknownFrame(snap,iter,token,referencePixel,numericalFailureCount(stats))' in html
|
||||
assert 'ensureDeepActiveWorkspace' in html and 'return this.computeDeepActiveFrame(snap,iter,token,forceStrict,referencePixel)' not in html
|
||||
assert 'return this.computePerturbFrameTiled(snap,iter,true,token,forceStrict,referencePixel,false,colorStyle,colorKey)' in html
|
||||
assert 'states[local]=DeepState' in html and 'let out=p.outputBase+(local/p.tileW)*p.outputStride' in html
|
||||
assert 'state.gpuInitFailed=true;markDirty(false);setTimeout' in html
|
||||
assert 'runCertifiedInteriorShadow' in html and 'gpu.provenIndices,FIELD_INTERIOR_PROVEN' in html
|
||||
assert 'falsePositive===0&&inconclusive===0' in html and 'oracleBits:[oracleBits,oracleBits+32]' in html
|
||||
assert 'waitForPrimary(' in html and 'waitForFinal(' in html and 'waitForNumericComplete(' in html
|
||||
assert 'fieldHashes()' in html and 'readFieldAll()' in html
|
||||
assert 'generationMetrics:[]' in html and 'primaryNumericalFailures' in html
|
||||
assert 'numericQuiescentMs' in html and 'historyCommitMs' in html
|
||||
recovery=html[html.index('async function recoverNumericalUnknownTiles'):html.index('async function recoverResidualPrecision')]
|
||||
assert 'readNumericalFailureTiles' in recovery and 'const currentMeta=await r.readMetaAll()' in recovery
|
||||
assert 'Uint32Array.from(tileIndices)' in recovery
|
||||
assert 'p.unknownOnly==2u && reason!=0u' in html
|
||||
assert "fast-coverage-repair-and-color" in html
|
||||
assert 'reprojectionSafe(rawHistory,2.25,.45)' in html
|
||||
|
|
@ -35,4 +111,4 @@ assert 'numericFrameComplete()' in html
|
|||
assert "requestBuild({ctx,snap,iter,width,height,refPixel,safety=1/64})" in html
|
||||
assert "type:'build'" in html and 'buildOnly=d.type===\'build\'' in html
|
||||
assert not list(ROOT.glob('index.baseline*.html'))
|
||||
print('PASS: syntax; only FAST repair gate changed in production kernels; coverage repair, broad temporal fill, async recovery, build-only BLA prep, single HTML')
|
||||
print('PASS: syntax; bounded Accurate seed; DS square reuse; shared UNKNOWN stats; sparse correction invariants; preview/reference reuse; bounded GPU bursts')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue